From 8b4e98ea6d0e2cf0be06c1efd68da378e90ace27 Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Sun, 2 Jun 2002 02:41:38 -0700 Subject: [PATCH] 2.5.19 IDE 78 - Move ide_fixstring() from ide.c to probe.c, since this is the place, where it's most used. - Remove GET_STAT() - it's not used any longer. - Remove last parameter of ide_error. Rename it to ata_error(). - Don't use ide_fixstring in qd65xx.c host chip driver. The model name is already fixed in probe.c. - Invent ata_irq_enable() for the handling of the trice nIEN bit of the control register. Consistently use ch->intrproc method every time we toggle this bit. This simply wasn't the case before! - Disable interrupts on a previous channel only when we share them indeed. - Eliminate simple drive command handling function drive_cmd. - Simplify the ioctl handler. Move it to ioctl, since that's the only place where it's actually used. --- include/linux/ide.h | 63 +++++++++++++++++------------------------------------ 1 file changed, 20 insertions(+), 43 deletions(-) (limited to 'include') diff --git a/include/linux/ide.h b/include/linux/ide.h index f9b112fa19b2..7fe98cfd802c 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -38,11 +38,6 @@ # define SUPPORT_SLOW_DATA_PORTS 1 /* 0 to reduce kernel size */ #endif -/* Right now this is only needed by a promise controlled. - */ -#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */ -# define OK_TO_RESET_CONTROLLER 0 /* 0 for use with AH2372A/B interface */ -#endif #ifndef FANCY_STATUS_DUMPS /* 1 for human-readable drive errors */ # define FANCY_STATUS_DUMPS 1 /* 0 to reduce kernel size */ #endif @@ -73,21 +68,22 @@ typedef unsigned char byte; /* used everywhere */ */ enum { - IDE_DATA_OFFSET = 0, - IDE_ERROR_OFFSET = 1, - IDE_NSECTOR_OFFSET = 2, - IDE_SECTOR_OFFSET = 3, - IDE_LCYL_OFFSET = 4, - IDE_HCYL_OFFSET = 5, - IDE_SELECT_OFFSET = 6, - IDE_STATUS_OFFSET = 7, - IDE_CONTROL_OFFSET = 8, - IDE_IRQ_OFFSET = 9, - IDE_NR_PORTS = 10 + IDE_DATA_OFFSET = 0, + IDE_ERROR_OFFSET = 1, + IDE_FEATURE_OFFSET = 1, + IDE_NSECTOR_OFFSET = 2, + IDE_SECTOR_OFFSET = 3, + IDE_LCYL_OFFSET = 4, + IDE_HCYL_OFFSET = 5, + IDE_SELECT_OFFSET = 6, + IDE_STATUS_OFFSET = 7, + IDE_COMMAND_OFFSET = 7, + IDE_CONTROL_OFFSET = 8, + IDE_ALTSTATUS_OFFSET = 8, + IDE_IRQ_OFFSET = 9, + IDE_NR_PORTS = 10 }; -#define IDE_FEATURE_OFFSET IDE_ERROR_OFFSET -#define IDE_COMMAND_OFFSET IDE_STATUS_OFFSET #define IDE_DATA_REG (drive->channel->io_ports[IDE_DATA_OFFSET]) #define IDE_ERROR_REG (drive->channel->io_ports[IDE_ERROR_OFFSET]) @@ -96,20 +92,16 @@ enum { #define IDE_LCYL_REG (drive->channel->io_ports[IDE_LCYL_OFFSET]) #define IDE_HCYL_REG (drive->channel->io_ports[IDE_HCYL_OFFSET]) #define IDE_SELECT_REG (drive->channel->io_ports[IDE_SELECT_OFFSET]) -#define IDE_STATUS_REG (drive->channel->io_ports[IDE_STATUS_OFFSET]) -#define IDE_CONTROL_REG (drive->channel->io_ports[IDE_CONTROL_OFFSET]) +#define IDE_COMMAND_REG (drive->channel->io_ports[IDE_STATUS_OFFSET]) #define IDE_IRQ_REG (drive->channel->io_ports[IDE_IRQ_OFFSET]) #define IDE_FEATURE_REG IDE_ERROR_REG -#define IDE_COMMAND_REG IDE_STATUS_REG -#define IDE_ALTSTATUS_REG IDE_CONTROL_REG #define IDE_IREASON_REG IDE_NSECTOR_REG #define IDE_BCOUNTL_REG IDE_LCYL_REG #define IDE_BCOUNTH_REG IDE_HCYL_REG #define GET_ERR() IN_BYTE(IDE_ERROR_REG) -#define GET_STAT() IN_BYTE(IDE_STATUS_REG) -#define GET_ALTSTAT() IN_BYTE(IDE_CONTROL_REG) +#define GET_ALTSTAT() IN_BYTE(drive->channel->io_ports[IDE_CONTROL_OFFSET]) #define GET_FEAT() IN_BYTE(IDE_NSECTOR_REG) #define BAD_R_STAT (BUSY_STAT | ERR_STAT) @@ -346,8 +338,6 @@ struct ata_device { byte scsi; /* 0=default, 1=skip current ide-subdriver for ide-scsi emulation */ select_t select; /* basic drive/head select reg value */ - - u8 ctl; /* "normal" value for IDE_CONTROL_REG */ u8 status; /* last retrived status value for device */ byte ready_stat; /* min status value for drive ready */ @@ -653,25 +643,10 @@ extern void ide_set_handler(struct ata_device *drive, ata_handler_t handler, */ extern u8 ide_dump_status(struct ata_device *, struct request *rq, const char *, u8); -extern ide_startstop_t ide_error(struct ata_device *, struct request *rq, - const char *, byte); +extern ide_startstop_t ata_error(struct ata_device *, struct request *rq, const char *); -/* - * ide_fixstring() cleans up and (optionally) byte-swaps a text string, - * removing leading/trailing blanks and compressing internal blanks. - * It is primarily used to tidy up the model name/number fields as - * returned by the WIN_[P]IDENTIFY commands. - */ -void ide_fixstring(byte *s, const int bytecount, const int byteswap); +extern void ide_fixstring(char *s, const int bytecount, const int byteswap); -/* - * This routine busy-waits for the drive status to be not "busy". - * It then checks the status for all of the "good" bits and none - * of the "bad" bits, and if all is okay it returns 0. All other - * cases return 1 after doing "*startstop = ide_error()", and the - * caller should return the updated value of "startstop" in this case. - * "startstop" is unchanged when the function returns 0; - */ extern int ide_wait_stat(ide_startstop_t *, struct ata_device *, struct request *rq, byte, byte, unsigned long); @@ -896,5 +871,7 @@ extern int drive_is_ready(struct ata_device *drive); extern void ata_select(struct ata_device *, unsigned long); extern void ata_mask(struct ata_device *); extern int ata_status(struct ata_device *, u8, u8); +extern int ata_irq_enable(struct ata_device *, int); +extern void ata_reset(struct ata_channel *); #endif -- cgit v1.2.3 From b6e6f1752e3eec4375acd890b38b99b17ff54992 Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Sun, 2 Jun 2002 02:41:59 -0700 Subject: [PATCH] [PATCH} 2.5.19 IDE 79 - Fix typo in sparc_v9 code, in ns87415, just introduced. - Eliminate unnecessary struct hd_drive_hob_hdr those are in reality precisely the same registers as usual. - Eliminate control_t, nowhere used type. - Unfold ide_init_drive_cmd() at the places where it's used. This makes obvious that REQ_DRIVE_CMD gets only used on the ioctl command path. --- drivers/ide/device.c | 14 ++++ drivers/ide/ide-cd.c | 7 +- drivers/ide/ide-disk.c | 3 - drivers/ide/ide-floppy.c | 17 ++--- drivers/ide/ide-tape.c | 19 ++--- drivers/ide/ide-taskfile.c | 165 +++--------------------------------------- drivers/ide/ide.c | 42 +++++------ drivers/ide/ioctl.c | 175 ++++++++++++++++++++++++++++++++++++--------- drivers/ide/ns87415.c | 2 +- drivers/scsi/ide-scsi.c | 19 ++--- include/linux/hdreg.h | 13 +--- include/linux/ide.h | 46 +++--------- 12 files changed, 226 insertions(+), 296 deletions(-) (limited to 'include') diff --git a/drivers/ide/device.c b/drivers/ide/device.c index 9fd239445538..652d8d49a8d9 100644 --- a/drivers/ide/device.c +++ b/drivers/ide/device.c @@ -142,4 +142,18 @@ void ata_reset(struct ata_channel *ch) EXPORT_SYMBOL(ata_reset); +/* + * Output a complete register file. + */ +void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) +{ + struct ata_channel *ch = drive->channel; + + OUT_BYTE(rf->feature, ch->io_ports[IDE_FEATURE_OFFSET]); + OUT_BYTE(rf->sector_count, ch->io_ports[IDE_NSECTOR_OFFSET]); + OUT_BYTE(rf->sector_number, ch->io_ports[IDE_SECTOR_OFFSET]); + OUT_BYTE(rf->low_cylinder, ch->io_ports[IDE_LCYL_OFFSET]); + OUT_BYTE(rf->high_cylinder, ch->io_ports[IDE_HCYL_OFFSET]); +} + MODULE_LICENSE("GPL"); diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 2ac1e11b1377..7ef13e954b38 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -535,7 +535,7 @@ static void cdrom_queue_request_sense(struct ata_device *drive, /* stuff the sense request in front of our current request */ rq = &info->request_sense_request; - ide_init_drive_cmd(rq); + memset(rq, 0, sizeof(*rq)); rq->cmd[0] = GPCMD_REQUEST_SENSE; rq->cmd[4] = pc->buflen; rq->flags = REQ_SENSE; @@ -1389,9 +1389,8 @@ int cdrom_queue_packet_command(struct ata_device *drive, unsigned char *cmd, /* Start of retry loop. */ do { - ide_init_drive_cmd(&rq); + memset(&rq, 0, sizeof(rq)); memcpy(rq.cmd, cmd, CDROM_PACKET_SIZE); - rq.flags = REQ_PC; /* FIXME --mdcki */ @@ -2276,7 +2275,7 @@ int ide_cdrom_reset (struct cdrom_device_info *cdi) struct request req; int ret; - ide_init_drive_cmd(&req); + memset(&req, 0, sizeof(req)); req.flags = REQ_SPECIAL; ret = ide_do_drive_cmd(drive, &req, ide_wait); diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index 19578f2f96de..f0bbcb993e85 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -264,8 +264,6 @@ static ide_startstop_t lba48_do_request(struct ata_device *drive, struct request args.hobfile.high_cylinder = (block >>= 8); /* hi lba */ args.hobfile.device_head = drive->select.all; - args.hobfile.control = 0x80; - args.taskfile.command = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG @@ -728,7 +726,6 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req) args.hobfile.high_cylinder = (addr_req >>= 8); args.hobfile.device_head = 0x40; - args.hobfile.control = 0x80; args.handler = task_no_data_intr; /* submit command request */ diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index d4f3c10e555b..386c3c3ee61f 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -712,10 +712,10 @@ static void idefloppy_update_buffers(struct ata_device *drive, struct request *r static void idefloppy_queue_pc_head(struct ata_device *drive, struct atapi_packet_command *pc, struct request *rq) { - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); + rq->flags = IDEFLOPPY_RQ; /* FIXME: --mdcki */ rq->buffer = (char *) pc; - rq->flags = IDEFLOPPY_RQ; (void) ide_do_drive_cmd (drive, rq, ide_preempt); } @@ -1065,10 +1065,10 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque #endif ata_irq_enable(drive, 1); - OUT_BYTE (dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ - OUT_BYTE (bcount.b.high,IDE_BCOUNTH_REG); - OUT_BYTE (bcount.b.low,IDE_BCOUNTL_REG); - OUT_BYTE (drive->select.all,IDE_SELECT_REG); + OUT_BYTE(dma_ok ? 1:0,IDE_FEATURE_REG); /* Use PIO/DMA */ + OUT_BYTE(bcount.b.high,IDE_BCOUNTH_REG); + OUT_BYTE(bcount.b.low,IDE_BCOUNTL_REG); + OUT_BYTE(drive->select.all,IDE_SELECT_REG); #ifdef CONFIG_BLK_DEV_IDEDMA if (dma_ok) { /* Begin DMA, if necessary */ @@ -1271,11 +1271,12 @@ static int idefloppy_queue_pc_tail(struct ata_device *drive, struct atapi_packet { struct request rq; - ide_init_drive_cmd (&rq); + memset(&rq, 0, sizeof(rq)); /* FIXME: --mdcki */ rq.buffer = (char *) pc; rq.flags = IDEFLOPPY_RQ; - return ide_do_drive_cmd (drive, &rq, ide_wait); + + return ide_do_drive_cmd(drive, &rq, ide_wait); } /* diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 21fe89734a34..16c8bea8eb27 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1921,7 +1921,7 @@ static void idetape_create_request_sense_cmd(struct atapi_packet_command *pc) */ static void idetape_queue_pc_head(struct ata_device *drive, struct atapi_packet_command *pc, struct request *rq) { - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); rq->buffer = (char *) pc; rq->flags = IDETAPE_PC_RQ1; ide_do_drive_cmd(drive, rq, ide_preempt); @@ -3153,7 +3153,7 @@ static int __idetape_queue_pc_tail(struct ata_device *drive, struct atapi_packet { struct request rq; - ide_init_drive_cmd (&rq); + memset(&rq, 0, sizeof(rq)); /* FIXME: --mdcki */ rq.buffer = (char *) pc; rq.flags = IDETAPE_PC_RQ1; @@ -3414,17 +3414,17 @@ static int idetape_queue_rw_tail(struct ata_device *drive, int cmd, int blocks, #if IDETAPE_DEBUG_LOG if (tape->debug_level >= 2) printk (KERN_INFO "ide-tape: idetape_queue_rw_tail: cmd=%d\n",cmd); -#endif /* IDETAPE_DEBUG_LOG */ +#endif #if IDETAPE_DEBUG_BUGS if (idetape_pipeline_active (tape)) { printk (KERN_ERR "ide-tape: bug: the pipeline is active in idetape_queue_rw_tail\n"); return (0); } -#endif /* IDETAPE_DEBUG_BUGS */ +#endif - ide_init_drive_cmd (&rq); - rq.bio = bio; + memset(&rq, 0, sizeof(rq)); rq.flags = cmd; + rq.bio = bio; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; if (tape->onstream) @@ -3472,7 +3472,7 @@ static void idetape_onstream_read_back_buffer(struct ata_device *drive) printk(KERN_INFO "ide-tape: %s: read back logical block %d, data %x %x %x %x\n", tape->name, logical_blk_num, *p++, *p++, *p++, *p++); #endif rq = &stage->rq; - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); rq->flags = IDETAPE_WRITE_RQ; rq->sector = tape->first_frame_position; rq->nr_sectors = rq->current_nr_sectors = tape->capabilities.ctl; @@ -3748,7 +3748,7 @@ static int idetape_add_chrdev_write_request(struct ata_device *drive, int blocks } } rq = &new_stage->rq; - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); rq->flags = IDETAPE_WRITE_RQ; rq->sector = tape->first_frame_position; /* Doesn't actually matter - We always assume sequential access */ rq->nr_sectors = rq->current_nr_sectors = blocks; @@ -3938,7 +3938,8 @@ static int idetape_initiate_read(struct ata_device *drive, int max_stages) } if (tape->restart_speed_control_req) idetape_restart_speed_control(drive); - ide_init_drive_cmd (&rq); + + memset(&rq, 0, sizeof(rq)); rq.flags = IDETAPE_READ_RQ; rq.sector = tape->first_frame_position; rq.nr_sectors = rq.current_nr_sectors = blocks; diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 82f6fbc69433..6ba395ef4c80 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -314,7 +314,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, struct ata_taskfile *args, struct request *rq) { struct hd_driveid *id = drive->id; - u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF; /* (ks/hs): Moved to start, do not use for multiple out commands */ if (args->handler != task_mulout_intr) { @@ -322,25 +321,16 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, ata_mask(drive); } - if ((id->command_set_2 & 0x0400) && - (id->cfs_enable_2 & 0x0400) && - (drive->addressing == 1)) { - OUT_BYTE(args->hobfile.feature, IDE_FEATURE_REG); - OUT_BYTE(args->hobfile.sector_count, IDE_NSECTOR_REG); - OUT_BYTE(args->hobfile.sector_number, IDE_SECTOR_REG); - OUT_BYTE(args->hobfile.low_cylinder, IDE_LCYL_REG); - OUT_BYTE(args->hobfile.high_cylinder, IDE_HCYL_REG); - } + if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) && + (drive->addressing == 1)) + ata_out_regfile(drive, &args->hobfile); - OUT_BYTE(args->taskfile.feature, IDE_FEATURE_REG); - OUT_BYTE(args->taskfile.sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - OUT_BYTE(args->taskfile.sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - OUT_BYTE(args->taskfile.low_cylinder, IDE_LCYL_REG); - OUT_BYTE(args->taskfile.high_cylinder, IDE_HCYL_REG); + ata_out_regfile(drive, &args->taskfile); - OUT_BYTE((args->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG); + { + u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF; + OUT_BYTE((args->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG); + } if (args->handler != NULL) { /* This is apparently supposed to reset the wait timeout for @@ -361,8 +351,7 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, } else { /* * FIXME: this is a gross hack, need to unify tcq dma proc and - * regular dma proc -- basically split stuff that needs to act - * on a request from things like ide_dma_check etc. + * regular dma proc. */ if (!drive->using_dma) @@ -760,15 +749,6 @@ void ide_cmd_type_parser(struct ata_taskfile *args) } } -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -void ide_init_drive_cmd(struct request *rq) -{ - memset(rq, 0, sizeof(*rq)); - rq->flags = REQ_DRIVE_CMD; -} - /* * This function issues a special IDE device request onto the request queue. * @@ -849,139 +829,12 @@ int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args) return ide_do_drive_cmd(drive, &rq, ide_wait); } -/* - * Implement generic ioctls invoked from userspace to imlpement specific - * functionality. - * - * Unfortunately every single low level programm out there is using this - * interface. - */ - -/* - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ -static int set_transfer(struct ata_device *drive, struct ata_taskfile *args) -{ - if ((args->taskfile.command == WIN_SETFEATURES) && - (args->taskfile.sector_number >= XFER_SW_DMA_0) && - (args->taskfile.feature == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) - return 1; - - return 0; -} - -/* - * Verify that we are doing an approved SETFEATURES_XFER with respect - * to the hardware being able to support request. Since some hardware - * can improperly report capabilties, we check to see if the host adapter - * in combination with the device (usually a disk) properly detect - * and acknowledge each end of the ribbon. - */ -static int ata66_check(struct ata_device *drive, struct ata_taskfile *args) -{ - if ((args->taskfile.command == WIN_SETFEATURES) && - (args->taskfile.sector_number > XFER_UDMA_2) && - (args->taskfile.feature == SETFEATURES_XFER)) { - if (!drive->channel->udma_four) { - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->channel->name); - return 1; - } -#ifndef CONFIG_IDEDMA_IVB - if ((drive->id->hw_config & 0x6000) == 0) { -#else - if (((drive->id->hw_config & 0x2000) == 0) || - ((drive->id->hw_config & 0x4000) == 0)) { -#endif - printk("%s: Speed warnings UDMA 3/4/5 is not functional.\n", drive->name); - return 1; - } - } - return 0; -} - -int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg) -{ - int err = 0; - u8 vals[4]; - u8 *argbuf = vals; - u8 pio = 0; - int argsize = 4; - struct ata_taskfile args; - struct request rq; - - ide_init_drive_cmd(&rq); - - /* Wait for drive ready. - */ - if (!arg) - return ide_do_drive_cmd(drive, &rq, ide_wait); - - /* Second phase. - */ - if (copy_from_user(vals, (void *)arg, 4)) - return -EFAULT; - - args.taskfile.feature = vals[2]; - args.taskfile.sector_count = vals[3]; - args.taskfile.sector_number = vals[1]; - args.taskfile.low_cylinder = 0x00; - args.taskfile.high_cylinder = 0x00; - args.taskfile.device_head = 0x00; - args.taskfile.command = vals[0]; - - if (vals[3]) { - argsize = 4 + (SECTOR_WORDS * 4 * vals[3]); - argbuf = kmalloc(argsize, GFP_KERNEL); - if (argbuf == NULL) - return -ENOMEM; - memcpy(argbuf, vals, 4); - memset(argbuf + 4, 0, argsize - 4); - } - - /* Always make sure the transfer reate has been setup. - * FIXME: what about setting up the drive with ->tuneproc? - */ - if (set_transfer(drive, &args)) { - pio = vals[1]; - if (ata66_check(drive, &args)) - goto abort; - } - - /* Issue ATA command and wait for completion. - */ - rq.buffer = argbuf; - err = ide_do_drive_cmd(drive, &rq, ide_wait); - - if (!err && pio) { - /* active-retuning-calls future */ - /* FIXME: what about the setup for the drive?! */ - if (drive->channel->speedproc) - drive->channel->speedproc(drive, pio); - } - -abort: - if (copy_to_user((void *)arg, argbuf, argsize)) - err = -EFAULT; - - if (argsize > 4) - kfree(argbuf); - - return err; -} - EXPORT_SYMBOL(drive_is_ready); EXPORT_SYMBOL(ata_read); EXPORT_SYMBOL(ata_write); EXPORT_SYMBOL(ata_taskfile); EXPORT_SYMBOL(recal_intr); EXPORT_SYMBOL(task_no_data_intr); -EXPORT_SYMBOL(ide_init_drive_cmd); EXPORT_SYMBOL(ide_do_drive_cmd); EXPORT_SYMBOL(ide_raw_taskfile); EXPORT_SYMBOL(ide_cmd_type_parser); -EXPORT_SYMBOL(ide_cmd_ioctl); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 6f35f20f2111..45e5737e112e 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -672,19 +672,6 @@ static ide_startstop_t drive_cmd_intr(struct ata_device *drive, struct request * return ide_stopped; } -/* - * Issue a simple drive command. The drive must be selected beforehand. - */ -static void drive_cmd(struct ata_device *drive, u8 cmd, u8 nsect) -{ - ide_set_handler(drive, drive_cmd_intr, WAIT_CMD, NULL); - ata_irq_enable(drive, 1); - ata_mask(drive); - OUT_BYTE(nsect, IDE_NSECTOR_REG); - OUT_BYTE(cmd, IDE_COMMAND_REG); -} - - /* * Busy-wait for the drive status to be not "busy". Check then the status for * all of the "good" bits and none of the "bad" bits, and if all is okay it @@ -815,21 +802,26 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r #ifdef DEBUG printk("%s: DRIVE_CMD ", drive->name); printk("cmd=0x%02x ", args[0]); - printk("sc=0x%02x ", args[1]); - printk("fr=0x%02x ", args[2]); - printk("xx=0x%02x\n", args[3]); + printk(" sc=0x%02x ", args[1]); + printk(" fr=0x%02x ", args[2]); + printk(" xx=0x%02x\n", args[3]); #endif + ide_set_handler(drive, drive_cmd_intr, WAIT_CMD, NULL); + ata_irq_enable(drive, 1); + ata_mask(drive); if (args[0] == WIN_SMART) { - OUT_BYTE(0x4f, IDE_LCYL_REG); - OUT_BYTE(0xc2, IDE_HCYL_REG); - OUT_BYTE(args[2],IDE_FEATURE_REG); - OUT_BYTE(args[1],IDE_SECTOR_REG); - drive_cmd(drive, args[0], args[3]); - - return ide_started; + struct hd_drive_task_hdr regfile; + regfile.feature = args[2]; + regfile.sector_count = args[3]; + regfile.sector_number = args[1]; + regfile.low_cylinder = 0x4f; + regfile.high_cylinder = 0xc2; + ata_out_regfile(drive, ®file); + } else { + OUT_BYTE(args[2], IDE_FEATURE_REG); + OUT_BYTE(args[1], IDE_NSECTOR_REG); } - OUT_BYTE(args[2],IDE_FEATURE_REG); - drive_cmd(drive, args[0], args[1]); + OUT_BYTE(args[0], IDE_COMMAND_REG); return ide_started; } diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c index 4a8f14976341..b2128238aeae 100644 --- a/drivers/ide/ioctl.c +++ b/drivers/ide/ioctl.c @@ -32,6 +32,119 @@ #include "ioctl.h" +/* + * Implement generic ioctls invoked from userspace to imlpement specific + * functionality. + * + * Unfortunately every single low level programm out there is using this + * interface. + */ +static int cmd_ioctl(struct ata_device *drive, unsigned long arg) +{ + int err = 0; + u8 vals[4]; + u8 *argbuf = vals; + u8 pio = 0; + int argsize = 4; + struct ata_taskfile args; + struct request rq; + + memset(&rq, 0, sizeof(rq)); + rq.flags = REQ_DRIVE_CMD; + + /* If empty parameter file - wait for drive ready. + */ + if (!arg) + return ide_do_drive_cmd(drive, &rq, ide_wait); + + /* Second phase. + */ + if (copy_from_user(vals, (void *)arg, 4)) + return -EFAULT; + + args.taskfile.feature = vals[2]; + args.taskfile.sector_count = vals[3]; + args.taskfile.sector_number = vals[1]; + args.taskfile.low_cylinder = 0x00; + args.taskfile.high_cylinder = 0x00; + args.taskfile.device_head = 0x00; + args.taskfile.command = vals[0]; + + if (vals[3]) { + argsize = 4 + (SECTOR_WORDS * 4 * vals[3]); + argbuf = kmalloc(argsize, GFP_KERNEL); + if (argbuf == NULL) + return -ENOMEM; + memcpy(argbuf, vals, 4); + memset(argbuf + 4, 0, argsize - 4); + } + + /* + * Always make sure the transfer reate has been setup. + * + * FIXME: what about setting up the drive with ->tuneproc? + * + * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. + * 1 : Safe to update drive->id DMA registers. + * 0 : OOPs not allowed. + */ + if ((args.taskfile.command == WIN_SETFEATURES) && + (args.taskfile.sector_number >= XFER_SW_DMA_0) && + (args.taskfile.feature == SETFEATURES_XFER) && + (drive->id->dma_ultra || + drive->id->dma_mword || + drive->id->dma_1word)) { + pio = vals[1]; + /* + * Verify that we are doing an approved SETFEATURES_XFER with + * respect to the hardware being able to support request. + * Since some hardware can improperly report capabilties, we + * check to see if the host adapter in combination with the + * device (usually a disk) properly detect and acknowledge each + * end of the ribbon. + */ + if (args.taskfile.sector_number > XFER_UDMA_2) { + if (!drive->channel->udma_four) { + printk(KERN_WARNING "%s: Speed warnings UDMA > 2 is not functional.\n", + drive->channel->name); + goto abort; + } +#ifndef CONFIG_IDEDMA_IVB + if (!(drive->id->hw_config & 0x6000)) +#else + if (!(drive->id->hw_config & 0x2000) || + !(drive->id->hw_config & 0x4000)) +#endif + { + printk(KERN_WARNING "%s: Speed warnings UDMA > 2 is not functional.\n", + drive->name); + goto abort; + } + } + } + + /* Issue ATA command and wait for completion. + */ + rq.buffer = argbuf; + err = ide_do_drive_cmd(drive, &rq, ide_wait); + + if (!err && pio) { + /* active-retuning-calls future */ + /* FIXME: what about the setup for the drive?! */ + if (drive->channel->speedproc) + drive->channel->speedproc(drive, pio); + } + +abort: + if (copy_to_user((void *)arg, argbuf, argsize)) + err = -EFAULT; + + if (argsize > 4) + kfree(argbuf); + + return err; +} + /* * NOTE: Due to ridiculous coding habbits in the hdparm utility we have to * always return unsigned long in case we are returning simple values. @@ -40,7 +153,7 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned { unsigned int major, minor; struct ata_device *drive; - struct request rq; +// struct request rq; kdev_t dev; dev = inode->i_rdev; @@ -50,7 +163,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned if ((drive = get_info_ptr(inode->i_rdev)) == NULL) return -ENODEV; - /* Contrary to popular beleve we disallow even the reading of the ioctl * values for users which don't have permission too. We do this becouse * such information could be used by an attacker to deply a simple-user @@ -61,7 +173,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned if (!capable(CAP_SYS_ADMIN)) return -EACCES; - ide_init_drive_cmd(&rq); switch (cmd) { case HDIO_GET_32BIT: { unsigned long val = drive->channel->io_32bit; @@ -96,7 +207,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned /* FIXME: we can see that tuneproc whould do the * locking!. */ - if (ide_spin_wait_hwgroup(drive)) return -EBUSY; @@ -114,7 +224,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned return 0; } - case HDIO_SET_UNMASKINTR: if (arg < 0 || arg > 1) return -EINVAL; @@ -202,9 +311,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned return 0; } - case BLKRRPART: /* Re-read partition tables */ - return ata_revalidate(inode->i_rdev); - case HDIO_GET_IDENTITY: if (minor(inode->i_rdev) & PARTN_MASK) return -EINVAL; @@ -222,12 +328,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned drive->atapi_overlap << IDE_NICE_ATAPI_OVERLAP, (long *) arg); - case HDIO_DRIVE_CMD: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; - - return ide_cmd_ioctl(drive, arg); - case HDIO_SET_NICE: if (arg != (arg & ((1 << IDE_NICE_DSC_OVERLAP)))) return -EPERM; @@ -241,6 +341,34 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned return 0; + case HDIO_GET_BUSSTATE: + if (put_user(drive->channel->bus_state, (long *)arg)) + return -EFAULT; + + return 0; + + case HDIO_SET_BUSSTATE: + if (drive->channel->busproc) + drive->channel->busproc(drive, (int)arg); + + return 0; + + case HDIO_DRIVE_CMD: + if (!capable(CAP_SYS_RAWIO)) + return -EACCES; + + return cmd_ioctl(drive, arg); + + /* + * uniform packet command handling + */ + case CDROMEJECT: + case CDROMCLOSETRAY: + return block_ioctl(inode->i_bdev, cmd, arg); + + case BLKRRPART: /* Re-read partition tables */ + return ata_revalidate(inode->i_rdev); + case BLKGETSIZE: case BLKGETSIZE64: case BLKROSET: @@ -254,25 +382,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned case BLKBSZSET: return blk_ioctl(inode->i_bdev, cmd, arg); - /* - * uniform packet command handling - */ - case CDROMEJECT: - case CDROMCLOSETRAY: - return block_ioctl(inode->i_bdev, cmd, arg); - - case HDIO_GET_BUSSTATE: - if (put_user(drive->channel->bus_state, (long *)arg)) - return -EFAULT; - - return 0; - - case HDIO_SET_BUSSTATE: - if (drive->channel->busproc) - drive->channel->busproc(drive, (int)arg); - - return 0; - /* Now check whatever this particular ioctl has a device type * specific implementation. */ diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 1afd957b904e..0f50038017e2 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -193,7 +193,7 @@ static void __init ide_init_ns87415(struct ata_channel *hwif) * XXX: Reset the device, if we don't it will not respond * to select properly during first probe. */ - ata_reset(struct ata_channel *hwif); + ata_reset(hwif); #endif } diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index cf6b27fc347a..e2292cd43325 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -412,9 +412,9 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request ata_select(drive, 10); ata_irq_enable(drive, 1); - OUT_BYTE (dma_ok,IDE_FEATURE_REG); - OUT_BYTE (bcount >> 8,IDE_BCOUNTH_REG); - OUT_BYTE (bcount & 0xff,IDE_BCOUNTL_REG); + OUT_BYTE(dma_ok,IDE_FEATURE_REG); + OUT_BYTE(bcount >> 8,IDE_BCOUNTH_REG); + OUT_BYTE(bcount & 0xff,IDE_BCOUNTL_REG); if (dma_ok) { set_bit(PC_DMA_IN_PROGRESS, &pc->flags); @@ -662,17 +662,20 @@ static int idescsi_queue(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)) } } - ide_init_drive_cmd (rq); + memset(rq, 0, sizeof(*rq)); + rq->flags = REQ_SPECIAL; rq->special = (char *) pc; rq->bio = idescsi_dma_bio (drive, pc); - rq->flags = REQ_SPECIAL; spin_unlock_irq(cmd->host->host_lock); - (void) ide_do_drive_cmd (drive, rq, ide_end); + ide_do_drive_cmd (drive, rq, ide_end); spin_lock_irq(cmd->host->host_lock); + return 0; abort: - if (pc) kfree (pc); - if (rq) kfree (rq); + if (pc) + kfree (pc); + if (rq) + kfree (rq); cmd->result = DID_ERROR << 16; done(cmd); diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h index 598827f0ee06..a9aa625ffe1e 100644 --- a/include/linux/hdreg.h +++ b/include/linux/hdreg.h @@ -81,18 +81,9 @@ struct hd_drive_task_hdr { u8 low_cylinder; u8 high_cylinder; u8 device_head; - u8 command; -} __attribute__((packed)); -struct hd_drive_hob_hdr { - u8 data; - u8 feature; - u8 sector_count; - u8 sector_number; - u8 low_cylinder; - u8 high_cylinder; - u8 device_head; - u8 control; + /* FXIME: Consider moving this out from here. */ + u8 command; } __attribute__((packed)); /* diff --git a/include/linux/ide.h b/include/linux/ide.h index 7fe98cfd802c..7e22036b21a8 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -253,11 +253,11 @@ typedef union { unsigned all : 8; /* all of the bits together */ struct { #if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned head : 4; /* always zeros here */ + unsigned XXX_head : 4; /* always zeros here */ unsigned unit : 1; /* drive select number: 0/1 */ - unsigned bit5 : 1; /* always 1 */ + unsigned XXX_bit5 : 1; /* always 1 */ unsigned lba : 1; /* using LBA instead of CHS */ - unsigned bit7 : 1; /* always 1 */ + unsigned XXX_bit7 : 1; /* always 1 */ #elif defined(__BIG_ENDIAN_BITFIELD) unsigned bit7 : 1; unsigned lba : 1; @@ -270,29 +270,6 @@ typedef union { } b; } select_t; -typedef union { - unsigned all : 8; /* all of the bits together */ - struct { -#if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned bit0 : 1; - unsigned nIEN : 1; /* device INTRQ to host */ - unsigned SRST : 1; /* host soft reset bit */ - unsigned bit3 : 1; /* ATA-2 thingy */ - unsigned reserved456 : 3; - unsigned HOB : 1; /* 48-bit address ordering */ -#elif defined(__BIG_ENDIAN_BITFIELD) - unsigned HOB : 1; - unsigned reserved456 : 3; - unsigned bit3 : 1; - unsigned SRST : 1; - unsigned nIEN : 1; - unsigned bit0 : 1; -#else -#error "Please fix " -#endif - } b; -} control_t; - /* * ATA/ATAPI device structure : */ @@ -530,7 +507,7 @@ struct ata_channel { * Register new hardware with ide */ extern int ide_register_hw(hw_regs_t *hw); -extern void ide_unregister(struct ata_channel *hwif); +extern void ide_unregister(struct ata_channel *); struct ata_taskfile; @@ -670,11 +647,6 @@ struct ata_device *get_info_ptr(kdev_t i_rdev); */ ide_startstop_t restart_request(struct ata_device *); -/* - * This function is intended to be used prior to invoking ide_do_drive_cmd(). - */ -extern void ide_init_drive_cmd(struct request *rq); - /* * "action" parameter type for ide_do_drive_cmd() below. */ @@ -698,7 +670,7 @@ extern void ide_end_drive_cmd(struct ata_device *, struct request *, u8); struct ata_taskfile { struct hd_drive_task_hdr taskfile; - struct hd_drive_hob_hdr hobfile; + struct hd_drive_task_hdr hobfile; int command_type; ide_startstop_t (*prehandler)(struct ata_device *, struct request *); ide_startstop_t (*handler)(struct ata_device *, struct request *); @@ -717,21 +689,18 @@ extern ide_startstop_t ata_taskfile(struct ata_device *, extern ide_startstop_t recal_intr(struct ata_device *, struct request *); extern ide_startstop_t task_no_data_intr(struct ata_device *, struct request *); - -/* This is setting up all fields in args, which depend upon the command type. - */ extern void ide_cmd_type_parser(struct ata_taskfile *args); extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *); -extern int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg); extern void ide_fix_driveid(struct hd_driveid *id); extern int ide_config_drive_speed(struct ata_device *, byte); extern byte eighty_ninty_three(struct ata_device *); -extern int system_bus_speed; extern void ide_stall_queue(struct ata_device *, unsigned long); +extern int system_bus_speed; + /* * CompactFlash cards and their brethern pretend to be removable hard disks, * but they never have a slave unit, and they don't have doorlock mechanisms. @@ -873,5 +842,6 @@ extern void ata_mask(struct ata_device *); extern int ata_status(struct ata_device *, u8, u8); extern int ata_irq_enable(struct ata_device *, int); extern void ata_reset(struct ata_channel *); +extern void ata_out_regfile(struct ata_device *, struct hd_drive_task_hdr *); #endif -- cgit v1.2.3 From 76d0453847004cf0dd82e368262b17225f4bdd03 Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Sun, 2 Jun 2002 02:42:20 -0700 Subject: [PATCH] 2.5.19 IDE 80 - Sanitize the handling of the ioctl's and fix a bug on the way in dealing with the WIN_SMART command where arguments where exchanged. - Finally sanitize ioctl further until it turned out that we could get rid of the special request type REQ_DRIVE_CMD entierly. We are now using consistently REQ_DRIVE_ACB. One hidden code path less again! - Realize the ide_end_drive_cmd can be on the REQ_DRIVE_ACB only for ioctl() to a disk. Eliminate it's usage from device type driver modules. - Remove command member from struct hd_drive_task_hdr and place it in strcut ata_taskfile. It is not common between the normal register file and HOB. We will have to introduce some helper functions for particular command types. --- drivers/block/ll_rw_blk.c | 20 +++++-- drivers/ide/ide-disk.c | 38 +++++++------- drivers/ide/ide-floppy.c | 8 ++- drivers/ide/ide-tape.c | 7 ++- drivers/ide/ide-taskfile.c | 58 +++++++++------------ drivers/ide/ide.c | 121 +++++++++++-------------------------------- drivers/ide/ioctl.c | 126 ++++++++++++++++++++------------------------- drivers/ide/pcidma.c | 3 +- drivers/ide/pdc4030.c | 4 +- drivers/ide/tcq.c | 14 ++--- drivers/scsi/ide-scsi.c | 6 ++- include/linux/blkdev.h | 2 - include/linux/hdreg.h | 4 -- include/linux/ide.h | 9 ++-- 14 files changed, 175 insertions(+), 245 deletions(-) (limited to 'include') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 5396cba9b387..0de94d28405c 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -490,11 +490,21 @@ void blk_queue_invalidate_tags(request_queue_t *q) } } -static char *rq_flags[] = { "REQ_RW", "REQ_RW_AHEAD", "REQ_BARRIER", - "REQ_CMD", "REQ_NOMERGE", "REQ_STARTED", - "REQ_DONTPREP", "REQ_QUEUED", "REQ_DRIVE_CMD", - "REQ_DRIVE_ACB", "REQ_PC", "REQ_BLOCK_PC", - "REQ_SENSE", "REQ_SPECIAL" }; +static char *rq_flags[] = { + "REQ_RW", + "REQ_RW_AHEAD", + "REQ_BARRIER", + "REQ_CMD", + "REQ_NOMERGE", + "REQ_STARTED", + "REQ_DONTPREP", + "REQ_QUEUED", + "REQ_DRIVE_ACB", + "REQ_PC", + "REQ_BLOCK_PC", + "REQ_SENSE", + "REQ_SPECIAL" +}; void blk_dump_rq_flags(struct request *rq, char *msg) { diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index f0bbcb993e85..a90e4d45bef5 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -170,7 +170,7 @@ static ide_startstop_t chs_do_request(struct ata_device *drive, struct request * args.taskfile.device_head = head; args.taskfile.device_head |= drive->select.all; - args.taskfile.command = get_command(drive, rq_data_dir(rq)); + args.cmd = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, @@ -211,7 +211,7 @@ static ide_startstop_t lba28_do_request(struct ata_device *drive, struct request args.taskfile.device_head = ((block >> 8) & 0x0f); args.taskfile.device_head |= drive->select.all; - args.taskfile.command = get_command(drive, rq_data_dir(rq)); + args.cmd = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, @@ -264,7 +264,7 @@ static ide_startstop_t lba48_do_request(struct ata_device *drive, struct request args.hobfile.high_cylinder = (block >>= 8); /* hi lba */ args.hobfile.device_head = drive->select.all; - args.taskfile.command = get_command(drive, rq_data_dir(rq)); + args.cmd = get_command(drive, rq_data_dir(rq)); #ifdef DEBUG printk("%s: %sing: ", drive->name, @@ -355,7 +355,7 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi memset(&args, 0, sizeof(args)); - args.taskfile.command = WIN_DOORLOCK; + args.cmd = WIN_DOORLOCK; ide_cmd_type_parser(&args); /* @@ -377,9 +377,9 @@ static int idedisk_flushcache(struct ata_device *drive) memset(&args, 0, sizeof(args)); if (drive->id->cfs_enable_2 & 0x2400) - args.taskfile.command = WIN_FLUSH_CACHE_EXT; + args.cmd = WIN_FLUSH_CACHE_EXT; else - args.taskfile.command = WIN_FLUSH_CACHE; + args.cmd = WIN_FLUSH_CACHE; ide_cmd_type_parser(&args); @@ -395,7 +395,7 @@ static void idedisk_release(struct inode *inode, struct file *filp, struct ata_d invalidate_bdev(inode->i_bdev, 0); memset(&args, 0, sizeof(args)); - args.taskfile.command = WIN_DOORUNLOCK; + args.cmd = WIN_DOORUNLOCK; ide_cmd_type_parser(&args); if (drive->doorlocking && @@ -444,7 +444,7 @@ static int set_multcount(struct ata_device *drive, int arg) memset(&args, 0, sizeof(args)); args.taskfile.sector_count = arg; - args.taskfile.command = WIN_SETMULT; + args.cmd = WIN_SETMULT; ide_cmd_type_parser(&args); if (!ide_raw_taskfile(drive, &args)) { @@ -475,7 +475,7 @@ static int write_cache(struct ata_device *drive, int arg) memset(&args, 0, sizeof(args)); args.taskfile.feature = (arg) ? SETFEATURES_EN_WCACHE : SETFEATURES_DIS_WCACHE; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); ide_raw_taskfile(drive, &args); @@ -489,7 +489,7 @@ static int idedisk_standby(struct ata_device *drive) struct ata_taskfile args; memset(&args, 0, sizeof(args)); - args.taskfile.command = WIN_STANDBYNOW1; + args.cmd = WIN_STANDBYNOW1; ide_cmd_type_parser(&args); return ide_raw_taskfile(drive, &args); @@ -502,7 +502,7 @@ static int set_acoustic(struct ata_device *drive, int arg) memset(&args, 0, sizeof(args)); args.taskfile.feature = (arg)?SETFEATURES_EN_AAM:SETFEATURES_DIS_AAM; args.taskfile.sector_count = arg; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); ide_raw_taskfile(drive, &args); @@ -622,14 +622,14 @@ static unsigned long native_max_address(struct ata_device *drive) /* Create IDE/ATA command request structure */ memset(&args, 0, sizeof(args)); args.taskfile.device_head = 0x40; - args.taskfile.command = WIN_READ_NATIVE_MAX; + args.cmd = WIN_READ_NATIVE_MAX; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if ((args.cmd & 0x01) == 0) { addr = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) @@ -650,14 +650,14 @@ static u64 native_max_address_ext(struct ata_device *drive) memset(&args, 0, sizeof(args)); args.taskfile.device_head = 0x40; - args.taskfile.command = WIN_READ_NATIVE_MAX_EXT; + args.cmd = WIN_READ_NATIVE_MAX_EXT; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if ((args.cmd & 0x01) == 0) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; @@ -691,12 +691,12 @@ static sector_t set_max_address(struct ata_device *drive, sector_t addr_req) args.taskfile.high_cylinder = (addr_req >> 16); args.taskfile.device_head = ((addr_req >> 24) & 0x0f) | 0x40; - args.taskfile.command = WIN_SET_MAX; + args.cmd = WIN_SET_MAX; args.handler = task_no_data_intr; /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, read new maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if ((args.cmd & 0x01) == 0) { addr_set = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) @@ -719,7 +719,7 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req) args.taskfile.low_cylinder = (addr_req >>= 8); args.taskfile.high_cylinder = (addr_req >>= 8); args.taskfile.device_head = 0x40; - args.taskfile.command = WIN_SET_MAX_EXT; + args.cmd = WIN_SET_MAX_EXT; args.hobfile.sector_number = (addr_req >>= 8); args.hobfile.low_cylinder = (addr_req >>= 8); @@ -731,7 +731,7 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req) /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.taskfile.command & 0x01) == 0) { + if ((args.cmd & 0x01) == 0) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index 386c3c3ee61f..ce9281a2db20 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -620,7 +620,7 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i #if IDEFLOPPY_DEBUG_LOG printk (KERN_INFO "Reached idefloppy_end_request\n"); -#endif /* IDEFLOPPY_DEBUG_LOG */ +#endif switch (uptodate) { case 0: error = IDEFLOPPY_ERROR_GENERAL; break; @@ -632,12 +632,16 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i /* Why does this happen? */ if (!rq) return 0; + if (!(rq->flags & IDEFLOPPY_RQ)) { ide_end_request(drive, rq, uptodate); return 0; } + rq->errors = error; - ide_end_drive_cmd (drive, rq, 0); + blkdev_dequeue_request(rq); + drive->rq = NULL; + end_that_request_last(rq); return 0; } diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index 16c8bea8eb27..bb4beecb858a 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -1864,9 +1864,12 @@ static int idetape_end_request(struct ata_device *drive, struct request *rq, int idetape_increase_max_pipeline_stages (drive); } } - ide_end_drive_cmd(drive, rq, 0); + blkdev_dequeue_request(rq); + drive->rq = NULL; + end_that_request_last(rq); + if (remove_stage) - idetape_remove_stage_head (drive); + idetape_remove_stage_head(drive); if (tape->active_data_request == NULL) clear_bit(IDETAPE_PIPELINE_ACTIVE, &tape->flags); spin_unlock_irqrestore(&tape->spinlock, flags); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 6ba395ef4c80..79a4cf8fbcca 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -311,34 +311,34 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request } ide_startstop_t ata_taskfile(struct ata_device *drive, - struct ata_taskfile *args, struct request *rq) + struct ata_taskfile *ar, struct request *rq) { struct hd_driveid *id = drive->id; /* (ks/hs): Moved to start, do not use for multiple out commands */ - if (args->handler != task_mulout_intr) { + if (ar->handler != task_mulout_intr) { ata_irq_enable(drive, 1); ata_mask(drive); } if ((id->command_set_2 & 0x0400) && (id->cfs_enable_2 & 0x0400) && (drive->addressing == 1)) - ata_out_regfile(drive, &args->hobfile); + ata_out_regfile(drive, &ar->hobfile); - ata_out_regfile(drive, &args->taskfile); + ata_out_regfile(drive, &ar->taskfile); { u8 HIHI = (drive->addressing) ? 0xE0 : 0xEF; - OUT_BYTE((args->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG); + OUT_BYTE((ar->taskfile.device_head & HIHI) | drive->select.all, IDE_SELECT_REG); } - if (args->handler != NULL) { + if (ar->handler != NULL) { /* This is apparently supposed to reset the wait timeout for * the interrupt to accur. */ - ide_set_handler(drive, args->handler, WAIT_CMD, NULL); - OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG); + ide_set_handler(drive, ar->handler, WAIT_CMD, NULL); + OUT_BYTE(ar->cmd, IDE_COMMAND_REG); /* * Warning check for race between handler and prehandler for @@ -346,8 +346,8 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, * inside the boundaries of the seek, we should be okay. */ - if (args->prehandler != NULL) - return args->prehandler(drive, rq); + if (ar->prehandler != NULL) + return ar->prehandler(drive, rq); } else { /* * FIXME: this is a gross hack, need to unify tcq dma proc and @@ -358,21 +358,20 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, return ide_started; /* for dma commands we don't set the handler */ - if (args->taskfile.command == WIN_WRITEDMA - || args->taskfile.command == WIN_WRITEDMA_EXT) + if (ar->cmd == WIN_WRITEDMA || ar->cmd == WIN_WRITEDMA_EXT) return !udma_write(drive, rq); - else if (args->taskfile.command == WIN_READDMA - || args->taskfile.command == WIN_READDMA_EXT) + else if (ar->cmd == WIN_READDMA + || ar->cmd == WIN_READDMA_EXT) return !udma_read(drive, rq); #ifdef CONFIG_BLK_DEV_IDE_TCQ - else if (args->taskfile.command == WIN_WRITEDMA_QUEUED - || args->taskfile.command == WIN_WRITEDMA_QUEUED_EXT - || args->taskfile.command == WIN_READDMA_QUEUED - || args->taskfile.command == WIN_READDMA_QUEUED_EXT) + else if (ar->cmd == WIN_WRITEDMA_QUEUED + || ar->cmd == WIN_WRITEDMA_QUEUED_EXT + || ar->cmd == WIN_READDMA_QUEUED + || ar->cmd == WIN_READDMA_QUEUED_EXT) return udma_tcq_taskfile(drive, rq); #endif else { - printk("ata_taskfile: unknown command %x\n", args->taskfile.command); + printk("ata_taskfile: unknown command %x\n", ar->cmd); return ide_stopped; } } @@ -396,18 +395,18 @@ ide_startstop_t recal_intr(struct ata_device *drive, struct request *rq) */ ide_startstop_t task_no_data_intr(struct ata_device *drive, struct request *rq) { - struct ata_taskfile *args = rq->special; + struct ata_taskfile *ar = rq->special; ide__sti(); /* local CPU only */ if (!ata_status(drive, READY_STAT, BAD_STAT)) { /* Keep quiet for NOP because it is expected to fail. */ - if (args && args->taskfile.command != WIN_NOP) + if (ar && ar->cmd != WIN_NOP) return ata_error(drive, rq, __FUNCTION__); } - if (args) - ide_end_drive_cmd(drive, rq, GET_ERR()); + if (ar) + ide_end_drive_cmd(drive, rq); return ide_stopped; } @@ -466,8 +465,8 @@ static ide_startstop_t pre_task_out_intr(struct ata_device *drive, struct reques } /* (ks/hs): Fixed Multi Write */ - if ((args->taskfile.command != WIN_MULTWRITE) && - (args->taskfile.command != WIN_MULTWRITE_EXT)) { + if ((args->cmd != WIN_MULTWRITE) && + (args->cmd != WIN_MULTWRITE_EXT)) { unsigned long flags; char *buf = ide_map_rq(rq, &flags); /* For Write_sectors we need to stuff the first sector */ @@ -569,7 +568,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args) args->prehandler = NULL; args->handler = NULL; - switch(args->taskfile.command) { + switch (args->cmd) { case WIN_IDENTIFY: case WIN_PIDENTIFY: args->handler = task_in_intr; @@ -817,13 +816,6 @@ int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args) memset(&rq, 0, sizeof(rq)); rq.flags = REQ_DRIVE_ACB; - -#if 0 - if (args->command_type != IDE_DRIVE_TASK_NO_DATA) - rq.current_nr_sectors = rq.nr_sectors - = (args->hobfile.sector_count << 8) - | args->taskfile.sector_count; -#endif rq.special = args; return ide_do_drive_cmd(drive, &rq, ide_wait); diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 45e5737e112e..652bce83da59 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -395,38 +395,30 @@ static inline u32 read_24(struct ata_device *drive) * * Should be called under lock held. */ -void ide_end_drive_cmd(struct ata_device *drive, struct request *rq, u8 err) +void ide_end_drive_cmd(struct ata_device *drive, struct request *rq) { - if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = rq->buffer; - rq->errors = !ata_status(drive, READY_STAT, BAD_STAT); - if (args) { - args[0] = drive->status; - args[1] = err; - args[2] = IN_BYTE(IDE_NSECTOR_REG); - } - } else if (rq->flags & REQ_DRIVE_ACB) { - struct ata_taskfile *args = rq->special; + if (rq->flags & REQ_DRIVE_ACB) { + struct ata_taskfile *ar = rq->special; rq->errors = !ata_status(drive, READY_STAT, BAD_STAT); - if (args) { - args->taskfile.feature = err; - args->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); - args->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG); - args->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); - args->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); - args->taskfile.device_head = IN_BYTE(IDE_SELECT_REG); - args->taskfile.command = drive->status; + if (ar) { + ar->taskfile.feature = IN_BYTE(IDE_ERROR_REG); + ar->taskfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); + ar->taskfile.sector_number = IN_BYTE(IDE_SECTOR_REG); + ar->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); + ar->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); + ar->taskfile.device_head = IN_BYTE(IDE_SELECT_REG); + ar->cmd = drive->status; if ((drive->id->command_set_2 & 0x0400) && (drive->id->cfs_enable_2 & 0x0400) && (drive->addressing == 1)) { /* The following command goes to the hob file! */ OUT_BYTE(0x80, drive->channel->io_ports[IDE_CONTROL_OFFSET]); - args->hobfile.feature = IN_BYTE(IDE_FEATURE_REG); - args->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); - args->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG); - args->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); - args->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); + ar->hobfile.feature = IN_BYTE(IDE_FEATURE_REG); + ar->hobfile.sector_count = IN_BYTE(IDE_NSECTOR_REG); + ar->hobfile.sector_number = IN_BYTE(IDE_SECTOR_REG); + ar->hobfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); + ar->hobfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); } } } @@ -583,7 +575,7 @@ static int do_recalibrate(struct ata_device *drive) memset(&args, 0, sizeof(args)); args.taskfile.sector_count = drive->sect; - args.taskfile.command = WIN_RESTORE; + args.cmd = WIN_RESTORE; args.handler = recal_intr; ata_taskfile(drive, &args, NULL); } @@ -602,10 +594,12 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch err = ide_dump_status(drive, rq, msg, stat); if (!drive || !rq) return ide_stopped; + /* retry only "normal" I/O: */ if (!(rq->flags & REQ_CMD)) { rq->errors = 1; - ide_end_drive_cmd(drive, rq, err); + ide_end_drive_cmd(drive, rq); + return ide_stopped; } /* other bits are useless when BUSY */ @@ -648,30 +642,6 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch return ide_stopped; } -/* - * Invoked on completion of a special DRIVE_CMD. - */ -static ide_startstop_t drive_cmd_intr(struct ata_device *drive, struct request *rq) -{ - u8 *args = rq->buffer; - - ide__sti(); /* local CPU only */ - if (!ata_status(drive, 0, DRQ_STAT) && args && args[3]) { - int retries = 10; - - ata_read(drive, &args[4], args[3] * SECTOR_WORDS); - - while (!ata_status(drive, 0, BUSY_STAT) && retries--) - udelay(100); - } - - if (!ata_status(drive, READY_STAT, BAD_STAT)) - return ata_error(drive, rq, __FUNCTION__); /* already calls ide_end_drive_cmd */ - ide_end_drive_cmd(drive, rq, GET_ERR()); - - return ide_stopped; -} - /* * Busy-wait for the drive status to be not "busy". Check then the status for * all of the "good" bits and none of the "bad" bits, and if all is okay it @@ -775,53 +745,20 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r } } - /* This issues a special drive command, usually initiated by ioctl() - * from the external hdparm program. + /* This issues a special drive command. */ if (rq->flags & REQ_DRIVE_ACB) { - struct ata_taskfile *args = rq->special; + struct ata_taskfile *ar = rq->special; - if (!(args)) + if (!(ar)) goto args_error; - ata_taskfile(drive, args, NULL); - - if (((args->command_type == IDE_DRIVE_TASK_RAW_WRITE) || - (args->command_type == IDE_DRIVE_TASK_OUT)) && - args->prehandler && args->handler) - return args->prehandler(drive, rq); - - return ide_started; - } + ata_taskfile(drive, ar, NULL); - if (rq->flags & REQ_DRIVE_CMD) { - u8 *args = rq->buffer; - - if (!(args)) - goto args_error; -#ifdef DEBUG - printk("%s: DRIVE_CMD ", drive->name); - printk("cmd=0x%02x ", args[0]); - printk(" sc=0x%02x ", args[1]); - printk(" fr=0x%02x ", args[2]); - printk(" xx=0x%02x\n", args[3]); -#endif - ide_set_handler(drive, drive_cmd_intr, WAIT_CMD, NULL); - ata_irq_enable(drive, 1); - ata_mask(drive); - if (args[0] == WIN_SMART) { - struct hd_drive_task_hdr regfile; - regfile.feature = args[2]; - regfile.sector_count = args[3]; - regfile.sector_number = args[1]; - regfile.low_cylinder = 0x4f; - regfile.high_cylinder = 0xc2; - ata_out_regfile(drive, ®file); - } else { - OUT_BYTE(args[2], IDE_FEATURE_REG); - OUT_BYTE(args[1], IDE_NSECTOR_REG); - } - OUT_BYTE(args[0], IDE_COMMAND_REG); + if (((ar->command_type == IDE_DRIVE_TASK_RAW_WRITE) || + (ar->command_type == IDE_DRIVE_TASK_OUT)) && + ar->prehandler && ar->handler) + return ar->prehandler(drive, rq); return ide_started; } @@ -863,7 +800,7 @@ args_error: #ifdef DEBUG printk("%s: DRIVE_CMD (null)\n", drive->name); #endif - ide_end_drive_cmd(drive, rq, GET_ERR()); + ide_end_drive_cmd(drive, rq); return ide_stopped; } diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c index b2128238aeae..d8b355e76143 100644 --- a/drivers/ide/ioctl.c +++ b/drivers/ide/ioctl.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include @@ -32,6 +33,30 @@ #include "ioctl.h" +/* + * Invoked on completion of a special DRIVE_CMD. + */ +static ide_startstop_t drive_cmd_intr(struct ata_device *drive, struct request *rq) +{ + struct ata_taskfile *ar = rq->special; + + ide__sti(); /* local CPU only */ + if (!ata_status(drive, 0, DRQ_STAT) && ar->taskfile.sector_number) { + int retries = 10; + + ata_read(drive, rq->buffer, ar->taskfile.sector_number * SECTOR_WORDS); + + while (!ata_status(drive, 0, BUSY_STAT) && retries--) + udelay(100); + } + + if (!ata_status(drive, READY_STAT, BAD_STAT)) + return ata_error(drive, rq, __FUNCTION__); /* already calls ide_end_drive_cmd */ + ide_end_drive_cmd(drive, rq); + + return ide_stopped; +} + /* * Implement generic ioctls invoked from userspace to imlpement specific * functionality. @@ -39,36 +64,37 @@ * Unfortunately every single low level programm out there is using this * interface. */ -static int cmd_ioctl(struct ata_device *drive, unsigned long arg) +static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg) { int err = 0; u8 vals[4]; u8 *argbuf = vals; - u8 pio = 0; int argsize = 4; struct ata_taskfile args; struct request rq; - memset(&rq, 0, sizeof(rq)); - rq.flags = REQ_DRIVE_CMD; - - /* If empty parameter file - wait for drive ready. - */ - if (!arg) - return ide_do_drive_cmd(drive, &rq, ide_wait); - /* Second phase. */ if (copy_from_user(vals, (void *)arg, 4)) return -EFAULT; + memset(&rq, 0, sizeof(rq)); + rq.flags = REQ_DRIVE_ACB; + + memset(&args, 0, sizeof(args)); + args.taskfile.feature = vals[2]; - args.taskfile.sector_count = vals[3]; - args.taskfile.sector_number = vals[1]; - args.taskfile.low_cylinder = 0x00; - args.taskfile.high_cylinder = 0x00; + args.taskfile.sector_count = vals[1]; + args.taskfile.sector_number = vals[3]; + if (vals[0] == WIN_SMART) { + args.taskfile.low_cylinder = 0x4f; + args.taskfile.high_cylinder = 0xc2; + } else { + args.taskfile.low_cylinder = 0x00; + args.taskfile.high_cylinder = 0x00; + } args.taskfile.device_head = 0x00; - args.taskfile.command = vals[0]; + args.cmd = vals[0]; if (vals[3]) { argsize = 4 + (SECTOR_WORDS * 4 * vals[3]); @@ -79,63 +105,18 @@ static int cmd_ioctl(struct ata_device *drive, unsigned long arg) memset(argbuf + 4, 0, argsize - 4); } - /* - * Always make sure the transfer reate has been setup. - * - * FIXME: what about setting up the drive with ->tuneproc? - * - * Backside of HDIO_DRIVE_CMD call of SETFEATURES_XFER. - * 1 : Safe to update drive->id DMA registers. - * 0 : OOPs not allowed. - */ - if ((args.taskfile.command == WIN_SETFEATURES) && - (args.taskfile.sector_number >= XFER_SW_DMA_0) && - (args.taskfile.feature == SETFEATURES_XFER) && - (drive->id->dma_ultra || - drive->id->dma_mword || - drive->id->dma_1word)) { - pio = vals[1]; - /* - * Verify that we are doing an approved SETFEATURES_XFER with - * respect to the hardware being able to support request. - * Since some hardware can improperly report capabilties, we - * check to see if the host adapter in combination with the - * device (usually a disk) properly detect and acknowledge each - * end of the ribbon. - */ - if (args.taskfile.sector_number > XFER_UDMA_2) { - if (!drive->channel->udma_four) { - printk(KERN_WARNING "%s: Speed warnings UDMA > 2 is not functional.\n", - drive->channel->name); - goto abort; - } -#ifndef CONFIG_IDEDMA_IVB - if (!(drive->id->hw_config & 0x6000)) -#else - if (!(drive->id->hw_config & 0x2000) || - !(drive->id->hw_config & 0x4000)) -#endif - { - printk(KERN_WARNING "%s: Speed warnings UDMA > 2 is not functional.\n", - drive->name); - goto abort; - } - } - } - /* Issue ATA command and wait for completion. */ - rq.buffer = argbuf; + args.handler = drive_cmd_intr; + + rq.buffer = argbuf + 4; + rq.special = &args; err = ide_do_drive_cmd(drive, &rq, ide_wait); - if (!err && pio) { - /* active-retuning-calls future */ - /* FIXME: what about the setup for the drive?! */ - if (drive->channel->speedproc) - drive->channel->speedproc(drive, pio); - } + argbuf[0] = drive->status; + argbuf[1] = args.taskfile.feature; + argbuf[2] = args.taskfile.sector_count; -abort: if (copy_to_user((void *)arg, argbuf, argsize)) err = -EFAULT; @@ -153,7 +134,6 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned { unsigned int major, minor; struct ata_device *drive; -// struct request rq; kdev_t dev; dev = inode->i_rdev; @@ -354,10 +334,14 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned return 0; case HDIO_DRIVE_CMD: - if (!capable(CAP_SYS_RAWIO)) - return -EACCES; + if (!arg) { + if (ide_spin_wait_hwgroup(drive)) + return -EBUSY; + else + return 0; + } - return cmd_ioctl(drive, arg); + return do_cmd_ioctl(drive, arg); /* * uniform packet command handling diff --git a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c index 7f852c7cc9e8..0a51f1863fc5 100644 --- a/drivers/ide/pcidma.c +++ b/drivers/ide/pcidma.c @@ -541,9 +541,10 @@ int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request * ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */ if ((rq->flags & REQ_DRIVE_ACB) && (drive->addressing == 1)) { + /* FIXME: this should never happen */ struct ata_taskfile *args = rq->special; - outb(args->taskfile.command, IDE_COMMAND_REG); + outb(args->cmd, IDE_COMMAND_REG); } else if (drive->addressing) { outb(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); } else { diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c index d33d298d20bd..893764a5da7a 100644 --- a/drivers/ide/pdc4030.c +++ b/drivers/ide/pdc4030.c @@ -630,7 +630,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg outb(taskfile->low_cylinder, IDE_LCYL_REG); outb(taskfile->high_cylinder, IDE_HCYL_REG); outb(taskfile->device_head, IDE_SELECT_REG); - outb(taskfile->command, IDE_COMMAND_REG); + outb(args->cmd, IDE_COMMAND_REG); switch (rq_data_dir(rq)) { case READ: @@ -708,7 +708,7 @@ ide_startstop_t promise_do_request(struct ata_device *drive, struct request *rq, args.taskfile.low_cylinder = (block>>=8); args.taskfile.high_cylinder = (block>>=8); args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; - args.taskfile.command = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE; + args.cmd = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE; /* We can't call ide_cmd_type_parser here, since it won't understand our command, but that doesn't matter, since we don't use the diff --git a/drivers/ide/tcq.c b/drivers/ide/tcq.c index 5db64872e225..41bb8af6a0cf 100644 --- a/drivers/ide/tcq.c +++ b/drivers/ide/tcq.c @@ -60,7 +60,7 @@ static ide_startstop_t tcq_nop_handler(struct ata_device *drive, struct request struct ata_taskfile *args = rq->special; ide__sti(); - ide_end_drive_cmd(drive, rq, GET_ERR()); + ide_end_drive_cmd(drive, rq); kfree(args); return ide_stopped; @@ -118,7 +118,7 @@ static void tcq_invalidate_queue(struct ata_device *drive) BUG_ON(!rq); rq->special = args; - args->taskfile.command = WIN_NOP; + args->cmd = WIN_NOP; args->handler = tcq_nop_handler; args->command_type = IDE_DRIVE_TASK_NO_DATA; @@ -407,7 +407,7 @@ static int check_autopoll(struct ata_device *drive) memset(&args, 0, sizeof(args)); args.taskfile.feature = 0x01; - args.taskfile.command = WIN_NOP; + args.cmd = WIN_NOP; ide_cmd_type_parser(&args); /* @@ -442,7 +442,7 @@ static int configure_tcq(struct ata_device *drive) memset(&args, 0, sizeof(args)); args.taskfile.feature = SETFEATURES_EN_WCACHE; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); if (ide_raw_taskfile(drive, &args)) { @@ -456,7 +456,7 @@ static int configure_tcq(struct ata_device *drive) */ memset(&args, 0, sizeof(args)); args.taskfile.feature = SETFEATURES_DIS_RI; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); if (ide_raw_taskfile(drive, &args)) { @@ -470,7 +470,7 @@ static int configure_tcq(struct ata_device *drive) */ memset(&args, 0, sizeof(args)); args.taskfile.feature = SETFEATURES_EN_SI; - args.taskfile.command = WIN_SETFEATURES; + args.cmd = WIN_SETFEATURES; ide_cmd_type_parser(&args); if (ide_raw_taskfile(drive, &args)) { @@ -554,7 +554,7 @@ ide_startstop_t udma_tcq_taskfile(struct ata_device *drive, struct request *rq) ata_irq_enable(drive, 0); #endif - OUT_BYTE(args->taskfile.command, IDE_COMMAND_REG); + OUT_BYTE(args->cmd, IDE_COMMAND_REG); if (wait_altstat(drive, &stat, BUSY_STAT)) { ide_dump_status(drive, rq, "queued start", stat); diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index e2292cd43325..cf44a6f975dc 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -242,7 +242,11 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int ide_end_request(drive, rq, uptodate); return 0; } - ide_end_drive_cmd(drive, rq, 0); + + blkdev_dequeue_request(rq); + drive->rq = NULL; + end_that_request_last(rq); + if (rq->errors >= ERROR_MAX) { pc->s.scsi_cmd->result = DID_ERROR << 16; if (log) diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index 407b176d7dad..a3e1c02d6d63 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -81,7 +81,6 @@ enum rq_flag_bits { /* * for ATA/ATAPI devices */ - __REQ_DRIVE_CMD, __REQ_DRIVE_ACB, __REQ_PC, /* packet command (special) */ @@ -101,7 +100,6 @@ enum rq_flag_bits { #define REQ_STARTED (1 << __REQ_STARTED) #define REQ_DONTPREP (1 << __REQ_DONTPREP) #define REQ_QUEUED (1 << __REQ_QUEUED) -#define REQ_DRIVE_CMD (1 << __REQ_DRIVE_CMD) #define REQ_DRIVE_ACB (1 << __REQ_DRIVE_ACB) #define REQ_PC (1 << __REQ_PC) #define REQ_BLOCK_PC (1 << __REQ_BLOCK_PC) diff --git a/include/linux/hdreg.h b/include/linux/hdreg.h index a9aa625ffe1e..6f1fd4aae99a 100644 --- a/include/linux/hdreg.h +++ b/include/linux/hdreg.h @@ -74,16 +74,12 @@ #define IDE_DRIVE_TASK_RAW_WRITE 4 struct hd_drive_task_hdr { - u8 data; u8 feature; u8 sector_count; u8 sector_number; u8 low_cylinder; u8 high_cylinder; u8 device_head; - - /* FXIME: Consider moving this out from here. */ - u8 command; } __attribute__((packed)); /* diff --git a/include/linux/ide.h b/include/linux/ide.h index 7e22036b21a8..9c289abd3ccc 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -253,11 +253,11 @@ typedef union { unsigned all : 8; /* all of the bits together */ struct { #if defined(__LITTLE_ENDIAN_BITFIELD) - unsigned XXX_head : 4; /* always zeros here */ + unsigned head : 4; /* always zeros here */ unsigned unit : 1; /* drive select number: 0/1 */ - unsigned XXX_bit5 : 1; /* always 1 */ + unsigned bit5 : 1; /* always 1 */ unsigned lba : 1; /* using LBA instead of CHS */ - unsigned XXX_bit7 : 1; /* always 1 */ + unsigned bit7 : 1; /* always 1 */ #elif defined(__BIG_ENDIAN_BITFIELD) unsigned bit7 : 1; unsigned lba : 1; @@ -666,11 +666,12 @@ extern int ide_do_drive_cmd(struct ata_device *, struct request *, ide_action_t) /* * Clean up after success/failure of an explicit drive cmd. */ -extern void ide_end_drive_cmd(struct ata_device *, struct request *, u8); +extern void ide_end_drive_cmd(struct ata_device *, struct request *); struct ata_taskfile { struct hd_drive_task_hdr taskfile; struct hd_drive_task_hdr hobfile; + u8 cmd; /* actual ATA command */ int command_type; ide_startstop_t (*prehandler)(struct ata_device *, struct request *); ide_startstop_t (*handler)(struct ata_device *, struct request *); -- cgit v1.2.3 From 08446d856daf3669d2e91c3fd80ccb612e13c20c Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Sun, 2 Jun 2002 02:42:42 -0700 Subject: [PATCH] 2.5.19 IDE 81 - Don't use ata_taskfiles cmd field for drive status reporting, we can now simply use drive->status instead. - Unify command type parser entries which could be unified due to the unification of corresponding interrupt handlers. - Eliminate reading parameter from ata_do_udma(). We have this information already in the rq. This allows us to merge several methods. - Rename XXX_udma to udma_setup, since we have finally settled up on this semantics. - Simplify tons of host chip code by removing wrapper functions. --- drivers/ide/aec62xx.c | 8 ++-- drivers/ide/alim15x3.c | 15 +++---- drivers/ide/amd74xx.c | 4 +- drivers/ide/cmd64x.c | 14 +++--- drivers/ide/cs5530.c | 4 +- drivers/ide/cy82c693.c | 4 +- drivers/ide/hpt34x.c | 42 ++++++------------ drivers/ide/hpt366.c | 31 +++---------- drivers/ide/icside.c | 7 ++- drivers/ide/ide-cd.c | 6 +-- drivers/ide/ide-disk.c | 10 ++--- drivers/ide/ide-floppy.c | 8 +--- drivers/ide/ide-pmac.c | 39 +++++++--------- drivers/ide/ide-tape.c | 8 +--- drivers/ide/ide-taskfile.c | 108 ++++++++++++++++++++------------------------- drivers/ide/ide.c | 55 +++++++++++------------ drivers/ide/ioctl.c | 2 +- drivers/ide/main.c | 9 ++-- drivers/ide/ns87415.c | 25 +++-------- drivers/ide/pcidma.c | 45 +++++++------------ drivers/ide/pdc202xx.c | 10 ++--- drivers/ide/pdc4030.c | 22 +++------ drivers/ide/piix.c | 4 +- drivers/ide/serverworks.c | 9 +--- drivers/ide/sis5513.c | 14 ++---- drivers/ide/sl82c105.c | 28 +++--------- drivers/ide/trm290.c | 31 ++++++------- drivers/ide/via82cxxx.c | 4 +- drivers/scsi/ide-scsi.c | 8 +--- include/linux/ide.h | 42 +++++++----------- 30 files changed, 232 insertions(+), 384 deletions(-) (limited to 'include') diff --git a/drivers/ide/aec62xx.c b/drivers/ide/aec62xx.c index 49846a21461a..8267396a47f3 100644 --- a/drivers/ide/aec62xx.c +++ b/drivers/ide/aec62xx.c @@ -150,7 +150,7 @@ static void aec62xx_tune_drive(struct ata_device *drive, unsigned char pio) } #ifdef CONFIG_BLK_DEV_IDEDMA -static int aec62xx_dmaproc(struct ata_device *drive) +static int aec62xx_udma_setup(struct ata_device *drive) { u32 bmide = pci_resource_start(drive->channel->pci_dev, 4); short speed; @@ -244,8 +244,8 @@ static void __init aec62xx_init_channel(struct ata_channel *ch) { int i; - ch->tuneproc = &aec62xx_tune_drive; - ch->speedproc = &aec_set_drive; + ch->tuneproc = aec62xx_tune_drive; + ch->speedproc = aec_set_drive; ch->autodma = 0; ch->io_32bit = 1; @@ -259,7 +259,7 @@ static void __init aec62xx_init_channel(struct ata_channel *ch) #ifdef CONFIG_BLK_DEV_IDEDMA if (ch->dma_base) { ch->highmem = 1; - ch->XXX_udma = aec62xx_dmaproc; + ch->udma_setup = aec62xx_udma_setup; #ifdef CONFIG_IDEDMA_AUTO if (!noautodma) ch->autodma = 1; diff --git a/drivers/ide/alim15x3.c b/drivers/ide/alim15x3.c index baf3f747eb06..0f4dee1a11d3 100644 --- a/drivers/ide/alim15x3.c +++ b/drivers/ide/alim15x3.c @@ -199,7 +199,7 @@ static int config_chipset_for_dma(struct ata_device *drive, u8 udma) return !ali15x3_tune_chipset(drive, mode); } -static int ali15x3_config_drive_for_dma(struct ata_device *drive) +static int ali15x3_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; struct ata_channel *hwif = drive->channel; @@ -261,17 +261,12 @@ no_dma_set: return 0; } -static int ali15x3_udma_write(struct ata_device *drive, struct request *rq) +static int ali15x3_udma_init(struct ata_device *drive, struct request *rq) { if ((m5229_revision < 0xC2) && (drive->type != ATA_DISK)) return 1; /* try PIO instead of DMA */ - return ata_do_udma(0, drive, rq); -} - -static int ali15x3_dmaproc(struct ata_device *drive) -{ - return ali15x3_config_drive_for_dma(drive); + return udma_pci_init(drive, rq); } #endif @@ -447,8 +442,8 @@ static void __init ali15x3_init_channel(struct ata_channel *hwif) /* * M1543C or newer for DMAing */ - hwif->udma_write = ali15x3_udma_write; - hwif->XXX_udma = ali15x3_dmaproc; + hwif->udma_init = ali15x3_udma_init; + hwif->udma_setup = ali15x3_udma_setup; hwif->autodma = 1; } diff --git a/drivers/ide/amd74xx.c b/drivers/ide/amd74xx.c index 4f5973df9b2d..34f2ce30593c 100644 --- a/drivers/ide/amd74xx.c +++ b/drivers/ide/amd74xx.c @@ -177,7 +177,7 @@ static void amd74xx_tune_drive(struct ata_device *drive, u8 pio) } #ifdef CONFIG_BLK_DEV_IDEDMA -int amd74xx_dmaproc(struct ata_device *drive) +static int amd74xx_udma_setup(struct ata_device *drive) { short w80 = drive->channel->udma_four; @@ -291,7 +291,7 @@ static void __init amd74xx_init_channel(struct ata_channel *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = amd74xx_dmaproc; + hwif->udma_setup = amd74xx_udma_setup; # ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; diff --git a/drivers/ide/cmd64x.c b/drivers/ide/cmd64x.c index f2ca4a71370d..d254363590f2 100644 --- a/drivers/ide/cmd64x.c +++ b/drivers/ide/cmd64x.c @@ -627,7 +627,7 @@ no_dma_set: return 0; } -static int cmd680_dmaproc(struct ata_device *drive) +static int cmd680_udma_setup(struct ata_device *drive) { return cmd64x_config_drive_for_dma(drive); } @@ -680,7 +680,7 @@ static int cmd64x_udma_irq_status(struct ata_device *drive) return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ } -static int cmd64x_dmaproc(struct ata_device *drive) +static int cmd64x_udma_setup(struct ata_device *drive) { return cmd64x_config_drive_for_dma(drive); } @@ -703,7 +703,7 @@ static int cmd646_1_udma_stop(struct ata_device *drive) * ASUS P55T2P4D with CMD646 chipset revision 0x01 requires the old * event order for DMA transfers. */ -static int cmd646_1_dmaproc(struct ata_device *drive) +static int cmd646_1_udma_setup(struct ata_device *drive) { return cmd64x_config_drive_for_dma(drive); } @@ -903,7 +903,7 @@ static void __init cmd64x_init_channel(struct ata_channel *hwif) hwif->busproc = cmd680_busproc; #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) - hwif->XXX_udma = cmd680_dmaproc; + hwif->udma_setup = cmd680_udma_setup; #endif hwif->resetproc = cmd680_reset; hwif->speedproc = cmd680_tune_chipset; @@ -914,7 +914,7 @@ static void __init cmd64x_init_channel(struct ata_channel *hwif) case PCI_DEVICE_ID_CMD_643: #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { - hwif->XXX_udma = cmd64x_dmaproc; + hwif->udma_setup = cmd64x_udma_setup; hwif->udma_stop = cmd64x_udma_stop; hwif->udma_irq_status = cmd64x_udma_irq_status; } @@ -927,10 +927,10 @@ static void __init cmd64x_init_channel(struct ata_channel *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { if (class_rev == 0x01) { - hwif->XXX_udma = cmd646_1_dmaproc; + hwif->udma_setup = cmd646_1_udma_setup; hwif->udma_stop = cmd646_1_udma_stop; } else { - hwif->XXX_udma = cmd64x_dmaproc; + hwif->udma_setup = cmd64x_udma_setup; hwif->udma_stop = cmd64x_udma_stop; hwif->udma_irq_status = cmd64x_udma_irq_status; } diff --git a/drivers/ide/cs5530.c b/drivers/ide/cs5530.c index 03a77a201d09..770282983261 100644 --- a/drivers/ide/cs5530.c +++ b/drivers/ide/cs5530.c @@ -191,7 +191,7 @@ static int cs5530_config_dma(struct ata_device *drive) return 0; } -int cs5530_dmaproc(struct ata_device *drive) +static int cs5530_udma_setup(struct ata_device *drive) { return cs5530_config_dma(drive); } @@ -292,7 +292,7 @@ static void __init ide_init_cs5530(struct ata_channel *hwif) unsigned int basereg, d0_timings; #ifdef CONFIG_BLK_DEV_IDEDMA - hwif->XXX_udma = cs5530_dmaproc; + hwif->udma_setup = cs5530_udma_setup; hwif->highmem = 1; #else hwif->autodma = 0; diff --git a/drivers/ide/cy82c693.c b/drivers/ide/cy82c693.c index 2a3ee6e7f8a2..3855f8a98ddb 100644 --- a/drivers/ide/cy82c693.c +++ b/drivers/ide/cy82c693.c @@ -236,7 +236,7 @@ static void cy82c693_dma_enable(struct ata_device *drive, int mode, int single) /* * used to set DMA mode for CY82C693 (single and multi modes) */ -static int cy82c693_dmaproc(struct ata_device *drive) +static int cy82c693_udma_setup(struct ata_device *drive) { /* * Set dma mode for drive everything else is done by the defaul func. @@ -443,7 +443,7 @@ static void __init ide_init_cy82c693(struct ata_channel *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = cy82c693_dmaproc; + hwif->udma_setup = cy82c693_udma_setup; if (!noautodma) hwif->autodma = 1; } diff --git a/drivers/ide/hpt34x.c b/drivers/ide/hpt34x.c index 84c88bd2540f..9b45c6adfd4f 100644 --- a/drivers/ide/hpt34x.c +++ b/drivers/ide/hpt34x.c @@ -172,7 +172,7 @@ static int config_chipset_for_dma(struct ata_device *drive, u8 udma) return !hpt34x_tune_chipset(drive, mode); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int hpt34x_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 1; @@ -246,18 +246,23 @@ static int hpt34x_udma_stop(struct ata_device *drive) return (dma_stat & 7) != 4; /* verify good DMA status */ } -static int do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +static int hpt34x_udma_init(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; unsigned long dma_base = ch->dma_base; unsigned int count; + u8 cmd; if (!(count = udma_new_table(ch, rq))) return 1; /* try PIO instead of DMA */ - outl(ch->dmatable_dma, dma_base + 4); /* PRD table */ - reading |= 0x01; - outb(reading, dma_base); /* specify r/w */ + if (rq_data_dir(rq) == READ) + cmd = 0x09; + else + cmd = 0x01; + + outl(ch->dmatable_dma, dma_base + 4); /* PRD table */ + outb(cmd, dma_base); /* specify r/w */ outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */ drive->waiting_for_dma = 1; @@ -265,30 +270,10 @@ static int do_udma(unsigned int reading, struct ata_device *drive, struct reques return 0; ide_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */ - OUT_BYTE((reading == 9) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); + OUT_BYTE((cmd == 0x09) ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); return 0; } - -static int hpt34x_udma_read(struct ata_device *drive, struct request *rq) -{ - return do_udma(1 << 3, drive, rq); -} - -static int hpt34x_udma_write(struct ata_device *drive, struct request *rq) -{ - return do_udma(0, drive, rq); -} - -/* - * This is specific to the HPT343 UDMA bios-less chipset - * and HPT345 UDMA bios chipset (stamped HPT363) - * by HighPoint|Triones Technologies, Inc. - */ -static int hpt34x_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif /* @@ -356,9 +341,8 @@ static void __init ide_init_hpt34x(struct ata_channel *hwif) hwif->autodma = 0; hwif->udma_stop = hpt34x_udma_stop; - hwif->udma_read = hpt34x_udma_read; - hwif->udma_write = hpt34x_udma_write; - hwif->XXX_udma = hpt34x_dmaproc; + hwif->udma_init = hpt34x_udma_init; + hwif->udma_setup = hpt34x_udma_setup; hwif->highmem = 1; } else { hwif->drives[0].autotune = 1; diff --git a/drivers/ide/hpt366.c b/drivers/ide/hpt366.c index 2e8d63311d5a..a46993786585 100644 --- a/drivers/ide/hpt366.c +++ b/drivers/ide/hpt366.c @@ -836,7 +836,7 @@ static void hpt3xx_maskproc(struct ata_device *drive) } } -static int config_drive_xfer_rate(struct ata_device *drive) +static int hpt3xx_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 1; @@ -903,15 +903,6 @@ static void hpt366_udma_irq_lost(struct ata_device *drive) pci_write_config_byte(drive->channel->pci_dev, 0x5a, reg5ah & ~0x10); } -/* - * This is specific to the HPT366 UDMA bios chipset - * by HighPoint|Triones Technologies, Inc. - */ -static int hpt366_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} - static void do_udma_start(struct ata_device *drive) { struct ata_channel *ch = drive->channel; @@ -992,11 +983,6 @@ static int hpt370_udma_stop(struct ata_device *drive) return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } -static int hpt370_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} - static int hpt374_udma_stop(struct ata_device *drive) { struct ata_channel *ch = drive->channel; @@ -1019,11 +1005,6 @@ static int hpt374_udma_stop(struct ata_device *drive) return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } - -static int hpt374_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif /* @@ -1364,27 +1345,27 @@ static void __init hpt366_init_channel(struct ata_channel *ch) if (hpt_min_rev(dev, 7)) { ch->udma_stop = hpt374_udma_stop; - ch->XXX_udma = hpt374_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } else if (hpt_min_rev(dev, 5)) { ch->udma_stop = hpt374_udma_stop; - ch->XXX_udma = hpt374_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } else if (hpt_min_rev(dev, 3)) { ch->udma_start = hpt370_udma_start; ch->udma_stop = hpt370_udma_stop; ch->udma_timeout = hpt370_udma_timeout; ch->udma_irq_lost = hpt370_udma_irq_lost; - ch->XXX_udma = hpt370_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } } else if (hpt_min_rev(dev, 2)) { ch->udma_irq_lost = hpt366_udma_irq_lost; // ch->resetproc = hpt3xx_reset; // ch->busproc = hpt3xx_tristate; - ch->XXX_udma = hpt366_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } else { ch->udma_irq_lost = hpt366_udma_irq_lost; // ch->resetproc = hpt3xx_reset; // ch->busproc = hpt3xx_tristate; - ch->XXX_udma = hpt366_dmaproc; + ch->udma_setup = hpt3xx_udma_setup; } if (!noautodma) ch->autodma = 1; diff --git a/drivers/ide/icside.c b/drivers/ide/icside.c index d8d8fc55abf1..36bbf7c7ced3 100644 --- a/drivers/ide/icside.c +++ b/drivers/ide/icside.c @@ -544,7 +544,7 @@ static int icside_dma_read(struct ata_device *drive, struct request *rq) return 0; } -static int icside_dma_write(struct ata_device *drive, struct request *rq) +static int icside_dma_init(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; unsigned int cmd; @@ -612,12 +612,11 @@ static int icside_setup_dma(struct ata_channel *ch) ch->dmatable_cpu = NULL; ch->dmatable_dma = 0; ch->speedproc = icside_set_speed; - ch->XXX_udma = icside_dma_check; + ch->udma_setup = icside_dma_check; ch->udma_enable = icside_dma_enable; ch->udma_start = icside_dma_start; ch->udma_stop = icside_dma_stop; - ch->udma_read = icside_dma_read; - ch->udma_write = icside_dma_write; + ch->udma_init = icside_dma_init; ch->udma_irq_status = icside_irq_status; ch->udma_timeout = icside_dma_timeout; ch->udma_irq_lost = icside_irq_lost; diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c index 7ef13e954b38..38655801b504 100644 --- a/drivers/ide/ide-cd.c +++ b/drivers/ide/ide-cd.c @@ -736,10 +736,8 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, return startstop; if (info->dma) { - if (info->cmd == READ) - info->dma = !udma_read(drive, rq); - else if (info->cmd == WRITE) - info->dma = !udma_write(drive, rq); + if (info->cmd == READ || info->cmd == WRITE) + info->dma = !udma_init(drive, rq); else printk("ide-cd: DMA set, but not allowed\n"); } diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c index a90e4d45bef5..fedd801869d3 100644 --- a/drivers/ide/ide-disk.c +++ b/drivers/ide/ide-disk.c @@ -517,7 +517,7 @@ static int set_using_tcq(struct ata_device *drive, int arg) if (!drive->driver) return -EPERM; - if (!drive->channel->XXX_udma) + if (!drive->channel->udma_setup) return -EPERM; if (arg == drive->queue_depth && drive->using_tcq) @@ -629,7 +629,7 @@ static unsigned long native_max_address(struct ata_device *drive) ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.cmd & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { addr = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) @@ -657,7 +657,7 @@ static u64 native_max_address_ext(struct ata_device *drive) ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.cmd & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; @@ -696,7 +696,7 @@ static sector_t set_max_address(struct ata_device *drive, sector_t addr_req) /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, read new maximum address value */ - if ((args.cmd & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { addr_set = ((args.taskfile.device_head & 0x0f) << 24) | (args.taskfile.high_cylinder << 16) | (args.taskfile.low_cylinder << 8) @@ -731,7 +731,7 @@ static u64 set_max_address_ext(struct ata_device *drive, u64 addr_req) /* submit command request */ ide_raw_taskfile(drive, &args); /* if OK, compute maximum address value */ - if ((args.cmd & 0x01) == 0) { + if (!(drive->status & ERR_STAT)) { u32 high = (args.hobfile.high_cylinder << 16) | (args.hobfile.low_cylinder << 8) | args.hobfile.sector_number; diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c index ce9281a2db20..19d1a246cb33 100644 --- a/drivers/ide/ide-floppy.c +++ b/drivers/ide/ide-floppy.c @@ -1060,12 +1060,8 @@ static ide_startstop_t idefloppy_issue_pc(struct ata_device *drive, struct reque if (test_and_clear_bit (PC_DMA_ERROR, &pc->flags)) udma_enable(drive, 0, 1); - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit (PC_WRITING, &pc->flags)) - dma_ok = !udma_write(drive, rq); - else - dma_ok = !udma_read(drive, rq); - } + if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + dma_ok = !udma_init(drive, rq); #endif ata_irq_enable(drive, 1); diff --git a/drivers/ide/ide-pmac.c b/drivers/ide/ide-pmac.c index fe187b2532f1..56631392f933 100644 --- a/drivers/ide/ide-pmac.c +++ b/drivers/ide/ide-pmac.c @@ -260,11 +260,9 @@ static void pmac_ide_setup_dma(struct device_node *np, int ix); static void pmac_udma_enable(struct ata_device *drive, int on, int verbose); static int pmac_udma_start(struct ata_device *drive, struct request *rq); static int pmac_udma_stop(struct ata_device *drive); -static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq); -static int pmac_udma_read(struct ata_device *drive, struct request *rq); -static int pmac_udma_write(struct ata_device *drive, struct request *rq); +static int pmac_udma_init(struct ata_device *drive, struct request *rq); static int pmac_udma_irq_status(struct ata_device *drive); -static int pmac_ide_dmaproc(struct ata_device *drive); +static int pmac_udma_setup(struct ata_device *drive); static int pmac_ide_build_dmatable(struct ata_device *drive, struct request *rq, int ix, int wr); static int pmac_ide_tune_chipset(struct ata_device *drive, byte speed); static void pmac_ide_tuneproc(struct ata_device *drive, byte pio); @@ -334,10 +332,9 @@ pmac_ide_init_hwif_ports(hw_regs_t *hw, ide_hwifs[ix].udma_enable = pmac_udma_enable; ide_hwifs[ix].udma_start = pmac_udma_start; ide_hwifs[ix].udma_stop = pmac_udma_stop; - ide_hwifs[ix].udma_read = pmac_udma_read; - ide_hwifs[ix].udma_write = pmac_udma_write; + ide_hwifs[ix].udma_init = pmac_udma_init; ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status; - ide_hwifs[ix].XXX_udma = pmac_ide_dmaproc; + ide_hwifs[ix].udma_setup = pmac_udma_setup; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO if (!noautodma) ide_hwifs[ix].autodma = 1; @@ -1043,10 +1040,9 @@ pmac_ide_setup_dma(struct device_node *np, int ix) ide_hwifs[ix].udma_enable = pmac_udma_enable; ide_hwifs[ix].udma_start = pmac_udma_start; ide_hwifs[ix].udma_stop = pmac_udma_stop; - ide_hwifs[ix].udma_read = pmac_udma_read; - ide_hwifs[ix].udma_write = pmac_udma_write; + ide_hwifs[ix].udma_init = pmac_udma_init; ide_hwifs[ix].udma_irq_status = pmac_udma_irq_status; - ide_hwifs[ix].XXX_udma = pmac_ide_dmaproc; + ide_hwifs[ix].udma_setup = pmac_udma_setup; #ifdef CONFIG_BLK_DEV_IDEDMA_PMAC_AUTO if (!noautodma) ide_hwifs[ix].autodma = 1; @@ -1405,11 +1401,12 @@ static int pmac_udma_stop(struct ata_device *drive) return (dstat & (RUN|DEAD|ACTIVE)) != RUN; } -static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +static int pmac_udma_init(struct ata_device *drive, struct request *rq) { int ix, ata4; volatile struct dbdma_regs *dma; - byte unit = (drive->select.b.unit & 0x01); + u8 unit = (drive->select.b.unit & 0x01); + int reading; /* Can we stuff a pointer to our intf structure in config_data * or select_data in hwif ? @@ -1417,6 +1414,12 @@ static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct r ix = pmac_ide_find(drive); if (ix < 0) return 0; + + if (rq_data_dir(rq) == READ) + reading = 1; + else + reading = 0; + dma = pmac_ide[ix].dma_regs; ata4 = (pmac_ide[ix].kind == controller_kl_ata4 || pmac_ide[ix].kind == controller_kl_ata4_80); @@ -1447,16 +1450,6 @@ static int pmac_do_udma(unsigned int reading, struct ata_device *drive, struct r return udma_start(drive, rq); } -static int pmac_udma_read(struct ata_device *drive, struct request *rq) -{ - return pmac_do_udma(1, drive, rq); -} - -static int pmac_udma_write(struct ata_device *drive, struct request *rq) -{ - return pmac_do_udma(0, drive, rq); -} - /* * FIXME: This should be attached to a channel as we can see now! */ @@ -1514,7 +1507,7 @@ static int pmac_udma_irq_status(struct ata_device *drive) return 0; } -static int pmac_ide_dmaproc(struct ata_device *drive) +static int pmac_udma_setup(struct ata_device *drive) { /* Change this to better match ide-dma.c */ pmac_ide_check_dma(drive); diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c index bb4beecb858a..91a979252d48 100644 --- a/drivers/ide/ide-tape.c +++ b/drivers/ide/ide-tape.c @@ -2258,12 +2258,8 @@ static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, printk (KERN_WARNING "ide-tape: DMA disabled, reverting to PIO\n"); udma_enable(drive, 0, 1); } - if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) { - if (test_bit (PC_WRITING, &pc->flags)) - dma_ok = !udma_write(drive, rq); - else - dma_ok = !udma_read(drive, rq); - } + if (test_bit (PC_DMA_RECOMMENDED, &pc->flags) && drive->using_dma) + dma_ok = !udma_init(drive, rq); #endif ata_irq_enable(drive, 1); diff --git a/drivers/ide/ide-taskfile.c b/drivers/ide/ide-taskfile.c index 79a4cf8fbcca..2e2db55d9774 100644 --- a/drivers/ide/ide-taskfile.c +++ b/drivers/ide/ide-taskfile.c @@ -350,19 +350,19 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, return ar->prehandler(drive, rq); } else { /* - * FIXME: this is a gross hack, need to unify tcq dma proc and - * regular dma proc. + * FIXME: This is a gross hack, need to unify tcq dma proc and + * regular dma proc. It should now be easier. */ if (!drive->using_dma) return ide_started; /* for dma commands we don't set the handler */ - if (ar->cmd == WIN_WRITEDMA || ar->cmd == WIN_WRITEDMA_EXT) - return !udma_write(drive, rq); - else if (ar->cmd == WIN_READDMA + if (ar->cmd == WIN_WRITEDMA + || ar->cmd == WIN_WRITEDMA_EXT + || ar->cmd == WIN_READDMA || ar->cmd == WIN_READDMA_EXT) - return !udma_read(drive, rq); + return !udma_init(drive, rq); #ifdef CONFIG_BLK_DEV_IDE_TCQ else if (ar->cmd == WIN_WRITEDMA_QUEUED || ar->cmd == WIN_WRITEDMA_QUEUED_EXT @@ -371,7 +371,7 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, return udma_tcq_taskfile(drive, rq); #endif else { - printk("ata_taskfile: unknown command %x\n", ar->cmd); + printk(KERN_ERR "%s: unknown command %x\n", __FUNCTION__, ar->cmd); return ide_stopped; } } @@ -556,31 +556,28 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request * more data left */ ide_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); + return ide_started; } /* Called to figure out the type of command being called. */ -void ide_cmd_type_parser(struct ata_taskfile *args) +void ide_cmd_type_parser(struct ata_taskfile *ar) { - struct hd_drive_task_hdr *taskfile = &args->taskfile; + struct hd_drive_task_hdr *taskfile = &ar->taskfile; - args->prehandler = NULL; - args->handler = NULL; + ar->prehandler = NULL; + ar->handler = NULL; - switch (args->cmd) { + switch (ar->cmd) { case WIN_IDENTIFY: case WIN_PIDENTIFY: - args->handler = task_in_intr; - args->command_type = IDE_DRIVE_TASK_IN; - return; - case CFA_TRANSLATE_SECTOR: case WIN_READ: case WIN_READ_EXT: case WIN_READ_BUFFER: - args->handler = task_in_intr; - args->command_type = IDE_DRIVE_TASK_IN; + ar->handler = task_in_intr; + ar->command_type = IDE_DRIVE_TASK_IN; return; case CFA_WRITE_SECT_WO_ERASE: @@ -589,56 +586,56 @@ void ide_cmd_type_parser(struct ata_taskfile *args) case WIN_WRITE_VERIFY: case WIN_WRITE_BUFFER: case WIN_DOWNLOAD_MICROCODE: - args->prehandler = pre_task_out_intr; - args->handler = task_out_intr; - args->command_type = IDE_DRIVE_TASK_RAW_WRITE; + ar->prehandler = pre_task_out_intr; + ar->handler = task_out_intr; + ar->command_type = IDE_DRIVE_TASK_RAW_WRITE; return; case WIN_MULTREAD: case WIN_MULTREAD_EXT: - args->handler = task_mulin_intr; - args->command_type = IDE_DRIVE_TASK_IN; + ar->handler = task_mulin_intr; + ar->command_type = IDE_DRIVE_TASK_IN; return; case CFA_WRITE_MULTI_WO_ERASE: case WIN_MULTWRITE: case WIN_MULTWRITE_EXT: - args->prehandler = pre_task_mulout_intr; - args->handler = task_mulout_intr; - args->command_type = IDE_DRIVE_TASK_RAW_WRITE; + ar->prehandler = pre_task_mulout_intr; + ar->handler = task_mulout_intr; + ar->command_type = IDE_DRIVE_TASK_RAW_WRITE; return; case WIN_SECURITY_DISABLE: case WIN_SECURITY_ERASE_UNIT: case WIN_SECURITY_SET_PASS: case WIN_SECURITY_UNLOCK: - args->handler = task_out_intr; - args->command_type = IDE_DRIVE_TASK_OUT; + ar->handler = task_out_intr; + ar->command_type = IDE_DRIVE_TASK_OUT; return; case WIN_SMART: if (taskfile->feature == SMART_WRITE_LOG_SECTOR) - args->prehandler = pre_task_out_intr; + ar->prehandler = pre_task_out_intr; - args->taskfile.low_cylinder = SMART_LCYL_PASS; - args->taskfile.high_cylinder = SMART_HCYL_PASS; + ar->taskfile.low_cylinder = SMART_LCYL_PASS; + ar->taskfile.high_cylinder = SMART_HCYL_PASS; - switch(args->taskfile.feature) { + switch(ar->taskfile.feature) { case SMART_READ_VALUES: case SMART_READ_THRESHOLDS: case SMART_READ_LOG_SECTOR: - args->handler = task_in_intr; - args->command_type = IDE_DRIVE_TASK_IN; + ar->handler = task_in_intr; + ar->command_type = IDE_DRIVE_TASK_IN; return; case SMART_WRITE_LOG_SECTOR: - args->handler = task_out_intr; - args->command_type = IDE_DRIVE_TASK_OUT; + ar->handler = task_out_intr; + ar->command_type = IDE_DRIVE_TASK_OUT; return; default: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = task_no_data_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; } @@ -648,22 +645,22 @@ void ide_cmd_type_parser(struct ata_taskfile *args) case WIN_READDMA_QUEUED: case WIN_READDMA_EXT: case WIN_READDMA_QUEUED_EXT: - args->command_type = IDE_DRIVE_TASK_IN; + ar->command_type = IDE_DRIVE_TASK_IN; return; case WIN_WRITEDMA: case WIN_WRITEDMA_QUEUED: case WIN_WRITEDMA_EXT: case WIN_WRITEDMA_QUEUED_EXT: - args->command_type = IDE_DRIVE_TASK_RAW_WRITE; + ar->command_type = IDE_DRIVE_TASK_RAW_WRITE; return; #endif case WIN_SETFEATURES: - args->handler = task_no_data_intr; - switch(args->taskfile.feature) { + ar->handler = task_no_data_intr; + switch (ar->taskfile.feature) { case SETFEATURES_XFER: - args->command_type = IDE_DRIVE_TASK_SET_XFER; + ar->command_type = IDE_DRIVE_TASK_SET_XFER; return; case SETFEATURES_DIS_DEFECT: case SETFEATURES_EN_APM: @@ -681,18 +678,18 @@ void ide_cmd_type_parser(struct ata_taskfile *args) case SETFEATURES_DIS_RI: case SETFEATURES_DIS_SI: default: - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; } case WIN_SPECIFY: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = task_no_data_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; case WIN_RESTORE: - args->handler = recal_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = recal_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; case WIN_DIAGNOSE: @@ -722,19 +719,10 @@ void ide_cmd_type_parser(struct ata_taskfile *args) case WIN_DOORUNLOCK: case DISABLE_SEAGATE: case EXABYTE_ENABLE_NEST: - - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - return; - case WIN_SETMULT: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; - return; - case WIN_NOP: - args->handler = task_no_data_intr; - args->command_type = IDE_DRIVE_TASK_NO_DATA; + ar->handler = task_no_data_intr; + ar->command_type = IDE_DRIVE_TASK_NO_DATA; return; case WIN_FORMAT: @@ -743,7 +731,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args) case WIN_QUEUED_SERVICE: case WIN_PACKETCMD: default: - args->command_type = IDE_DRIVE_TASK_INVALID; + ar->command_type = IDE_DRIVE_TASK_INVALID; return; } } diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 652bce83da59..b3245c977552 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -184,31 +184,6 @@ void ide_set_handler(struct ata_device *drive, ata_handler_t handler, spin_unlock_irqrestore(ch->lock, flags); } -static u8 auto_reduce_xfer(struct ata_device *drive) -{ - if (!drive->crc_count) - return drive->current_speed; - drive->crc_count = 0; - - switch(drive->current_speed) { - case XFER_UDMA_7: return XFER_UDMA_6; - case XFER_UDMA_6: return XFER_UDMA_5; - case XFER_UDMA_5: return XFER_UDMA_4; - case XFER_UDMA_4: return XFER_UDMA_3; - case XFER_UDMA_3: return XFER_UDMA_2; - case XFER_UDMA_2: return XFER_UDMA_1; - case XFER_UDMA_1: return XFER_UDMA_0; - /* - * OOPS we do not goto non Ultra DMA modes - * without iCRC's available we force - * the system to PIO and make the user - * invoke the ATA-1 ATA-2 DMA modes. - */ - case XFER_UDMA_0: - default: return XFER_PIO_4; - } -} - static void check_crc_errors(struct ata_device *drive) { if (!drive->using_dma) @@ -218,7 +193,34 @@ static void check_crc_errors(struct ata_device *drive) if (drive->crc_count) { udma_enable(drive, 0, 0); if (drive->channel->speedproc) { - u8 pio = auto_reduce_xfer(drive); + u8 pio = XFER_PIO_4; + drive->crc_count = 0; + + switch (drive->current_speed) { + case XFER_UDMA_7: pio = XFER_UDMA_6; + break; + case XFER_UDMA_6: pio = XFER_UDMA_5; + break; + case XFER_UDMA_5: pio = XFER_UDMA_4; + break; + case XFER_UDMA_4: pio = XFER_UDMA_3; + break; + case XFER_UDMA_3: pio = XFER_UDMA_2; + break; + case XFER_UDMA_2: pio = XFER_UDMA_1; + break; + case XFER_UDMA_1: pio = XFER_UDMA_0; + break; + /* + * OOPS we do not goto non Ultra DMA modes + * without iCRC's available we force + * the system to PIO and make the user + * invoke the ATA-1 ATA-2 DMA modes. + */ + case XFER_UDMA_0: + default: + pio = XFER_PIO_4; + } drive->channel->speedproc(drive, pio); } if (drive->current_speed >= XFER_SW_DMA_0) @@ -408,7 +410,6 @@ void ide_end_drive_cmd(struct ata_device *drive, struct request *rq) ar->taskfile.low_cylinder = IN_BYTE(IDE_LCYL_REG); ar->taskfile.high_cylinder = IN_BYTE(IDE_HCYL_REG); ar->taskfile.device_head = IN_BYTE(IDE_SELECT_REG); - ar->cmd = drive->status; if ((drive->id->command_set_2 & 0x0400) && (drive->id->cfs_enable_2 & 0x0400) && (drive->addressing == 1)) { diff --git a/drivers/ide/ioctl.c b/drivers/ide/ioctl.c index d8b355e76143..21262246008b 100644 --- a/drivers/ide/ioctl.c +++ b/drivers/ide/ioctl.c @@ -235,7 +235,7 @@ int ata_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned if (!drive->driver) return -EPERM; - if (!drive->id || !(drive->id->capability & 1) || !drive->channel->XXX_udma) + if (!drive->id || !(drive->id->capability & 1) || !drive->channel->udma_setup) return -EPERM; if (ide_spin_wait_hwgroup(drive)) diff --git a/drivers/ide/main.c b/drivers/ide/main.c index 46f40d44aa71..769690addae6 100644 --- a/drivers/ide/main.c +++ b/drivers/ide/main.c @@ -520,12 +520,11 @@ void ide_unregister(struct ata_channel *ch) ch->ata_write = old.ata_write; ch->atapi_read = old.atapi_read; ch->atapi_write = old.atapi_write; - ch->XXX_udma = old.XXX_udma; + ch->udma_setup = old.udma_setup; ch->udma_enable = old.udma_enable; ch->udma_start = old.udma_start; ch->udma_stop = old.udma_stop; - ch->udma_read = old.udma_read; - ch->udma_write = old.udma_write; + ch->udma_init = old.udma_init; ch->udma_irq_status = old.udma_irq_status; ch->udma_timeout = old.udma_timeout; ch->udma_irq_lost = old.udma_irq_lost; @@ -1092,7 +1091,7 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv spin_unlock_irqrestore(&ide_lock, flags); /* Default autotune or requested autotune */ if (drive->autotune != 2) { - if (drive->channel->XXX_udma) { + if (drive->channel->udma_setup) { /* * Force DMAing for the beginning of the check. Some @@ -1103,7 +1102,7 @@ int ide_register_subdriver(struct ata_device *drive, struct ata_operations *driv */ udma_enable(drive, 0, 0); - drive->channel->XXX_udma(drive); + drive->channel->udma_setup(drive); #ifdef CONFIG_BLK_DEV_IDE_TCQ_DEFAULT udma_tcq_enable(drive, 1); #endif diff --git a/drivers/ide/ns87415.c b/drivers/ide/ns87415.c index 0f50038017e2..3247a51aae57 100644 --- a/drivers/ide/ns87415.c +++ b/drivers/ide/ns87415.c @@ -101,11 +101,11 @@ static int ns87415_udma_stop(struct ata_device *drive) } -static int ns87415_udma_read(struct ata_device *drive, struct request *rq) +static int ns87415_udma_init(struct ata_device *drive, struct request *rq) { ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - if (!ata_do_udma(1, drive, rq)) /* use standard DMA stuff */ + if (!udma_pci_init(drive, rq)) /* use standard DMA stuff */ return 0; ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ @@ -113,26 +113,14 @@ static int ns87415_udma_read(struct ata_device *drive, struct request *rq) return 1; } -static int ns87415_udma_write(struct ata_device *drive, struct request *rq) -{ - ns87415_prepare_drive(drive, 1); /* select DMA xfer */ - - if (!ata_do_udma(0, drive, rq)) /* use standard DMA stuff */ - return 0; - - ns87415_prepare_drive(drive, 0); /* DMA failed: select PIO xfer */ - - return 1; -} - -static int ns87415_dmaproc(struct ata_device *drive) +static int ns87415_udma_setup(struct ata_device *drive) { if (drive->type != ATA_DISK) { udma_enable(drive, 0, 0); return 0; } - return XXX_ide_dmaproc(drive); + return udma_pci_setup(drive); } #endif @@ -218,9 +206,8 @@ static void __init ide_init_ns87415(struct ata_channel *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->udma_stop = ns87415_udma_stop; - hwif->udma_read = ns87415_udma_read; - hwif->udma_write = ns87415_udma_write; - hwif->XXX_udma = ns87415_dmaproc; + hwif->udma_init = ns87415_udma_init; + hwif->udma_setup = ns87415_udma_setup; } #endif diff --git a/drivers/ide/pcidma.c b/drivers/ide/pcidma.c index 0a51f1863fc5..346fba58c643 100644 --- a/drivers/ide/pcidma.c +++ b/drivers/ide/pcidma.c @@ -164,7 +164,7 @@ int ata_start_dma(struct ata_device *drive, struct request *rq) /* * Configure a device for DMA operation. */ -int XXX_ide_dmaproc(struct ata_device *drive) +int udma_pci_setup(struct ata_device *drive) { int config_allows_dma = 1; struct hd_driveid *id = drive->id; @@ -427,16 +427,6 @@ int udma_pci_stop(struct ata_device *drive) return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } -int udma_pci_read(struct ata_device *drive, struct request *rq) -{ - return ata_do_udma(1, drive, rq); -} - -int udma_pci_write(struct ata_device *drive, struct request *rq) -{ - return ata_do_udma(0, drive, rq); -} - /* * FIXME: This should be attached to a channel as we can see now! */ @@ -490,18 +480,16 @@ void ata_init_dma(struct ata_channel *ch, unsigned long dma_base) * We could just assign them, and then leave it up to the chipset * specific code to override these after they've called this function. */ - if (!ch->XXX_udma) - ch->XXX_udma = XXX_ide_dmaproc; + if (!ch->udma_setup) + ch->udma_setup = udma_pci_setup; if (!ch->udma_enable) ch->udma_enable = udma_pci_enable; if (!ch->udma_start) ch->udma_start = udma_pci_start; if (!ch->udma_stop) ch->udma_stop = udma_pci_stop; - if (!ch->udma_read) - ch->udma_read = udma_pci_read; - if (!ch->udma_write) - ch->udma_write = udma_pci_write; + if (!ch->udma_init) + ch->udma_init = udma_pci_init; if (!ch->udma_irq_status) ch->udma_irq_status = udma_pci_irq_status; if (!ch->udma_timeout) @@ -528,16 +516,20 @@ dma_alloc_failure: * It's exported only for host chips which use it for fallback or (too) late * capability checking. */ - -int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +int udma_pci_init(struct ata_device *drive, struct request *rq) { + u8 cmd; + if (ata_start_dma(drive, rq)) return 1; if (drive->type != ATA_DISK) return 0; - reading <<= 3; + if (rq_data_dir(rq) == READ) + cmd = 0x08; + else + cmd = 0x00; ide_set_handler(drive, ide_dma_intr, WAIT_CMD, dma_timer_expiry); /* issue cmd to drive */ if ((rq->flags & REQ_DRIVE_ACB) && (drive->addressing == 1)) { @@ -545,22 +537,19 @@ int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request * struct ata_taskfile *args = rq->special; outb(args->cmd, IDE_COMMAND_REG); - } else if (drive->addressing) { - outb(reading ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); - } else { - outb(reading ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); - } + } else if (drive->addressing) + outb(cmd ? WIN_READDMA_EXT : WIN_WRITEDMA_EXT, IDE_COMMAND_REG); + else + outb(cmd ? WIN_READDMA : WIN_WRITEDMA, IDE_COMMAND_REG); return udma_start(drive, rq); } -EXPORT_SYMBOL(ata_do_udma); EXPORT_SYMBOL(ide_dma_intr); EXPORT_SYMBOL(udma_pci_enable); EXPORT_SYMBOL(udma_pci_start); EXPORT_SYMBOL(udma_pci_stop); -EXPORT_SYMBOL(udma_pci_read); -EXPORT_SYMBOL(udma_pci_write); +EXPORT_SYMBOL(udma_pci_init); EXPORT_SYMBOL(udma_pci_irq_status); EXPORT_SYMBOL(udma_pci_timeout); EXPORT_SYMBOL(udma_pci_irq_lost); diff --git a/drivers/ide/pdc202xx.c b/drivers/ide/pdc202xx.c index 839682eced98..e39249907b43 100644 --- a/drivers/ide/pdc202xx.c +++ b/drivers/ide/pdc202xx.c @@ -563,7 +563,7 @@ chipset_is_set: return !(hwif->speedproc(drive, mode)); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int pdc202xx_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; struct ata_channel *hwif = drive->channel; @@ -670,7 +670,7 @@ static int pdc202xx_udma_irq_status(struct ata_device *drive) return (dma_stat & 4) == 4; /* return 1 if INTR asserted */ } -static void pdc202xx_bug (struct ata_device *drive) +static void pdc202xx_bug(struct ata_device *drive) { if (!drive->channel->resetproc) return; @@ -678,10 +678,6 @@ static void pdc202xx_bug (struct ata_device *drive) drive->channel->resetproc(drive); } -static int pdc202xx_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif void pdc202xx_new_reset(struct ata_device *drive) @@ -838,7 +834,7 @@ static void __init ide_init_pdc202xx(struct ata_channel *hwif) if (hwif->dma_base) { hwif->udma_irq_lost = pdc202xx_bug; hwif->udma_timeout = pdc202xx_bug; - hwif->XXX_udma = pdc202xx_dmaproc; + hwif->udma_setup = pdc202xx_udma_setup; hwif->highmem = 1; if (!noautodma) hwif->autodma = 1; diff --git a/drivers/ide/pdc4030.c b/drivers/ide/pdc4030.c index 893764a5da7a..30d920893a69 100644 --- a/drivers/ide/pdc4030.c +++ b/drivers/ide/pdc4030.c @@ -619,16 +619,11 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg return ide_stopped; } - ata_irq_enable(drive, 1); /* clear nIEN */ + ata_irq_enable(drive, 1); ata_mask(drive); - outb(taskfile->feature, IDE_FEATURE_REG); - outb(taskfile->sector_count, IDE_NSECTOR_REG); - /* refers to number of sectors to transfer */ - outb(taskfile->sector_number, IDE_SECTOR_REG); - /* refers to sector offset or start sector */ - outb(taskfile->low_cylinder, IDE_LCYL_REG); - outb(taskfile->high_cylinder, IDE_HCYL_REG); + ata_out_regfile(drive, taskfile); + outb(taskfile->device_head, IDE_SELECT_REG); outb(args->cmd, IDE_COMMAND_REG); @@ -708,14 +703,9 @@ ide_startstop_t promise_do_request(struct ata_device *drive, struct request *rq, args.taskfile.low_cylinder = (block>>=8); args.taskfile.high_cylinder = (block>>=8); args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all; - args.cmd = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE; - - /* We can't call ide_cmd_type_parser here, since it won't understand - our command, but that doesn't matter, since we don't use the - generic interrupt handlers either. Setup the bits of args that we - will need. */ - args.handler = NULL; - rq->special = &args; + args.cmd = (rq_data_dir(rq) == READ) ? PROMISE_READ : PROMISE_WRITE; + args.handler = NULL; + rq->special = &args; return do_pdc4030_io(drive, &args, rq); } diff --git a/drivers/ide/piix.c b/drivers/ide/piix.c index f937dc9d1965..47d8ab15b50e 100644 --- a/drivers/ide/piix.c +++ b/drivers/ide/piix.c @@ -253,7 +253,7 @@ static void piix_tune_drive(struct ata_device *drive, unsigned char pio) #ifdef CONFIG_BLK_DEV_IDEDMA -int piix_dmaproc(struct ata_device *drive) +static int piix_udma_setup(struct ata_device *drive) { short w80 = drive->channel->udma_four; @@ -399,7 +399,7 @@ static void __init piix_init_channel(struct ata_channel *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = piix_dmaproc; + hwif->udma_setup = piix_udma_setup; # ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; diff --git a/drivers/ide/serverworks.c b/drivers/ide/serverworks.c index f8dd45da13a7..f69f12630a22 100644 --- a/drivers/ide/serverworks.c +++ b/drivers/ide/serverworks.c @@ -290,7 +290,7 @@ static int config_chipset_for_dma(struct ata_device *drive) return !svwks_tune_chipset(drive, mode); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int svwks_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 1; @@ -387,11 +387,6 @@ static int svwks_udma_stop(struct ata_device *drive) return (dma_stat & 7) != 4 ? (0x10 | dma_stat) : 0; /* verify good DMA status */ } - -static int svwks_dmaproc(struct ata_device *drive) -{ - return config_drive_xfer_rate(drive); -} #endif static unsigned int __init svwks_init_chipset(struct pci_dev *dev) @@ -506,7 +501,7 @@ static void __init ide_init_svwks(struct ata_channel *hwif) hwif->autodma = 1; #endif hwif->udma_stop = svwks_udma_stop; - hwif->XXX_udma = svwks_dmaproc; + hwif->udma_setup = svwks_udma_setup; hwif->highmem = 1; } else { hwif->autodma = 0; diff --git a/drivers/ide/sis5513.c b/drivers/ide/sis5513.c index b8697d6a51b1..e677d1e53311 100644 --- a/drivers/ide/sis5513.c +++ b/drivers/ide/sis5513.c @@ -466,12 +466,14 @@ static int config_chipset_for_dma(struct ata_device *drive, u8 udma) return !sis5513_tune_chipset(drive, mode); } -static int config_drive_xfer_rate(struct ata_device *drive) +static int sis5513_udma_setup(struct ata_device *drive) { struct hd_driveid *id = drive->id; int on = 0; int verbose = 1; + config_drive_art_rwp(drive); + config_art_rwp_pio(drive, 5); config_chipset_for_pio(drive, 5); if (id && (id->capability & 1) && drive->channel->autodma) { @@ -520,14 +522,6 @@ no_dma_set: return 0; } - -static int sis5513_dmaproc(struct ata_device *drive) -{ - config_drive_art_rwp(drive); - config_art_rwp_pio(drive, 5); - - return config_drive_xfer_rate(drive); -} #endif /* Chip detection and general config */ @@ -633,7 +627,7 @@ static void __init ide_init_sis5513(struct ata_channel *hwif) if (chipset_family > ATA_16) { hwif->autodma = noautodma ? 0 : 1; hwif->highmem = 1; - hwif->XXX_udma = sis5513_dmaproc; + hwif->udma_setup = sis5513_udma_setup; } else { #endif hwif->autodma = 0; diff --git a/drivers/ide/sl82c105.c b/drivers/ide/sl82c105.c index 47fe6394b953..0a450c16b450 100644 --- a/drivers/ide/sl82c105.c +++ b/drivers/ide/sl82c105.c @@ -130,7 +130,7 @@ static int config_for_dma(struct ata_device *drive) * Check to see if the drive and * chipset is capable of DMA mode */ -static int sl82c105_check_drive(struct ata_device *drive) +static int sl82c105_dma_setup(struct ata_device *drive) { int on = 0; @@ -172,15 +172,6 @@ static int sl82c105_check_drive(struct ata_device *drive) return 0; } -/* - * Our very own dmaproc. We need to intercept various calls - * to fix up the SL82C105 specific behaviour. - */ -static int sl82c105_dmaproc(struct ata_device *drive) -{ - return sl82c105_check_drive(drive); -} - /* * The SL82C105 holds off all IDE interrupts while in DMA mode until * all DMA activity is completed. Sometimes this causes problems (eg, @@ -215,16 +206,10 @@ static void sl82c105_dma_enable(struct ata_device *drive, int on, int verbose) * The generic IDE core will have disabled the BMEN bit before this * function is called. */ -static int sl82c105_dma_read(struct ata_device *drive, struct request *rq) -{ - sl82c105_reset_host(drive->channel->pci_dev); - return udma_pci_read(drive, rq); -} - -static int sl82c105_dma_write(struct ata_device *drive, struct request *rq) +static int sl82c105_dma_init(struct ata_device *drive, struct request *rq) { sl82c105_reset_host(drive->channel->pci_dev); - return udma_pci_write(drive, rq); + return udma_pci_init(drive, rq); } static void sl82c105_timeout(struct ata_device *drive) @@ -354,12 +339,11 @@ static void __init sl82c105_init_dma(struct ata_channel *ch, unsigned long dma_b ata_init_dma(ch, dma_base); if (bridge_rev <= 5) - ch->XXX_udma = NULL; + ch->udma_setup = NULL; else { - ch->XXX_udma = sl82c105_dmaproc; + ch->udma_setup = sl82c105_dma_setup; ch->udma_enable = sl82c105_dma_enable; - ch->udma_read = sl82c105_dma_read; - ch->udma_write = sl82c105_dma_write; + ch->udma_init = sl82c105_dma_init; ch->udma_timeout = sl82c105_timeout; ch->udma_irq_lost = sl82c105_lostirq; } diff --git a/drivers/ide/trm290.c b/drivers/ide/trm290.c index d8a0e316ac44..fe918bb09263 100644 --- a/drivers/ide/trm290.c +++ b/drivers/ide/trm290.c @@ -191,10 +191,18 @@ static int trm290_udma_stop(struct ata_device *drive) return (inw(ch->dma_base + 2) != 0x00ff); } -static int do_udma(unsigned int reading, struct ata_device *drive, struct request *rq) +static int trm290_udma_init(struct ata_device *drive, struct request *rq) { struct ata_channel *ch = drive->channel; - unsigned int count, writing; + unsigned int count; + int writing; + int reading; + + + if (rq_data_dir(rq) == READ) + reading = 1; + else + reading = 0; if (!reading) { reading = 0; @@ -228,24 +236,14 @@ static int do_udma(unsigned int reading, struct ata_device *drive, struct reques return 0; } -static int trm290_udma_read(struct ata_device *drive, struct request *rq) -{ - return do_udma(1, drive, rq); -} - -static int trm290_udma_write(struct ata_device *drive, struct request *rq) -{ - return do_udma(0, drive, rq); -} - static int trm290_udma_irq_status(struct ata_device *drive) { return (inw(drive->channel->dma_base + 2) == 0x00ff); } -static int trm290_dmaproc(struct ata_device *drive) +static int trm290_udma_setup(struct ata_device *drive) { - return XXX_ide_dmaproc(drive); + return udma_pci_setup(drive); } #endif @@ -301,10 +299,9 @@ static void __init trm290_init_channel(struct ata_channel *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA hwif->udma_start = trm290_udma_start; hwif->udma_stop = trm290_udma_stop; - hwif->udma_read = trm290_udma_read; - hwif->udma_write = trm290_udma_write; + hwif->udma_init = trm290_udma_init; hwif->udma_irq_status = trm290_udma_irq_status; - hwif->XXX_udma = trm290_dmaproc; + hwif->udma_setup = trm290_udma_setup; #endif hwif->selectproc = &trm290_selectproc; diff --git a/drivers/ide/via82cxxx.c b/drivers/ide/via82cxxx.c index c0be5c205f1d..8c8214dcd5b0 100644 --- a/drivers/ide/via82cxxx.c +++ b/drivers/ide/via82cxxx.c @@ -223,7 +223,7 @@ static void via82cxxx_tune_drive(struct ata_device *drive, unsigned char pio) } #ifdef CONFIG_BLK_DEV_IDEDMA -static int via82cxxx_dmaproc(struct ata_device *drive) +static int via82cxxx_udma_setup(struct ata_device *drive) { short w80 = drive->channel->udma_four; @@ -368,7 +368,7 @@ static void __init via82cxxx_init_channel(struct ata_channel *hwif) #ifdef CONFIG_BLK_DEV_IDEDMA if (hwif->dma_base) { hwif->highmem = 1; - hwif->XXX_udma = &via82cxxx_dmaproc; + hwif->udma_setup = via82cxxx_udma_setup; # ifdef CONFIG_IDEDMA_AUTO if (!noautodma) hwif->autodma = 1; diff --git a/drivers/scsi/ide-scsi.c b/drivers/scsi/ide-scsi.c index cf44a6f975dc..d14c7740452c 100644 --- a/drivers/scsi/ide-scsi.c +++ b/drivers/scsi/ide-scsi.c @@ -407,12 +407,8 @@ static ide_startstop_t idescsi_issue_pc(struct ata_device *drive, struct request pc->current_position=pc->buffer; bcount = min(pc->request_transfer, 63 * 1024); /* Request to transfer the entire buffer at once */ - if (drive->using_dma && rq->bio) { - if (test_bit (PC_WRITING, &pc->flags)) - dma_ok = !udma_write(drive, rq); - else - dma_ok = !udma_read(drive, rq); - } + if (drive->using_dma && rq->bio) + dma_ok = !udma_init(drive, rq); ata_select(drive, 10); ata_irq_enable(drive, 1); diff --git a/include/linux/ide.h b/include/linux/ide.h index 9c289abd3ccc..24f5ce47a19d 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h @@ -425,7 +425,7 @@ struct ata_channel { * mode itself. */ - /* setup disk on a channel for a particular transfer mode */ + /* setup disk on a channel for a particular PIO transfer mode */ void (*tuneproc) (struct ata_device *, byte pio); /* setup the chipset timing for a particular transfer mode */ @@ -455,18 +455,13 @@ struct ata_channel { void (*atapi_read)(struct ata_device *, void *, unsigned int); void (*atapi_write)(struct ata_device *, void *, unsigned int); - int (*XXX_udma)(struct ata_device *); + int (*udma_setup)(struct ata_device *); void (*udma_enable)(struct ata_device *, int, int); - int (*udma_start) (struct ata_device *, struct request *rq); int (*udma_stop) (struct ata_device *); - - int (*udma_read) (struct ata_device *, struct request *rq); - int (*udma_write) (struct ata_device *, struct request *rq); - + int (*udma_init) (struct ata_device *, struct request *rq); int (*udma_irq_status) (struct ata_device *); - void (*udma_timeout) (struct ata_device *); void (*udma_irq_lost) (struct ata_device *); @@ -770,14 +765,12 @@ static inline int udma_stop(struct ata_device *drive) return drive->channel->udma_stop(drive); } -static inline int udma_read(struct ata_device *drive, struct request *rq) -{ - return drive->channel->udma_read(drive, rq); -} - -static inline int udma_write(struct ata_device *drive, struct request *rq) +/* + * Initiate actual DMA data transfer. The direction is encoded in the request. + */ +static inline int udma_init(struct ata_device *drive, struct request *rq) { - return drive->channel->udma_write(drive, rq); + return drive->channel->udma_init(drive, rq); } static inline int udma_irq_status(struct ata_device *drive) @@ -797,14 +790,14 @@ static inline void udma_irq_lost(struct ata_device *drive) #ifdef CONFIG_BLK_DEV_IDEDMA -void udma_pci_enable(struct ata_device *drive, int on, int verbose); -int udma_pci_start(struct ata_device *drive, struct request *rq); -int udma_pci_stop(struct ata_device *drive); -int udma_pci_read(struct ata_device *drive, struct request *rq); -int udma_pci_write(struct ata_device *drive, struct request *rq); -int udma_pci_irq_status(struct ata_device *drive); -void udma_pci_timeout(struct ata_device *drive); -void udma_pci_irq_lost(struct ata_device *); +extern void udma_pci_enable(struct ata_device *drive, int on, int verbose); +extern int udma_pci_start(struct ata_device *drive, struct request *rq); +extern int udma_pci_stop(struct ata_device *drive); +extern int udma_pci_init(struct ata_device *drive, struct request *rq); +extern int udma_pci_irq_status(struct ata_device *drive); +extern void udma_pci_timeout(struct ata_device *drive); +extern void udma_pci_irq_lost(struct ata_device *); +extern int udma_pci_setup(struct ata_device *); extern int udma_new_table(struct ata_channel *, struct request *); extern void udma_destroy_table(struct ata_channel *); @@ -813,14 +806,11 @@ extern void udma_print(struct ata_device *); extern int udma_black_list(struct ata_device *); extern int udma_white_list(struct ata_device *); -extern int ata_do_udma(unsigned int reading, struct ata_device *drive, struct request *rq); - extern ide_startstop_t udma_tcq_taskfile(struct ata_device *, struct request *); extern int udma_tcq_enable(struct ata_device *, int); extern ide_startstop_t ide_dma_intr(struct ata_device *, struct request *); extern int check_drive_lists(struct ata_device *, int good_bad); -extern int XXX_ide_dmaproc(struct ata_device *); extern void ide_release_dma(struct ata_channel *); extern int ata_start_dma(struct ata_device *, struct request *rq); -- cgit v1.2.3 From 15283e97f91ed67fab57a7df9c268c9fed98cc1f Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Sun, 2 Jun 2002 03:15:02 -0700 Subject: [PATCH] documentation and tq_disk removals This should be the last of tq_disk, at least the trivial ones. md still has some queue_task references, I'll let Ingo/Neil clean those up. suspend is still broken, it was broken before too though. I guess Pavel will want to fix that. Also, I've documented the plug functions. --- drivers/block/ll_rw_blk.c | 40 +++++++++++++++++++++++++++++++--------- drivers/ide/ide.c | 3 +-- fs/jfs/jfs_logmgr.c | 4 ++-- include/linux/raid/md_k.h | 4 ++-- kernel/suspend.c | 3 ++- 5 files changed, 38 insertions(+), 16 deletions(-) (limited to 'include') diff --git a/drivers/block/ll_rw_blk.c b/drivers/block/ll_rw_blk.c index 0de94d28405c..9e42c51e4fbf 100644 --- a/drivers/block/ll_rw_blk.c +++ b/drivers/block/ll_rw_blk.c @@ -848,9 +848,15 @@ void generic_unplug_device(void *data) spin_unlock_irqrestore(q->queue_lock, flags); } -/* - * clear stop flag and run queue - */ +/** + * blk_start_queue - restart a previously stopped queue + * @q: The &request_queue_t in question + * + * Description: + * blk_start_queue() will clear the stop flag on the queue, and call + * the request_fn for the queue if it was in a stopped state when + * entered. Also see blk_stop_queue() + **/ void blk_start_queue(request_queue_t *q) { if (test_and_clear_bit(QUEUE_FLAG_STOPPED, &q->queue_flags)) { @@ -863,17 +869,33 @@ void blk_start_queue(request_queue_t *q) } } -/* - * set stop bit, queue won't be run until blk_start_queue() is called - */ +/** + * blk_stop_queue - stop a queue + * @q: The &request_queue_t in question + * + * Description: + * The Linux block layer assumes that a block driver will consume all + * entries on the request queue when the request_fn strategy is called. + * Often this will not happen, because of hardware limitations (queue + * depth settings). If a device driver gets a 'queue full' response, + * or if it simply chooses not to queue more I/O at one point, it can + * call this function to prevent the request_fn from being called until + * the driver has signalled it's ready to go again. This happens by calling + * blk_start_queue() to restart queue operations. + **/ void blk_stop_queue(request_queue_t *q) { set_bit(QUEUE_FLAG_STOPPED, &q->queue_flags); } -/* - * the equivalent of the previous tq_disk run - */ +/** + * blk_run_queues - fire all plugged queues + * + * Description: + * Start I/O on all plugged queues known to the block layer. Queues that + * are currently stopped are ignored. This is equivalent to the older + * tq_disk task queue run. + **/ void blk_run_queues(void) { struct list_head *n, *tmp, local_plug_list; diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c index 26023c342d8a..4891d2869173 100644 --- a/drivers/ide/ide.c +++ b/drivers/ide/ide.c @@ -909,8 +909,7 @@ static struct ata_device *choose_urgent_device(struct ata_channel *channel) mod_timer(&channel->timer, sleep); /* we purposely leave hwgroup busy while sleeping */ } else { - /* Ugly, but how can we sleep for the lock otherwise? perhaps - * from tq_disk? */ + /* Ugly, but how can we sleep for the lock otherwise? */ ide_release_lock(&irq_lock);/* for atari only */ clear_bit(IDE_BUSY, channel->active); } diff --git a/fs/jfs/jfs_logmgr.c b/fs/jfs/jfs_logmgr.c index 8e7f423b8398..fffacf72af04 100644 --- a/fs/jfs/jfs_logmgr.c +++ b/fs/jfs/jfs_logmgr.c @@ -1813,7 +1813,7 @@ static int lbmRead(log_t * log, int pn, lbuf_t ** bpp) bio->bi_end_io = lbmIODone; bio->bi_private = bp; submit_bio(READ, bio); - run_task_queue(&tq_disk); + blk_run_queues(); wait_event(bp->l_ioevent, (bp->l_flag != lbmREAD)); @@ -1958,7 +1958,7 @@ void lbmStartIO(lbuf_t * bp) submit_bio(WRITE, bio); INCREMENT(lmStat.submitted); - run_task_queue(&tq_disk); + blk_run_queues(); jFYI(1, ("lbmStartIO done\n")); } diff --git a/include/linux/raid/md_k.h b/include/linux/raid/md_k.h index 62024cab73f2..7b270a50487e 100644 --- a/include/linux/raid/md_k.h +++ b/include/linux/raid/md_k.h @@ -355,7 +355,7 @@ do { \ if (condition) \ break; \ spin_unlock_irq(&lock); \ - run_task_queue(&tq_disk); \ + blk_run_queues(); \ schedule(); \ spin_lock_irq(&lock); \ } \ @@ -381,7 +381,7 @@ do { \ set_current_state(TASK_UNINTERRUPTIBLE); \ if (condition) \ break; \ - run_task_queue(&tq_disk); \ + blk_run_queues(); \ schedule(); \ } \ current->state = TASK_RUNNING; \ diff --git a/kernel/suspend.c b/kernel/suspend.c index 565daab07143..c9c65946bd4e 100644 --- a/kernel/suspend.c +++ b/kernel/suspend.c @@ -300,7 +300,8 @@ static __inline__ int fill_suspend_header(struct suspend_header *sh) static void do_suspend_sync(void) { while (1) { - run_task_queue(&tq_disk); + blk_run_queues(); +#error this is broken, FIXME if (!TQ_ACTIVE(tq_disk)) break; printk(KERN_ERR "Hm, tq_disk is not empty after run_task_queue\n"); -- cgit v1.2.3 From b9a78e5991e18eb4c5f93d2d58e19f1708528dae Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 2 Jun 2002 03:21:53 -0700 Subject: [PATCH] list_head debugging A common and very subtle bug is to use list_heads which aren't on any lists. It causes kernel memory corruption which is observed long after the offending code has executed. The patch nulls out the dangling pointers so we get a nice oops at the site of the buggy code. --- include/linux/list.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'include') diff --git a/include/linux/list.h b/include/linux/list.h index 99da4ab62ec2..6331739453a0 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -94,6 +94,8 @@ static __inline__ void __list_del(struct list_head * prev, static __inline__ void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); + entry->next = NULL; + entry->prev = NULL; } /** -- cgit v1.2.3 From 0f2b38d5e227d968384c4f97cc67dabb341552af Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 2 Jun 2002 03:22:05 -0700 Subject: [PATCH] remove PageSkip() macros Remove some unused PageSkip() macros. Presumably leftovers from PG_skip which isn't there any more. --- include/asm-alpha/pgtable.h | 3 --- include/asm-cris/pgtable.h | 2 -- include/asm-i386/pgtable.h | 2 -- include/asm-ia64/pgtable.h | 3 --- include/asm-m68k/pgtable.h | 2 -- include/asm-mips/pgtable.h | 2 -- include/asm-mips64/pgtable.h | 2 -- include/asm-parisc/pgtable.h | 3 --- include/asm-s390/pgtable.h | 2 -- include/asm-s390x/pgtable.h | 2 -- include/asm-sh/pgtable.h | 2 -- include/asm-x86_64/pgtable.h | 2 -- 12 files changed, 27 deletions(-) (limited to 'include') diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index 073f2c8b5cd0..ac1ecc3f9415 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -346,9 +346,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) - #ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) #endif diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h index 51eb17d87f9d..6aa04ba4d4b1 100644 --- a/include/asm-cris/pgtable.h +++ b/include/asm-cris/pgtable.h @@ -506,8 +506,6 @@ static inline void update_mmu_cache(struct vm_area_struct * vma, #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #include diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 8785225614da..645005ac5cfb 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -277,8 +277,6 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 4ff23d54e418..7ccd4d9e6994 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -408,9 +408,6 @@ extern void paging_init (void); #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) - #define io_remap_page_range remap_page_range /* XXX is this right? */ /* diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h index 0d20bd4ed997..6fb8eb88612f 100644 --- a/include/asm-m68k/pgtable.h +++ b/include/asm-m68k/pgtable.h @@ -164,8 +164,6 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma, #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index b70d53edab46..240b1327f412 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -500,8 +500,6 @@ extern void update_mmu_cache(struct vm_area_struct *vma, #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) /* TLB operations. */ diff --git a/include/asm-mips64/pgtable.h b/include/asm-mips64/pgtable.h index d5f16df89c8a..b8258f5733b4 100644 --- a/include/asm-mips64/pgtable.h +++ b/include/asm-mips64/pgtable.h @@ -559,8 +559,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) #define swp_entry_to_pte(x) ((pte_t) { (x).val }) -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) #endif diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index df853449c900..2448948197e7 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -328,9 +328,6 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma, #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) - #define io_remap_page_range remap_page_range /* diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 026e0ee40a23..6e156879dcaf 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -494,8 +494,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) /* diff --git a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h index 4fee035ea2dc..f057679c0665 100644 --- a/include/asm-s390x/pgtable.h +++ b/include/asm-s390x/pgtable.h @@ -514,8 +514,6 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) /* diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index a7e2b8dfecaf..46d9a217e18a 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -312,8 +312,6 @@ extern void update_mmu_cache(struct vm_area_struct * vma, #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 6a79a3d416d1..4c151605c479 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -337,8 +337,6 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #endif /* !__ASSEMBLY__ */ -/* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ -#define PageSkip(page) (0) #define kern_addr_valid(addr) (1) #define io_remap_page_range remap_page_range -- cgit v1.2.3 From 02eaba7ffd145ef1389f4adc420f94af20ab3068 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 2 Jun 2002 03:22:17 -0700 Subject: [PATCH] fix swapcache packing in the radix tree First some terminology: this patch introduces a kernel-wide `pgoff_t' type. It is the index of a page into the pagecache. The thing at page->index. For most mappings it is also the offset of the page into that mapping. This type has a very distinct function in the kernel and it needs a name. I don't have any particular plans to go and migrate everything so we can support 64-bit pagecache indices on x86, but this would be the way to do it. This patch improves the packing density of swapcache pages in the radix tree. A swapcache page is identified by the `swap type' (indexes the swap device) and the `offset' (into that swap device). These two numbers are encoded into a `swp_entry_t' machine word in arch-specific code because the resulting number is placed into pagetables in a form which will generate a fault. The kernel also need to generate a pgoff_t for that page to index it into the swapper_space radix tree. That pgoff_t is usually bitwise-identical to the swp_entry_t. That worked OK when the pagecache was using a hash. But with a radix tree, it produces catastrophically bad results. x86 (and many other architectures) place the `type' field into the low-order bits of the swp_entry_t. So *all* swapcache pages are basically identical in the eight low-order bits. This produces a very sparse radix tree for swapcache. I'm observing packing densities of 1% to 2%: so the typical 128-slot radix tree node has only one or two pages in it. The end result is that the kernel needs to allocate approximately one new radix-tree node for each page which is added to the swapcache. So no wonder we're having radix-tree node exhaustion during swapout! (It's actually quite encouraging that the kernel works as well as it does). The patch changes the encoding of the swp_entry_t so that its most-significant bits contain the `type' field and the least-significant bits contain the `offset' field, right-aligned. That is: the encoding in swp_entry_t is now arch-independent. The new file has conversion functions which convert the swp_entry_t to and from its machine pte representation. Packing density in the swapper_space mapping goes up to around 90% (observed) and the kernel is tons happier under swap load. An alternative approach would be to create new conversion functions which convert an arch-specific swp_entry_t to and from a pgoff_t. I tried that. It worked, but I liked it less. --- arch/m68k/atari/stram.c | 4 +-- include/asm-alpha/pgtable.h | 10 +++---- include/asm-arm/pgtable.h | 10 +++---- include/asm-cris/pgtable.h | 10 +++---- include/asm-i386/pgtable.h | 10 +++---- include/asm-ia64/pgtable.h | 10 +++---- include/asm-m68k/pgtable.h | 20 ++++++------- include/asm-mips/pgtable.h | 11 ++++--- include/asm-mips64/pgtable.h | 10 +++---- include/asm-parisc/pgtable.h | 10 +++---- include/asm-ppc/pgtable.h | 10 +++---- include/asm-ppc64/pgtable.h | 10 +++---- include/asm-s390/pgtable.h | 10 +++---- include/asm-s390x/pgtable.h | 10 +++---- include/asm-sh/pgtable.h | 10 +++---- include/asm-sparc/pgtable.h | 10 +++---- include/asm-sparc64/pgtable.h | 10 +++---- include/asm-x86_64/pgtable.h | 10 +++---- include/linux/swap.h | 11 ++++++- include/linux/swapops.h | 68 +++++++++++++++++++++++++++++++++++++++++++ include/linux/types.h | 8 +++++ kernel/suspend.c | 15 +++++----- mm/memory.c | 4 ++- mm/swapfile.c | 37 +++++++++++------------ mm/vmscan.c | 1 + 25 files changed, 209 insertions(+), 120 deletions(-) create mode 100644 include/linux/swapops.h (limited to 'include') diff --git a/arch/m68k/atari/stram.c b/arch/m68k/atari/stram.c index 5d1e3c9eff9b..d4b403bfcf20 100644 --- a/arch/m68k/atari/stram.c +++ b/arch/m68k/atari/stram.c @@ -315,7 +315,7 @@ void __init atari_stram_reserve_pages(void *start_mem) otherwise just use the end of kernel data (= start_mem) */ swap_start = !kernel_in_stram ? stram_start + PAGE_SIZE : start_mem; /* decrement by one page, rest of kernel assumes that first swap page - * is always reserved and maybe doesn't handle SWP_ENTRY == 0 + * is always reserved and maybe doesn't handle swp_entry == 0 * correctly */ swap_start -= PAGE_SIZE; swap_end = stram_end; @@ -749,7 +749,7 @@ static int unswap_by_read(unsigned short *map, unsigned long max, } if (map[i]) { - entry = SWP_ENTRY(stram_swap_type, i); + entry = swp_entry(stram_swap_type, i); DPRINTK("unswap: map[i=%lu]=%u nr_swap=%u\n", i, map[i], nr_swap_pages); diff --git a/include/asm-alpha/pgtable.h b/include/asm-alpha/pgtable.h index ac1ecc3f9415..a972181fd540 100644 --- a/include/asm-alpha/pgtable.h +++ b/include/asm-alpha/pgtable.h @@ -340,11 +340,11 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma, extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) { pte_t pte; pte_val(pte) = (type << 32) | (offset << 40); return pte; } -#define SWP_TYPE(x) (((x).val >> 32) & 0xff) -#define SWP_OFFSET(x) ((x).val >> 40) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 32) & 0xff) +#define __swp_offset(x) ((x).val >> 40) +#define __swp_entry(type, offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) diff --git a/include/asm-arm/pgtable.h b/include/asm-arm/pgtable.h index dbbb85bd3995..62456af5582a 100644 --- a/include/asm-arm/pgtable.h +++ b/include/asm-arm/pgtable.h @@ -142,11 +142,11 @@ extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; * * We support up to 32GB of swap on 4k machines */ -#define SWP_TYPE(x) (((x).val >> 2) & 0x7f) -#define SWP_OFFSET(x) ((x).val >> 9) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(swp) ((pte_t) { (swp).val }) +#define __swp_type(x) (((x).val >> 2) & 0x7f) +#define __swp_offset(x) ((x).val >> 9) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 2) | ((offset) << 9) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(swp) ((pte_t) { (swp).val }) /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */ /* FIXME: this is not correct */ diff --git a/include/asm-cris/pgtable.h b/include/asm-cris/pgtable.h index 6aa04ba4d4b1..57e391330752 100644 --- a/include/asm-cris/pgtable.h +++ b/include/asm-cris/pgtable.h @@ -500,11 +500,11 @@ static inline void update_mmu_cache(struct vm_area_struct * vma, /* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */ /* Since the PAGE_PRESENT bit is bit 4, we can use the bits above */ -#define SWP_TYPE(x) (((x).val >> 5) & 0x7f) -#define SWP_OFFSET(x) ((x).val >> 12) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 5) | ((offset) << 12) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 5) & 0x7f) +#define __swp_offset(x) ((x).val >> 12) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 5) | ((offset) << 12) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #define kern_addr_valid(addr) (1) diff --git a/include/asm-i386/pgtable.h b/include/asm-i386/pgtable.h index 645005ac5cfb..f48db2beeeba 100644 --- a/include/asm-i386/pgtable.h +++ b/include/asm-i386/pgtable.h @@ -269,11 +269,11 @@ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define update_mmu_cache(vma,address,pte) do { } while (0) /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) (((x).val >> 1) & 0x3f) -#define SWP_OFFSET(x) ((x).val >> 8) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 1) & 0x3f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-ia64/pgtable.h b/include/asm-ia64/pgtable.h index 7ccd4d9e6994..cc8c0a29b335 100644 --- a/include/asm-ia64/pgtable.h +++ b/include/asm-ia64/pgtable.h @@ -402,11 +402,11 @@ pte_same (pte_t a, pte_t b) extern pgd_t swapper_pg_dir[PTRS_PER_PGD]; extern void paging_init (void); -#define SWP_TYPE(entry) (((entry).val >> 1) & 0xff) -#define SWP_OFFSET(entry) (((entry).val << 1) >> 10) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 1) | ((long) (offset) << 9) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(entry) (((entry).val >> 1) & 0xff) +#define __swp_offset(entry) (((entry).val << 1) >> 10) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 1) | ((long) (offset) << 9) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #define io_remap_page_range remap_page_range /* XXX is this right? */ diff --git a/include/asm-m68k/pgtable.h b/include/asm-m68k/pgtable.h index 6fb8eb88612f..597f08991de3 100644 --- a/include/asm-m68k/pgtable.h +++ b/include/asm-m68k/pgtable.h @@ -145,20 +145,20 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma, #ifdef CONFIG_SUN3 /* Macros to (de)construct the fake PTEs representing swap pages. */ -#define SWP_TYPE(x) ((x).val & 0x7F) -#define SWP_OFFSET(x) (((x).val) >> 7) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) | ((offset) << 7)) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) ((x).val & 0x7F) +#define __swp_offset(x) (((x).val) >> 7) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) | ((offset) << 7)) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #else /* Encode and de-code a swap entry (must be !pte_none(e) && !pte_present(e)) */ -#define SWP_TYPE(x) (((x).val >> 1) & 0xff) -#define SWP_OFFSET(x) ((x).val >> 10) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 10) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 1) & 0xff) +#define __swp_offset(x) ((x).val >> 10) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 10) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* CONFIG_SUN3 */ diff --git a/include/asm-mips/pgtable.h b/include/asm-mips/pgtable.h index 240b1327f412..bec6e22366e5 100644 --- a/include/asm-mips/pgtable.h +++ b/include/asm-mips/pgtable.h @@ -493,12 +493,11 @@ extern void paging_init(void); extern void update_mmu_cache(struct vm_area_struct *vma, unsigned long address, pte_t pte); -#define SWP_TYPE(x) (((x).val >> 1) & 0x3f) -#define SWP_OFFSET(x) ((x).val >> 8) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) - +#define __swp_type(x) (((x).val >> 1) & 0x3f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type,offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #define kern_addr_valid(addr) (1) diff --git a/include/asm-mips64/pgtable.h b/include/asm-mips64/pgtable.h index b8258f5733b4..d3118912a2a5 100644 --- a/include/asm-mips64/pgtable.h +++ b/include/asm-mips64/pgtable.h @@ -553,11 +553,11 @@ extern void (*update_mmu_cache)(struct vm_area_struct *vma, extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) { pte_t pte; pte_val(pte) = (type << 32) | (offset << 40); return pte; } -#define SWP_TYPE(x) (((x).val >> 32) & 0xff) -#define SWP_OFFSET(x) ((x).val >> 40) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 32) & 0xff) +#define __swp_offset(x) ((x).val >> 40) +#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #ifndef CONFIG_DISCONTIGMEM #define kern_addr_valid(addr) (1) diff --git a/include/asm-parisc/pgtable.h b/include/asm-parisc/pgtable.h index 2448948197e7..c1d676cf92ea 100644 --- a/include/asm-parisc/pgtable.h +++ b/include/asm-parisc/pgtable.h @@ -312,14 +312,14 @@ extern inline void update_mmu_cache(struct vm_area_struct * vma, /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) ((x).val & 0x3f) -#define SWP_OFFSET(x) ( (((x).val >> 6) & 0x7) | \ +#define __swp_type(x) ((x).val & 0x3f) +#define __swp_offset(x) ( (((x).val >> 6) & 0x7) | \ (((x).val >> 7) & ~0x7) ) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { (type) | \ +#define __swp_entry(type, offset) ((swp_entry_t) { (type) | \ ((offset & 0x7) << 6) | \ ((offset & ~0x7) << 7) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #define module_map vmalloc #define module_unmap vfree diff --git a/include/asm-ppc/pgtable.h b/include/asm-ppc/pgtable.h index a0514543259c..c5bfc1332e5f 100644 --- a/include/asm-ppc/pgtable.h +++ b/include/asm-ppc/pgtable.h @@ -482,11 +482,11 @@ extern void add_hash_page(unsigned context, unsigned long va, * must not include the _PAGE_PRESENT bit, or the _PAGE_HASHPTE bit * (if used). -- paulus */ -#define SWP_TYPE(entry) ((entry).val & 0x3f) -#define SWP_OFFSET(entry) ((entry).val >> 6) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { (type) | ((offset) << 6) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val << 2 }) +#define __swp_type(entry) ((entry).val & 0x3f) +#define __swp_offset(entry) ((entry).val >> 6) +#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 6) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> 2 }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << 2 }) /* CONFIG_APUS */ /* For virtual address to physical address conversion */ diff --git a/include/asm-ppc64/pgtable.h b/include/asm-ppc64/pgtable.h index 48d9f43a3e49..e546e3f0f88c 100644 --- a/include/asm-ppc64/pgtable.h +++ b/include/asm-ppc64/pgtable.h @@ -359,11 +359,11 @@ extern void paging_init(void); extern void update_mmu_cache(struct vm_area_struct *, unsigned long, pte_t); /* Encode and de-code a swap entry */ -#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f) -#define SWP_OFFSET(entry) ((entry).val >> 8) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> PTE_SHIFT }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_SHIFT }) +#define __swp_type(entry) (((entry).val >> 1) & 0x3f) +#define __swp_offset(entry) ((entry).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) >> PTE_SHIFT }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val << PTE_SHIFT }) /* * kern_addr_valid is intended to indicate whether an address is a valid diff --git a/include/asm-s390/pgtable.h b/include/asm-s390/pgtable.h index 6e156879dcaf..fa9993ad8e9d 100644 --- a/include/asm-s390/pgtable.h +++ b/include/asm-s390/pgtable.h @@ -485,12 +485,12 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) return pte; } -#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f) -#define SWP_OFFSET(entry) (((entry).val >> 12) & 0x7FFFF ) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __swp_type(entry) (((entry).val >> 1) & 0x3f) +#define __swp_offset(entry) (((entry).val >> 12) & 0x7FFFF ) +#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-s390x/pgtable.h b/include/asm-s390x/pgtable.h index f057679c0665..a2729aa46c35 100644 --- a/include/asm-s390x/pgtable.h +++ b/include/asm-s390x/pgtable.h @@ -505,12 +505,12 @@ extern inline pte_t mk_swap_pte(unsigned long type, unsigned long offset) return pte; } -#define SWP_TYPE(entry) (((entry).val >> 1) & 0x3f) -#define SWP_OFFSET(entry) ((entry).val >> 12) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) +#define __swp_type(entry) (((entry).val >> 1) & 0x3f) +#define __swp_offset(entry) ((entry).val >> 12) +#define __swp_entry(type,offset) ((swp_entry_t) { pte_val(mk_swap_pte((type),(offset))) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ diff --git a/include/asm-sh/pgtable.h b/include/asm-sh/pgtable.h index 46d9a217e18a..74034ac9c862 100644 --- a/include/asm-sh/pgtable.h +++ b/include/asm-sh/pgtable.h @@ -294,11 +294,11 @@ extern void update_mmu_cache(struct vm_area_struct * vma, * NOTE: We should set ZEROs at the position of _PAGE_PRESENT * and _PAGE_PROTONOE bits */ -#define SWP_TYPE(x) ((x).val & 0xff) -#define SWP_OFFSET(x) ((x).val >> 10) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { (type) | ((offset) << 10) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) ((x).val & 0xff) +#define __swp_offset(x) ((x).val >> 10) +#define __swp_entry(type, offset) ((swp_entry_t) { (type) | ((offset) << 10) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) /* * Routines for update of PTE diff --git a/include/asm-sparc/pgtable.h b/include/asm-sparc/pgtable.h index b73aaa20847e..775e8483859a 100644 --- a/include/asm-sparc/pgtable.h +++ b/include/asm-sparc/pgtable.h @@ -376,11 +376,11 @@ BTFIXUPDEF_CALL(void, update_mmu_cache, struct vm_area_struct *, unsigned long, extern int invalid_segment; /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) (((x).val >> 2) & 0x7f) -#define SWP_OFFSET(x) (((x).val >> 9) & 0x3ffff) -#define SWP_ENTRY(type,offset) ((swp_entry_t) { (((type) & 0x7f) << 2) | (((offset) & 0x3ffff) << 9) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 2) & 0x7f) +#define __swp_offset(x) (((x).val >> 9) & 0x3ffff) +#define __swp_entry(type,offset) ((swp_entry_t) { (((type) & 0x7f) << 2) | (((offset) & 0x3ffff) << 9) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) struct ctx_list { struct ctx_list *next; diff --git a/include/asm-sparc64/pgtable.h b/include/asm-sparc64/pgtable.h index 73d5951edfb9..e5c086958155 100644 --- a/include/asm-sparc64/pgtable.h +++ b/include/asm-sparc64/pgtable.h @@ -298,16 +298,16 @@ extern inline pte_t mk_pte_io(unsigned long page, pgprot_t prot, int space) } /* Encode and de-code a swap entry */ -#define SWP_TYPE(entry) (((entry).val >> PAGE_SHIFT) & 0xffUL) -#define SWP_OFFSET(entry) ((entry).val >> (PAGE_SHIFT + 8UL)) -#define SWP_ENTRY(type, offset) \ +#define __swp_type(entry) (((entry).val >> PAGE_SHIFT) & 0xffUL) +#define __swp_offset(entry) ((entry).val >> (PAGE_SHIFT + 8UL)) +#define __swp_entry(type, offset) \ ( (swp_entry_t) \ { \ (((long)(type) << PAGE_SHIFT) | \ ((long)(offset) << (PAGE_SHIFT + 8UL))) \ } ) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) extern unsigned long prom_virt_to_phys(unsigned long, int *); diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h index 4c151605c479..09d3254fa9a7 100644 --- a/include/asm-x86_64/pgtable.h +++ b/include/asm-x86_64/pgtable.h @@ -329,11 +329,11 @@ extern inline pte_t pte_modify(pte_t pte, pgprot_t newprot) #define update_mmu_cache(vma,address,pte) do { } while (0) /* Encode and de-code a swap entry */ -#define SWP_TYPE(x) (((x).val >> 1) & 0x3f) -#define SWP_OFFSET(x) ((x).val >> 8) -#define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) -#define pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) -#define swp_entry_to_pte(x) ((pte_t) { (x).val }) +#define __swp_type(x) (((x).val >> 1) & 0x3f) +#define __swp_offset(x) ((x).val >> 8) +#define __swp_entry(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) }) +#define __pte_to_swp_entry(pte) ((swp_entry_t) { pte_val(pte) }) +#define __swp_entry_to_pte(x) ((pte_t) { (x).val }) #endif /* !__ASSEMBLY__ */ diff --git a/include/linux/swap.h b/include/linux/swap.h index 7e20b3016c7f..d0160265e3c5 100644 --- a/include/linux/swap.h +++ b/include/linux/swap.h @@ -11,7 +11,16 @@ #define SWAP_FLAG_PRIO_MASK 0x7fff #define SWAP_FLAG_PRIO_SHIFT 0 -#define MAX_SWAPFILES 32 +/* + * MAX_SWAPFILES defines the maximum number of swaptypes: things which can + * be swapped to. The swap type and the offset into that swap type are + * encoded into pte's and into pgoff_t's in the swapcache. Using five bits + * for the type means that the maximum number of swapcache pages is 27 bits + * on 32-bit-pgoff_t architectures. And that assumes that the architecture packs + * the type/offset into the pte as 5/27 as well. + */ +#define MAX_SWAPFILES_SHIFT 5 +#define MAX_SWAPFILES (1 << MAX_SWAPFILES_SHIFT) /* * Magic header for a swap area. The first part of the union is diff --git a/include/linux/swapops.h b/include/linux/swapops.h new file mode 100644 index 000000000000..500f9960d939 --- /dev/null +++ b/include/linux/swapops.h @@ -0,0 +1,68 @@ +/* + * swapcache pages are stored in the swapper_space radix tree. We want to + * get good packing density in that tree, so the index should be dense in + * the low-order bits. + * + * We arrange the `type' and `offset' fields so that `type' is at the five + * high-order bits of the smp_entry_t and `offset' is right-aligned in the + * remaining bits. + * + * swp_entry_t's are *never* stored anywhere in their arch-dependent format. + */ +#define SWP_TYPE_SHIFT(e) (sizeof(e.val) * 8 - MAX_SWAPFILES_SHIFT) +#define SWP_OFFSET_MASK(e) ((1 << SWP_TYPE_SHIFT(e)) - 1) + +/* + * Store a type+offset into a swp_entry_t in an arch-independent format + */ +static inline swp_entry_t swp_entry(unsigned type, pgoff_t offset) +{ + swp_entry_t ret; + + ret.val = (type << SWP_TYPE_SHIFT(ret)) | + (offset & SWP_OFFSET_MASK(ret)); + return ret; +} + +/* + * Extract the `type' field from a swp_entry_t. The swp_entry_t is in + * arch-independent format + */ +static inline unsigned swp_type(swp_entry_t entry) +{ + return (entry.val >> SWP_TYPE_SHIFT(entry)) & + ((1 << MAX_SWAPFILES_SHIFT) - 1); +} + +/* + * Extract the `offset' field from a swp_entry_t. The swp_entry_t is in + * arch-independent format + */ +static inline pgoff_t swp_offset(swp_entry_t entry) +{ + return entry.val & SWP_OFFSET_MASK(entry); +} + +/* + * Convert the arch-dependent pte representation of a swp_entry_t into an + * arch-independent swp_entry_t. + */ +static inline swp_entry_t pte_to_swp_entry(pte_t pte) +{ + swp_entry_t arch_entry; + + arch_entry = __pte_to_swp_entry(pte); + return swp_entry(__swp_type(arch_entry), __swp_offset(arch_entry)); +} + +/* + * Convert the arch-independent representation of a swp_entry_t into the + * arch-dependent pte representation. + */ +static inline pte_t swp_entry_to_pte(swp_entry_t entry) +{ + swp_entry_t arch_entry; + + arch_entry = __swp_entry(swp_type(entry), swp_offset(entry)); + return __swp_entry_to_pte(arch_entry); +} diff --git a/include/linux/types.h b/include/linux/types.h index 211461bc97c0..c102bcf8be83 100644 --- a/include/linux/types.h +++ b/include/linux/types.h @@ -124,6 +124,14 @@ typedef u64 sector_t; typedef unsigned long sector_t; #endif +/* + * The type of an index into the pagecache. Use a #define so asm/types.h + * can override it. + */ +#ifndef pgoff_t +#define pgoff_t unsigned long +#endif + #endif /* __KERNEL_STRICT_NAMES */ /* diff --git a/kernel/suspend.c b/kernel/suspend.c index c9c65946bd4e..a1b7b3361a67 100644 --- a/kernel/suspend.c +++ b/kernel/suspend.c @@ -64,6 +64,7 @@ #include #include #include +#include unsigned char software_suspend_enabled = 0; @@ -327,7 +328,7 @@ static void mark_swapfiles(swp_entry_t prev, int mode) if (!cur) panic("Out of memory in mark_swapfiles"); /* XXX: this is dirty hack to get first page of swap file */ - entry = SWP_ENTRY(root_swap, 0); + entry = swp_entry(root_swap, 0); lock_page(virt_to_page((unsigned long)cur)); rw_swap_page_nolock(READ, entry, (char *) cur); @@ -420,7 +421,7 @@ static int write_suspend_image(void) if (!(entry = get_swap_page()).val) panic("\nNot enough swapspace when writing data" ); - if(swapfile_used[SWP_TYPE(entry)] != SWAPFILE_SUSPEND) + if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND) panic("\nPage %d: not enough swapspace on suspend device", i ); address = (pagedir_nosave+i)->address; @@ -446,7 +447,7 @@ static int write_suspend_image(void) return -ENOSPC; } - if(swapfile_used[SWP_TYPE(entry)] != SWAPFILE_SUSPEND) + if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND) panic("\nNot enough swapspace for pagedir on suspend device" ); if (sizeof(swp_entry_t) != sizeof(long)) @@ -466,7 +467,7 @@ static int write_suspend_image(void) panic("union diskpage has bad size"); if (!(entry = get_swap_page()).val) panic( "\nNot enough swapspace when writing header" ); - if(swapfile_used[SWP_TYPE(entry)] != SWAPFILE_SUSPEND) + if(swapfile_used[swp_type(entry)] != SWAPFILE_SUSPEND) panic("\nNot enough swapspace for header on suspend device" ); cur = (void *) buffer; @@ -481,7 +482,7 @@ static int write_suspend_image(void) PRINTK( ", signature" ); #if 0 - if (SWP_TYPE(entry) != 0) + if (swp_type(entry) != 0) panic("Need just one swapfile"); #endif mark_swapfiles(prev, MARK_SWAP_SUSPEND); @@ -1069,7 +1070,7 @@ static int resume_try_to_read(const char * specialfile, int noresume) if (bdev_read_page(resume_device, pos, ptr)) { error = -EIO; goto resume_read_error; } #define PREPARENEXT \ { next = cur->link.next; \ - next.val = SWP_OFFSET(next) * PAGE_SIZE; \ + next.val = swp_offset(next) * PAGE_SIZE; \ } error = -EIO; @@ -1142,7 +1143,7 @@ static int resume_try_to_read(const char * specialfile, int noresume) swp_entry_t swap_address = (pagedir_nosave+i)->swap_address; if (!(i%100)) PRINTK( "." ); - next.val = SWP_OFFSET (swap_address) * PAGE_SIZE; + next.val = swp_offset(swap_address) * PAGE_SIZE; /* You do not need to check for overlaps... ... check_pagedir already did this work */ READTO(next.val, (char *)((pagedir_nosave+i)->address)); diff --git a/mm/memory.c b/mm/memory.c index 477749935dea..ff1be5c5afb3 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -50,6 +50,8 @@ #include #include +#include + unsigned long max_mapnr; unsigned long num_physpages; void * high_memory; @@ -1128,7 +1130,7 @@ void swapin_readahead(swp_entry_t entry) num = valid_swaphandles(entry, &offset); for (i = 0; i < num; offset++, i++) { /* Ok, do the async read-ahead now */ - new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset)); + new_page = read_swap_cache_async(swp_entry(swp_type(entry), offset)); if (!new_page) break; page_cache_release(new_page); diff --git a/mm/swapfile.c b/mm/swapfile.c index 1a032196a10d..6ae2eff56601 100644 --- a/mm/swapfile.c +++ b/mm/swapfile.c @@ -19,6 +19,7 @@ #include /* for block_flushpage() */ #include +#include spinlock_t swaplock = SPIN_LOCK_UNLOCKED; unsigned int nr_swapfiles; @@ -121,7 +122,7 @@ swp_entry_t get_swap_page(void) offset = scan_swap_map(p); swap_device_unlock(p); if (offset) { - entry = SWP_ENTRY(type,offset); + entry = swp_entry(type,offset); type = swap_info[type].next; if (type < 0 || p->prio != swap_info[type].prio) { @@ -154,13 +155,13 @@ static struct swap_info_struct * swap_info_get(swp_entry_t entry) if (!entry.val) goto out; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) goto bad_nofile; p = & swap_info[type]; if (!(p->flags & SWP_USED)) goto bad_device; - offset = SWP_OFFSET(entry); + offset = swp_offset(entry); if (offset >= p->max) goto bad_offset; if (!p->swap_map[offset]) @@ -220,7 +221,7 @@ void swap_free(swp_entry_t entry) p = swap_info_get(entry); if (p) { - swap_entry_free(p, SWP_OFFSET(entry)); + swap_entry_free(p, swp_offset(entry)); swap_info_put(p); } } @@ -239,7 +240,7 @@ static int exclusive_swap_page(struct page *page) p = swap_info_get(entry); if (p) { /* Is the only swap cache user the cache itself? */ - if (p->swap_map[SWP_OFFSET(entry)] == 1) { + if (p->swap_map[swp_offset(entry)] == 1) { /* Recheck the page count with the pagecache lock held.. */ read_lock(&swapper_space.page_lock); if (page_count(page) - !!PagePrivate(page) == 2) @@ -307,7 +308,7 @@ int remove_exclusive_swap_page(struct page *page) /* Is the only swap cache user the cache itself? */ retval = 0; - if (p->swap_map[SWP_OFFSET(entry)] == 1) { + if (p->swap_map[swp_offset(entry)] == 1) { /* Recheck the page count with the pagecache lock held.. */ write_lock(&swapper_space.page_lock); if (page_count(page) - !!PagePrivate(page) == 2) { @@ -344,7 +345,7 @@ void free_swap_and_cache(swp_entry_t entry) p = swap_info_get(entry); if (p) { - if (swap_entry_free(p, SWP_OFFSET(entry)) == 1) + if (swap_entry_free(p, swp_offset(entry)) == 1) page = find_trylock_page(&swapper_space, entry.val); swap_info_put(p); } @@ -568,7 +569,7 @@ static int try_to_unuse(unsigned int type) * page and read the swap into it. */ swap_map = &si->swap_map[i]; - entry = SWP_ENTRY(type, i); + entry = swp_entry(type, i); page = read_swap_cache_async(entry); if (!page) { /* @@ -954,7 +955,7 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags) } lock_page(virt_to_page(swap_header)); - rw_swap_page_nolock(READ, SWP_ENTRY(type,0), (char *) swap_header); + rw_swap_page_nolock(READ, swp_entry(type,0), (char *) swap_header); if (!memcmp("SWAP-SPACE",swap_header->magic.magic,10)) swap_header_version = 1; @@ -1007,7 +1008,7 @@ asmlinkage long sys_swapon(const char * specialfile, int swap_flags) } p->lowest_bit = 1; - maxpages = SWP_OFFSET(SWP_ENTRY(0,~0UL)) - 1; + maxpages = swp_offset(swp_entry(0,~0UL)) - 1; if (maxpages > swap_header->info.last_page) maxpages = swap_header->info.last_page; p->highest_bit = maxpages - 1; @@ -1141,11 +1142,11 @@ int swap_duplicate(swp_entry_t entry) unsigned long offset, type; int result = 0; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) goto bad_file; p = type + swap_info; - offset = SWP_OFFSET(entry); + offset = swp_offset(entry); swap_device_lock(p); if (offset < p->max && p->swap_map[offset]) { @@ -1182,11 +1183,11 @@ int swap_count(struct page *page) entry.val = page->index; if (!entry.val) goto bad_entry; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) goto bad_file; p = type + swap_info; - offset = SWP_OFFSET(entry); + offset = swp_offset(entry); if (offset >= p->max) goto bad_offset; if (!p->swap_map[offset]) @@ -1218,14 +1219,14 @@ void get_swaphandle_info(swp_entry_t entry, unsigned long *offset, unsigned long type; struct swap_info_struct *p; - type = SWP_TYPE(entry); + type = swp_type(entry); if (type >= nr_swapfiles) { printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_file, entry.val); return; } p = &swap_info[type]; - *offset = SWP_OFFSET(entry); + *offset = swp_offset(entry); if (*offset >= p->max && *offset != 0) { printk(KERN_ERR "rw_swap_page: %s%08lx\n", Bad_offset, entry.val); return; @@ -1250,11 +1251,11 @@ int valid_swaphandles(swp_entry_t entry, unsigned long *offset) { int ret = 0, i = 1 << page_cluster; unsigned long toff; - struct swap_info_struct *swapdev = SWP_TYPE(entry) + swap_info; + struct swap_info_struct *swapdev = swp_type(entry) + swap_info; if (!page_cluster) /* no readahead */ return 0; - toff = (SWP_OFFSET(entry) >> page_cluster) << page_cluster; + toff = (swp_offset(entry) >> page_cluster) << page_cluster; if (!toff) /* first page is swap header */ toff++, i--; *offset = toff; diff --git a/mm/vmscan.c b/mm/vmscan.c index 167413089968..91f180f2b08a 100644 --- a/mm/vmscan.c +++ b/mm/vmscan.c @@ -27,6 +27,7 @@ #include #include +#include /* * The "priority" of VM scanning is how much of the queues we -- cgit v1.2.3 From ddedde1dac6640a722545a253a79e15f5e70d2c7 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 2 Jun 2002 03:22:54 -0700 Subject: [PATCH] remove inode.i_wait Remove i_wait from struct inode and hash it instead. This is a pure space-saving exercise - 12 bytes from struct inode on x86. NFS was using i_wait for its own purposes. Add a wait_queue_head_t to the fs-private inode for that. This change has been acked by Trond. --- fs/fs-writeback.c | 3 +- fs/inode.c | 175 +++++++++++++++++++++++++++------------------- fs/nfs/inode.c | 8 ++- include/linux/fs.h | 1 - include/linux/nfs_fs.h | 3 + include/linux/writeback.h | 1 + 6 files changed, 116 insertions(+), 75 deletions(-) (limited to 'include') diff --git a/fs/fs-writeback.c b/fs/fs-writeback.c index dae51694ae43..c9549228ee97 100644 --- a/fs/fs-writeback.c +++ b/fs/fs-writeback.c @@ -176,8 +176,7 @@ static void __sync_single_inode(struct inode *inode, int wait, int *nr_to_write) } } } - if (waitqueue_active(&inode->i_wait)) - wake_up(&inode->i_wait); + wake_up_inode(inode); } /* diff --git a/fs/inode.c b/fs/inode.c index 9fca16d59ee8..17cc8dfb1ac9 100644 --- a/fs/inode.c +++ b/fs/inode.c @@ -14,6 +14,9 @@ #include #include #include +#include +#include + /* * This is needed for the following functions: * - inode_has_buffers @@ -149,7 +152,6 @@ static void destroy_inode(struct inode *inode) void inode_init_once(struct inode *inode) { memset(inode, 0, sizeof(*inode)); - init_waitqueue_head(&inode->i_wait); INIT_LIST_HEAD(&inode->i_hash); INIT_LIST_HEAD(&inode->i_data.clean_pages); INIT_LIST_HEAD(&inode->i_data.dirty_pages); @@ -176,21 +178,6 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) inode_init_once(inode); } -void __wait_on_inode(struct inode * inode) -{ - DECLARE_WAITQUEUE(wait, current); - - add_wait_queue(&inode->i_wait, &wait); -repeat: - set_current_state(TASK_UNINTERRUPTIBLE); - if (inode->i_state & I_LOCK) { - schedule(); - goto repeat; - } - remove_wait_queue(&inode->i_wait, &wait); - current->state = TASK_RUNNING; -} - /* * inode_lock must be held */ @@ -538,7 +525,7 @@ void unlock_new_inode(struct inode *inode) * that haven't tested I_LOCK). */ inode->i_state &= ~(I_LOCK|I_NEW); - wake_up(&inode->i_wait); + wake_up_inode(inode); } @@ -899,59 +886,6 @@ int bmap(struct inode * inode, int block) return res; } -/* - * Initialize the hash tables. - */ -void __init inode_init(unsigned long mempages) -{ - struct list_head *head; - unsigned long order; - unsigned int nr_hash; - int i; - - mempages >>= (14 - PAGE_SHIFT); - mempages *= sizeof(struct list_head); - for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) - ; - - do { - unsigned long tmp; - - nr_hash = (1UL << order) * PAGE_SIZE / - sizeof(struct list_head); - i_hash_mask = (nr_hash - 1); - - tmp = nr_hash; - i_hash_shift = 0; - while ((tmp >>= 1UL) != 0UL) - i_hash_shift++; - - inode_hashtable = (struct list_head *) - __get_free_pages(GFP_ATOMIC, order); - } while (inode_hashtable == NULL && --order >= 0); - - printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n", - nr_hash, order, (PAGE_SIZE << order)); - - if (!inode_hashtable) - panic("Failed to allocate inode hash table\n"); - - head = inode_hashtable; - i = nr_hash; - do { - INIT_LIST_HEAD(head); - head++; - i--; - } while (i); - - /* inode slab cache */ - inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), - 0, SLAB_HWCACHE_ALIGN, init_once, - NULL); - if (!inode_cachep) - panic("cannot create inode slab cache"); -} - static inline void do_atime_update(struct inode *inode) { unsigned long time = CURRENT_TIME; @@ -1044,3 +978,104 @@ void remove_dquot_ref(struct super_block *sb, int type) } #endif + +/* + * Hashed waitqueues for wait_on_inode(). The table is pretty small - the + * kernel doesn't lock many inodes at the same time. + */ +#define I_WAIT_TABLE_ORDER 3 +static struct i_wait_queue_head { + wait_queue_head_t wqh; +} ____cacheline_aligned_in_smp i_wait_queue_heads[1<i_state & I_LOCK) { + schedule(); + goto repeat; + } + remove_wait_queue(wq, &wait); + current->state = TASK_RUNNING; +} + +void wake_up_inode(struct inode *inode) +{ + wait_queue_head_t *wq = i_waitq_head(inode); + + /* + * Prevent speculative execution through spin_unlock(&inode_lock); + */ + smp_mb(); + if (waitqueue_active(wq)) + wake_up_all(wq); +} + +/* + * Initialize the waitqueues and inode hash table. + */ +void __init inode_init(unsigned long mempages) +{ + struct list_head *head; + unsigned long order; + unsigned int nr_hash; + int i; + + for (i = 0; i < ARRAY_SIZE(i_wait_queue_heads); i++) + init_waitqueue_head(&i_wait_queue_heads[i].wqh); + + mempages >>= (14 - PAGE_SHIFT); + mempages *= sizeof(struct list_head); + for (order = 0; ((1UL << order) << PAGE_SHIFT) < mempages; order++) + ; + + do { + unsigned long tmp; + + nr_hash = (1UL << order) * PAGE_SIZE / + sizeof(struct list_head); + i_hash_mask = (nr_hash - 1); + + tmp = nr_hash; + i_hash_shift = 0; + while ((tmp >>= 1UL) != 0UL) + i_hash_shift++; + + inode_hashtable = (struct list_head *) + __get_free_pages(GFP_ATOMIC, order); + } while (inode_hashtable == NULL && --order >= 0); + + printk("Inode-cache hash table entries: %d (order: %ld, %ld bytes)\n", + nr_hash, order, (PAGE_SIZE << order)); + + if (!inode_hashtable) + panic("Failed to allocate inode hash table\n"); + + head = inode_hashtable; + i = nr_hash; + do { + INIT_LIST_HEAD(head); + head++; + i--; + } while (i); + + /* inode slab cache */ + inode_cachep = kmem_cache_create("inode_cache", sizeof(struct inode), + 0, SLAB_HWCACHE_ALIGN, init_once, + NULL); + if (!inode_cachep) + panic("cannot create inode slab cache"); +} diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c index 6f0e6fc0340f..9d61c8b75258 100644 --- a/fs/nfs/inode.c +++ b/fs/nfs/inode.c @@ -799,11 +799,14 @@ int nfs_wait_on_inode(struct inode *inode, int flag) { struct rpc_clnt *clnt = NFS_CLIENT(inode); + struct nfs_inode *nfsi = NFS_I(inode); + int error; if (!(NFS_FLAGS(inode) & flag)) return 0; atomic_inc(&inode->i_count); - error = nfs_wait_event(clnt, inode->i_wait, !(NFS_FLAGS(inode) & flag)); + error = nfs_wait_event(clnt, nfsi->nfs_i_wait, + !(NFS_FLAGS(inode) & flag)); iput(inode); return error; } @@ -922,7 +925,7 @@ __nfs_revalidate_inode(struct nfs_server *server, struct inode *inode) NFS_FLAGS(inode) &= ~NFS_INO_STALE; out: NFS_FLAGS(inode) &= ~NFS_INO_REVALIDATING; - wake_up(&inode->i_wait); + wake_up(&NFS_I(inode)->nfs_i_wait); out_nowait: unlock_kernel(); return status; @@ -1258,6 +1261,7 @@ static void init_once(void * foo, kmem_cache_t * cachep, unsigned long flags) nfsi->ndirty = 0; nfsi->ncommit = 0; nfsi->npages = 0; + init_waitqueue_head(&nfsi->nfs_i_wait); } } diff --git a/include/linux/fs.h b/include/linux/fs.h index 31a691491a9f..1b01db32cc35 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -383,7 +383,6 @@ struct inode { struct inode_operations *i_op; struct file_operations *i_fop; /* former ->i_op->default_file_ops */ struct super_block *i_sb; - wait_queue_head_t i_wait; struct file_lock *i_flock; struct address_space *i_mapping; struct address_space i_data; diff --git a/include/linux/nfs_fs.h b/include/linux/nfs_fs.h index 027986b2f336..64c3b5ef2d88 100644 --- a/include/linux/nfs_fs.h +++ b/include/linux/nfs_fs.h @@ -13,6 +13,7 @@ #include #include #include +#include #include @@ -159,6 +160,8 @@ struct nfs_inode { /* Credentials for shared mmap */ struct rpc_cred *mm_cred; + wait_queue_head_t nfs_i_wait; + struct inode vfs_inode; }; diff --git a/include/linux/writeback.h b/include/linux/writeback.h index 5f035892d26f..cf706c783eda 100644 --- a/include/linux/writeback.h +++ b/include/linux/writeback.h @@ -31,6 +31,7 @@ static inline int current_is_pdflush(void) void writeback_unlocked_inodes(int *nr_to_write, int sync_mode, unsigned long *older_than_this); +void wake_up_inode(struct inode *inode); void __wait_on_inode(struct inode * inode); void sync_inodes_sb(struct super_block *, int wait); void sync_inodes(int wait); -- cgit v1.2.3 From 5a302308ef86f0030628fd9244e8495007ce9e70 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 2 Jun 2002 03:23:07 -0700 Subject: [PATCH] rename block_symlink() to page_symlink() block_symlink() is not a "block" function at all. It is a pure pagecache/address_space function. Seeing driverfs calling it was the last straw. The patch renames it to `page_symlink()' and moves it into fs/namei.c --- fs/buffer.c | 40 ---------------------------------------- fs/driverfs/inode.c | 2 +- fs/ext2/namei.c | 3 +-- fs/ext3/inode.c | 2 +- fs/ext3/namei.c | 4 ++-- fs/minix/namei.c | 3 +-- fs/namei.c | 40 ++++++++++++++++++++++++++++++++++++++++ fs/ramfs/inode.c | 3 +-- fs/sysv/namei.c | 2 +- fs/ufs/namei.c | 2 +- fs/umsdos/namei.c | 2 +- include/linux/buffer_head.h | 1 - include/linux/fs.h | 1 + kernel/ksyms.c | 2 +- 14 files changed, 52 insertions(+), 55 deletions(-) (limited to 'include') diff --git a/fs/buffer.c b/fs/buffer.c index 66ace03446ad..80b01a96ee35 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -2327,46 +2327,6 @@ int brw_page(int rw, struct page *page, return 0; } -int block_symlink(struct inode *inode, const char *symname, int len) -{ - struct address_space *mapping = inode->i_mapping; - struct page *page = grab_cache_page(mapping, 0); - int err = -ENOMEM; - char *kaddr; - - if (!page) - goto fail; - err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); - if (err) - goto fail_map; - kaddr = page_address(page); - memcpy(kaddr, symname, len-1); - mapping->a_ops->commit_write(NULL, page, 0, len-1); - /* - * Notice that we are _not_ going to block here - end of page is - * unmapped, so this will only try to map the rest of page, see - * that it is unmapped (typically even will not look into inode - - * ->i_size will be enough for everything) and zero it out. - * OTOH it's obviously correct and should make the page up-to-date. - */ - if (!PageUptodate(page)) { - err = mapping->a_ops->readpage(NULL, page); - wait_on_page_locked(page); - } else { - unlock_page(page); - } - page_cache_release(page); - if (err < 0) - goto fail; - mark_inode_dirty(inode); - return 0; -fail_map: - unlock_page(page); - page_cache_release(page); -fail: - return err; -} - /* * Sanity checks for try_to_free_buffers. */ diff --git a/fs/driverfs/inode.c b/fs/driverfs/inode.c index c0461118ce00..044443f73e6c 100644 --- a/fs/driverfs/inode.c +++ b/fs/driverfs/inode.c @@ -171,7 +171,7 @@ static int driverfs_symlink(struct inode * dir, struct dentry *dentry, const cha inode = driverfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); if (inode) { int l = strlen(symname)+1; - error = block_symlink(inode, symname, l); + error = page_symlink(inode, symname, l); if (!error) { d_instantiate(dentry, inode); dget(dentry); diff --git a/fs/ext2/namei.c b/fs/ext2/namei.c index e1cfa4aedfb4..0b15a2f878e7 100644 --- a/fs/ext2/namei.c +++ b/fs/ext2/namei.c @@ -31,7 +31,6 @@ #include "ext2.h" #include -#include /* for block_symlink() */ /* * Couple of helper functions - make the code slightly cleaner. @@ -165,7 +164,7 @@ static int ext2_symlink (struct inode * dir, struct dentry * dentry, /* slow symlink */ inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &ext2_aops; - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_fail; } else { diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 52f744db686c..7e3e8aed1ba4 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1092,7 +1092,7 @@ static int commit_write_fn(handle_t *handle, struct buffer_head *bh) /* * We need to pick up the new inode size which generic_commit_write gave us - * `file' can be NULL - eg, when called from block_symlink(). + * `file' can be NULL - eg, when called from page_symlink(). * * ext3 never places buffers on inode->i_mapping->private_list. metadata * buffers are managed internally. diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index 5480619fd800..a5a4ff23ece9 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -987,11 +987,11 @@ static int ext3_symlink (struct inode * dir, inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &ext3_aops; /* - * block_symlink() calls back into ext3_prepare/commit_write. + * page_symlink() calls into ext3_prepare/commit_write. * We have a transaction open. All is sweetness. It also sets * i_size in generic_commit_write(). */ - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_no_entry; } else { diff --git a/fs/minix/namei.c b/fs/minix/namei.c index 490d638aeb66..94cbe91bb9ff 100644 --- a/fs/minix/namei.c +++ b/fs/minix/namei.c @@ -4,7 +4,6 @@ * Copyright (C) 1991, 1992 Linus Torvalds */ -#include /* for block_symlink() */ #include "minix.h" static inline void inc_count(struct inode *inode) @@ -111,7 +110,7 @@ static int minix_symlink(struct inode * dir, struct dentry *dentry, inode->i_mode = S_IFLNK | 0777; minix_set_inode(inode, 0); - err = block_symlink(inode, symname, i); + err = page_symlink(inode, symname, i); if (err) goto out_fail; diff --git a/fs/namei.c b/fs/namei.c index d4cea0318dc4..506f8b5eee6b 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2136,6 +2136,46 @@ int page_follow_link(struct dentry *dentry, struct nameidata *nd) return res; } +int page_symlink(struct inode *inode, const char *symname, int len) +{ + struct address_space *mapping = inode->i_mapping; + struct page *page = grab_cache_page(mapping, 0); + int err = -ENOMEM; + char *kaddr; + + if (!page) + goto fail; + err = mapping->a_ops->prepare_write(NULL, page, 0, len-1); + if (err) + goto fail_map; + kaddr = page_address(page); + memcpy(kaddr, symname, len-1); + mapping->a_ops->commit_write(NULL, page, 0, len-1); + /* + * Notice that we are _not_ going to block here - end of page is + * unmapped, so this will only try to map the rest of page, see + * that it is unmapped (typically even will not look into inode - + * ->i_size will be enough for everything) and zero it out. + * OTOH it's obviously correct and should make the page up-to-date. + */ + if (!PageUptodate(page)) { + err = mapping->a_ops->readpage(NULL, page); + wait_on_page_locked(page); + } else { + unlock_page(page); + } + page_cache_release(page); + if (err < 0) + goto fail; + mark_inode_dirty(inode); + return 0; +fail_map: + unlock_page(page); + page_cache_release(page); +fail: + return err; +} + struct inode_operations page_symlink_inode_operations = { readlink: page_readlink, follow_link: page_follow_link, diff --git a/fs/ramfs/inode.c b/fs/ramfs/inode.c index b5e8ec09d431..4d7bb011fbf6 100644 --- a/fs/ramfs/inode.c +++ b/fs/ramfs/inode.c @@ -29,7 +29,6 @@ #include #include #include -#include /* for block_symlink() */ #include @@ -235,7 +234,7 @@ static int ramfs_symlink(struct inode * dir, struct dentry *dentry, const char * inode = ramfs_get_inode(dir->i_sb, S_IFLNK|S_IRWXUGO, 0); if (inode) { int l = strlen(symname)+1; - error = block_symlink(inode, symname, l); + error = page_symlink(inode, symname, l); if (!error) { d_instantiate(dentry, inode); dget(dentry); diff --git a/fs/sysv/namei.c b/fs/sysv/namei.c index 34cbff4f7c5f..e3681629a89d 100644 --- a/fs/sysv/namei.c +++ b/fs/sysv/namei.c @@ -117,7 +117,7 @@ static int sysv_symlink(struct inode * dir, struct dentry * dentry, goto out; sysv_set_inode(inode, 0); - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_fail; diff --git a/fs/ufs/namei.c b/fs/ufs/namei.c index 643dd7b3780c..faea20eb2069 100644 --- a/fs/ufs/namei.c +++ b/fs/ufs/namei.c @@ -143,7 +143,7 @@ static int ufs_symlink (struct inode * dir, struct dentry * dentry, /* slow symlink */ inode->i_op = &page_symlink_inode_operations; inode->i_mapping->a_ops = &ufs_aops; - err = block_symlink(inode, symname, l); + err = page_symlink(inode, symname, l); if (err) goto out_fail; } else { diff --git a/fs/umsdos/namei.c b/fs/umsdos/namei.c index f7640dbda210..9dbcc659408a 100644 --- a/fs/umsdos/namei.c +++ b/fs/umsdos/namei.c @@ -499,7 +499,7 @@ static int umsdos_symlink_x (struct inode *dir, struct dentry *dentry, } len = strlen (symname) + 1; - ret = block_symlink(dentry->d_inode, symname, len); + ret = page_symlink(dentry->d_inode, symname, len); if (ret < 0) goto out_unlink; out: diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 9bcb2b34df84..38e533d62fa9 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -192,7 +192,6 @@ void FASTCALL(unlock_buffer(struct buffer_head *bh)); */ int try_to_release_page(struct page * page, int gfp_mask); int block_flushpage(struct page *page, unsigned long offset); -int block_symlink(struct inode *, const char *, int); int block_write_full_page(struct page*, get_block_t*); int block_read_full_page(struct page*, get_block_t*); int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); diff --git a/include/linux/fs.h b/include/linux/fs.h index 1b01db32cc35..f4ae9af76b69 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -1244,6 +1244,7 @@ extern int vfs_readlink(struct dentry *, char *, int, const char *); extern int vfs_follow_link(struct nameidata *, const char *); extern int page_readlink(struct dentry *, char *, int); extern int page_follow_link(struct dentry *, struct nameidata *); +extern int page_symlink(struct inode *inode, const char *symname, int len); extern struct inode_operations page_symlink_inode_operations; extern void generic_fillattr(struct inode *, struct kstat *); diff --git a/kernel/ksyms.c b/kernel/ksyms.c index 0f17b56ac17a..19f60908e878 100644 --- a/kernel/ksyms.c +++ b/kernel/ksyms.c @@ -277,7 +277,7 @@ EXPORT_SYMBOL(vfs_follow_link); EXPORT_SYMBOL(page_readlink); EXPORT_SYMBOL(page_follow_link); EXPORT_SYMBOL(page_symlink_inode_operations); -EXPORT_SYMBOL(block_symlink); +EXPORT_SYMBOL(page_symlink); EXPORT_SYMBOL(vfs_readdir); EXPORT_SYMBOL(__get_lease); EXPORT_SYMBOL(lease_get_mtime); -- cgit v1.2.3 From da9bfeb499208761f621ec7f4fbe381736ecfb85 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 2 Jun 2002 03:23:19 -0700 Subject: [PATCH] direct-to-BIO writeback for writeback-mode ext3 Turn on direct-to-BIO writeback for ext3 in data=writeback mode. --- fs/ext3/inode.c | 38 ++++++++++++++++++++++++++++++++++++-- fs/ext3/namei.c | 10 ++++++++-- include/linux/ext3_fs.h | 1 + include/linux/ext3_jbd.h | 5 +++++ 4 files changed, 50 insertions(+), 4 deletions(-) (limited to 'include') diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index 7e3e8aed1ba4..aad5acd5d381 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1389,6 +1389,34 @@ struct address_space_operations ext3_aops = { releasepage: ext3_releasepage, /* BKL not held. Don't need */ }; +/* For writeback mode, we can use mpage_writepages() */ + +static int +ext3_writepages(struct address_space *mapping, int *nr_to_write) +{ + int ret; + int err; + + ret = write_mapping_buffers(mapping); + err = mpage_writepages(mapping, nr_to_write, ext3_get_block); + if (!ret) + ret = err; + return ret; +} + +struct address_space_operations ext3_writeback_aops = { + readpage: ext3_readpage, /* BKL not held. Don't need */ + readpages: ext3_readpages, /* BKL not held. Don't need */ + writepage: ext3_writepage, /* BKL not held. We take it */ + writepages: ext3_writepages, /* BKL not held. Don't need */ + sync_page: block_sync_page, + prepare_write: ext3_prepare_write, /* BKL not held. We take it */ + commit_write: ext3_commit_write, /* BKL not held. We take it */ + bmap: ext3_bmap, /* BKL held */ + flushpage: ext3_flushpage, /* BKL not held. Don't need */ + releasepage: ext3_releasepage, /* BKL not held. Don't need */ +}; + /* * ext3_block_truncate_page() zeroes out a mapping from file offset `from' * up to the end of the block which corresponds to `from'. @@ -2159,7 +2187,10 @@ void ext3_read_inode(struct inode * inode) else if (S_ISREG(inode->i_mode)) { inode->i_op = &ext3_file_inode_operations; inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; } else if (S_ISDIR(inode->i_mode)) { inode->i_op = &ext3_dir_inode_operations; inode->i_fop = &ext3_dir_operations; @@ -2168,7 +2199,10 @@ void ext3_read_inode(struct inode * inode) inode->i_op = &ext3_fast_symlink_inode_operations; else { inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; } } else init_special_inode(inode, inode->i_mode, diff --git a/fs/ext3/namei.c b/fs/ext3/namei.c index a5a4ff23ece9..693bdd30ccbf 100644 --- a/fs/ext3/namei.c +++ b/fs/ext3/namei.c @@ -510,7 +510,10 @@ static int ext3_create (struct inode * dir, struct dentry * dentry, int mode) if (!IS_ERR(inode)) { inode->i_op = &ext3_file_inode_operations; inode->i_fop = &ext3_file_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; ext3_mark_inode_dirty(handle, inode); err = ext3_add_nondir(handle, dentry, inode); } @@ -985,7 +988,10 @@ static int ext3_symlink (struct inode * dir, if (l > sizeof (EXT3_I(inode)->i_data)) { inode->i_op = &page_symlink_inode_operations; - inode->i_mapping->a_ops = &ext3_aops; + if (ext3_should_writeback_data(inode)) + inode->i_mapping->a_ops = &ext3_writeback_aops; + else + inode->i_mapping->a_ops = &ext3_aops; /* * page_symlink() calls into ext3_prepare/commit_write. * We have a transaction open. All is sweetness. It also sets diff --git a/include/linux/ext3_fs.h b/include/linux/ext3_fs.h index f8630de86518..5847e06c1020 100644 --- a/include/linux/ext3_fs.h +++ b/include/linux/ext3_fs.h @@ -695,6 +695,7 @@ extern struct file_operations ext3_file_operations; /* inode.c */ extern struct address_space_operations ext3_aops; +extern struct address_space_operations ext3_writeback_aops; /* namei.c */ extern struct inode_operations ext3_dir_inode_operations; diff --git a/include/linux/ext3_jbd.h b/include/linux/ext3_jbd.h index ece9ec115665..05645eb7afca 100644 --- a/include/linux/ext3_jbd.h +++ b/include/linux/ext3_jbd.h @@ -299,5 +299,10 @@ static inline int ext3_should_order_data(struct inode *inode) return (test_opt(inode->i_sb, DATA_FLAGS) == EXT3_MOUNT_ORDERED_DATA); } +static inline int ext3_should_writeback_data(struct inode *inode) +{ + return !ext3_should_journal_data(inode) && + !ext3_should_order_data(inode); +} #endif /* _LINUX_EXT3_JBD_H */ -- cgit v1.2.3 From 53b478c60dd9914ce1668128ba466188ef42c918 Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Sun, 2 Jun 2002 03:24:28 -0700 Subject: [PATCH] rename flushpage to invalidatepage Fixes a pet peeve: the identifier "flushpage" implies "flush the page to disk". Which is very much not what the flushpage functions actually do. The patch renames block_flushpage and the flushpage address_space_operation to "invalidatepage". It also fixes a buglet in invalidate_this_page2(), which was calling block_flushpage() directly - it needs to call do_flushpage() (now do_invalidatepage()) so that the filesystem's ->flushpage (now ->invalidatepage) a_op gets a chance to relinquish any interest which it has in the page's buffers. --- Documentation/filesystems/Locking | 10 +++++----- fs/buffer.c | 22 +++++++++++----------- fs/ext3/inode.c | 8 ++++---- fs/jbd/journal.c | 2 +- fs/jbd/transaction.c | 6 +++--- fs/jfs/jfs_metapage.c | 6 +++--- include/linux/buffer_head.h | 2 +- include/linux/fs.h | 2 +- include/linux/jbd.h | 3 ++- mm/filemap.c | 22 +++++++++++----------- 10 files changed, 42 insertions(+), 41 deletions(-) (limited to 'include') diff --git a/Documentation/filesystems/Locking b/Documentation/filesystems/Locking index 0bb774bb0c3b..1b73f2a9ea79 100644 --- a/Documentation/filesystems/Locking +++ b/Documentation/filesystems/Locking @@ -138,7 +138,7 @@ prototypes: int (*prepare_write)(struct file *, struct page *, unsigned, unsigned); int (*commit_write)(struct file *, struct page *, unsigned, unsigned); int (*bmap)(struct address_space *, long); - int (*flushpage) (struct page *, unsigned long); + int (*invalidatepage) (struct page *, unsigned long); int (*releasepage) (struct page *, int); int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int); @@ -156,7 +156,7 @@ set_page_dirty no no prepare_write: no yes commit_write: no yes bmap: yes -flushpage: no yes +invalidatepage: no yes releasepage: no yes ->prepare_write(), ->commit_write(), ->sync_page() and ->readpage() @@ -206,10 +206,10 @@ filesystems and by the swapper. The latter will eventually go away. All instances do not actually need the BKL. Please, keep it that way and don't breed new callers. - ->flushpage() is called when the filesystem must attempt to drop + ->invalidatepage() is called when the filesystem must attempt to drop some or all of the buffers from the page when it is being truncated. It -returns zero on success. If ->flushpage is zero, the kernel uses -block_flushpage() instead. +returns zero on success. If ->invalidatepage is zero, the kernel uses +block_invalidatepage() instead. ->releasepage() is called when the kernel is about to try to drop the buffers from the page in preparation for freeing it. It returns zero to diff --git a/fs/buffer.c b/fs/buffer.c index 80b01a96ee35..dd21d3ed1ad1 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1341,22 +1341,21 @@ int try_to_release_page(struct page *page, int gfp_mask) } /** - * block_flushpage - invalidate part of all of a buffer-backed page + * block_invalidatepage - invalidate part of all of a buffer-backed page * * @page: the page which is affected * @offset: the index of the truncation point * - * block_flushpage() should be called block_invalidatepage(). It is - * called when all or part of the page has become invalidatedby a truncate - * operation. + * block_invalidatepage() is called when all or part of the page has become + * invalidatedby a truncate operation. * - * block_flushpage() does not have to release all buffers, but it must + * block_invalidatepage() does not have to release all buffers, but it must * ensure that no dirty buffer is left outside @offset and that no I/O * is underway against any of the blocks which are outside the truncation * point. Because the caller is about to free (and possibly reuse) those * blocks on-disk. */ -int block_flushpage(struct page *page, unsigned long offset) +int block_invalidatepage(struct page *page, unsigned long offset) { struct buffer_head *head, *bh, *next; unsigned int curr_off = 0; @@ -1393,7 +1392,7 @@ int block_flushpage(struct page *page, unsigned long offset) return 1; } -EXPORT_SYMBOL(block_flushpage); +EXPORT_SYMBOL(block_invalidatepage); /* * We attach and possibly dirty the buffers atomically wrt @@ -2276,10 +2275,11 @@ int brw_kiovec(int rw, int nr, struct kiobuf *iovec[], * some of the bmap kludges and interface ugliness here. * * NOTE: unlike file pages, swap pages are locked while under writeout. - * This is to avoid a deadlock which occurs when free_swap_and_cache() - * calls block_flushpage() under spinlock and hits a locked buffer, and - * schedules under spinlock. Another approach would be to teach - * find_trylock_page() to also trylock the page's writeback flags. + * This is to throttle processes which reuse their swapcache pages while + * they are under writeout, and to ensure that there is no I/O going on + * when the page has been successfully locked. Functions such as + * free_swap_and_cache() need to guarantee that there is no I/O in progress + * because they will be freeing up swap blocks, which may then be reused. * * Swap pages are also marked PageWriteback when they are being written * so that memory allocators will throttle on them. diff --git a/fs/ext3/inode.c b/fs/ext3/inode.c index aad5acd5d381..b339c253628e 100644 --- a/fs/ext3/inode.c +++ b/fs/ext3/inode.c @@ -1364,10 +1364,10 @@ ext3_readpages(struct address_space *mapping, return mpage_readpages(mapping, pages, nr_pages, ext3_get_block); } -static int ext3_flushpage(struct page *page, unsigned long offset) +static int ext3_invalidatepage(struct page *page, unsigned long offset) { journal_t *journal = EXT3_JOURNAL(page->mapping->host); - return journal_flushpage(journal, page, offset); + return journal_invalidatepage(journal, page, offset); } static int ext3_releasepage(struct page *page, int wait) @@ -1385,7 +1385,7 @@ struct address_space_operations ext3_aops = { prepare_write: ext3_prepare_write, /* BKL not held. We take it */ commit_write: ext3_commit_write, /* BKL not held. We take it */ bmap: ext3_bmap, /* BKL held */ - flushpage: ext3_flushpage, /* BKL not held. Don't need */ + invalidatepage: ext3_invalidatepage, /* BKL not held. Don't need */ releasepage: ext3_releasepage, /* BKL not held. Don't need */ }; @@ -1413,7 +1413,7 @@ struct address_space_operations ext3_writeback_aops = { prepare_write: ext3_prepare_write, /* BKL not held. We take it */ commit_write: ext3_commit_write, /* BKL not held. We take it */ bmap: ext3_bmap, /* BKL held */ - flushpage: ext3_flushpage, /* BKL not held. Don't need */ + invalidatepage: ext3_invalidatepage, /* BKL not held. Don't need */ releasepage: ext3_releasepage, /* BKL not held. Don't need */ }; diff --git a/fs/jbd/journal.c b/fs/jbd/journal.c index f20e9f4e8c35..052dd4ef3f01 100644 --- a/fs/jbd/journal.c +++ b/fs/jbd/journal.c @@ -78,7 +78,7 @@ EXPORT_SYMBOL(log_wait_commit); EXPORT_SYMBOL(log_start_commit); EXPORT_SYMBOL(journal_wipe); EXPORT_SYMBOL(journal_blocks_per_page); -EXPORT_SYMBOL(journal_flushpage); +EXPORT_SYMBOL(journal_invalidatepage); EXPORT_SYMBOL(journal_try_to_free_buffers); EXPORT_SYMBOL(journal_bmap); EXPORT_SYMBOL(journal_force_commit); diff --git a/fs/jbd/transaction.c b/fs/jbd/transaction.c index 82886e98f26f..89c625bf9fa8 100644 --- a/fs/jbd/transaction.c +++ b/fs/jbd/transaction.c @@ -1749,13 +1749,13 @@ static int dispose_buffer(struct journal_head *jh, } /* - * journal_flushpage + * journal_invalidatepage * * This code is tricky. It has a number of cases to deal with. * * There are two invariants which this code relies on: * - * i_size must be updated on disk before we start calling flushpage on the + * i_size must be updated on disk before we start calling invalidatepage on the * data. * * This is done in ext3 by defining an ext3_setattr method which @@ -1891,7 +1891,7 @@ zap_buffer: /* * Return non-zero if the page's buffers were successfully reaped */ -int journal_flushpage(journal_t *journal, +int journal_invalidatepage(journal_t *journal, struct page *page, unsigned long offset) { diff --git a/fs/jfs/jfs_metapage.c b/fs/jfs/jfs_metapage.c index 7d0e39c683b7..37aaec2e67f7 100644 --- a/fs/jfs/jfs_metapage.c +++ b/fs/jfs/jfs_metapage.c @@ -537,7 +537,7 @@ void release_metapage(metapage_t * mp) if (test_bit(META_discard, &mp->flag)) { lock_page(mp->page); - block_flushpage(mp->page, 0); + block_invalidatepage(mp->page, 0); unlock_page(mp->page); } @@ -587,13 +587,13 @@ void invalidate_metapages(struct inode *ip, unsigned long addr, set_bit(META_discard, &mp->flag); spin_unlock(&meta_lock); lock_page(mp->page); - block_flushpage(mp->page, 0); + block_invalidatepage(mp->page, 0); unlock_page(mp->page); } else { spin_unlock(&meta_lock); page = find_lock_page(mapping, lblock>>l2BlocksPerPage); if (page) { - block_flushpage(page, 0); + block_invalidatepage(page, 0); unlock_page(page); } } diff --git a/include/linux/buffer_head.h b/include/linux/buffer_head.h index 38e533d62fa9..90767fc78617 100644 --- a/include/linux/buffer_head.h +++ b/include/linux/buffer_head.h @@ -191,7 +191,7 @@ void FASTCALL(unlock_buffer(struct buffer_head *bh)); * address_spaces. */ int try_to_release_page(struct page * page, int gfp_mask); -int block_flushpage(struct page *page, unsigned long offset); +int block_invalidatepage(struct page *page, unsigned long offset); int block_write_full_page(struct page*, get_block_t*); int block_read_full_page(struct page*, get_block_t*); int block_prepare_write(struct page*, unsigned, unsigned, get_block_t*); diff --git a/include/linux/fs.h b/include/linux/fs.h index f4ae9af76b69..839dfbd712e2 100644 --- a/include/linux/fs.h +++ b/include/linux/fs.h @@ -306,7 +306,7 @@ struct address_space_operations { int (*commit_write)(struct file *, struct page *, unsigned, unsigned); /* Unfortunately this kludge is needed for FIBMAP. Don't use it */ int (*bmap)(struct address_space *, long); - int (*flushpage) (struct page *, unsigned long); + int (*invalidatepage) (struct page *, unsigned long); int (*releasepage) (struct page *, int); #define KERNEL_HAS_O_DIRECT /* this is for modules out of the kernel */ int (*direct_IO)(int, struct inode *, struct kiobuf *, unsigned long, int); diff --git a/include/linux/jbd.h b/include/linux/jbd.h index d0c52537a274..835d38c9dbfc 100644 --- a/include/linux/jbd.h +++ b/include/linux/jbd.h @@ -641,7 +641,8 @@ extern int journal_dirty_metadata (handle_t *, struct buffer_head *); extern void journal_release_buffer (handle_t *, struct buffer_head *); extern void journal_forget (handle_t *, struct buffer_head *); extern void journal_sync_buffer (struct buffer_head *); -extern int journal_flushpage(journal_t *, struct page *, unsigned long); +extern int journal_invalidatepage(journal_t *, + struct page *, unsigned long); extern int journal_try_to_free_buffers(journal_t *, struct page *, int); extern int journal_stop(handle_t *); extern int journal_flush (journal_t *); diff --git a/mm/filemap.c b/mm/filemap.c index bf7be669af45..a8283c49fcd0 100644 --- a/mm/filemap.c +++ b/mm/filemap.c @@ -23,7 +23,7 @@ /* * This is needed for the following functions: * - try_to_release_page - * - block_flushpage + * - block_invalidatepage * - page_has_buffers * - generic_osync_inode * @@ -154,30 +154,30 @@ unlock: spin_unlock(&pagemap_lru_lock); } -static int do_flushpage(struct page *page, unsigned long offset) +static int do_invalidatepage(struct page *page, unsigned long offset) { - int (*flushpage) (struct page *, unsigned long); - flushpage = page->mapping->a_ops->flushpage; - if (flushpage) - return (*flushpage)(page, offset); - return block_flushpage(page, offset); + int (*invalidatepage)(struct page *, unsigned long); + invalidatepage = page->mapping->a_ops->invalidatepage; + if (invalidatepage) + return (*invalidatepage)(page, offset); + return block_invalidatepage(page, offset); } static inline void truncate_partial_page(struct page *page, unsigned partial) { memclear_highpage_flush(page, partial, PAGE_CACHE_SIZE-partial); if (PagePrivate(page)) - do_flushpage(page, partial); + do_invalidatepage(page, partial); } /* * AKPM: the PagePrivate test here seems a bit bogus. It bypasses the - * mapping's ->flushpage, which may still want to be called. + * mapping's ->invalidatepage, which may still want to be called. */ static void truncate_complete_page(struct page *page) { /* Leave it on the LRU if it gets converted into anonymous buffers */ - if (!PagePrivate(page) || do_flushpage(page, 0)) + if (!PagePrivate(page) || do_invalidatepage(page, 0)) lru_cache_del(page); ClearPageDirty(page); ClearPageUptodate(page); @@ -339,7 +339,7 @@ static inline int invalidate_this_page2(struct address_space * mapping, page_cache_get(page); write_unlock(&mapping->page_lock); - block_flushpage(page, 0); + do_invalidatepage(page, 0); } else unlocked = 0; -- cgit v1.2.3 From 8795dba6a479913957c9c6e761abffabcc19d4a9 Mon Sep 17 00:00:00 2001 From: Martin Dalecki Date: Sun, 2 Jun 2002 03:28:08 -0700 Subject: [PATCH] 2.5.19 blk.h and more about the ugly kids. - Remove DEVICE_INTR and associated code from floppy driver. - Savlage s390 xpram code from kernel version dependant compilation disease. - Eliminate SET_INTR code from the places where it was used. - Eliminate bogous support for multiple sbpcd controllers. The driver didn't even compile right now before we could think about further supporting it at all we have to get rid of this hack first. Don't call invalidate_buffers in the release method there. Why should it be necessary? - Resurrect sonycd535 compilation. - Let CURRENT request macro use the same primitive at the remaining QUEUE macro in blk.h, which is still not quite right, but first things first :-). --- drivers/acorn/block/mfmhd.c | 16 ++-- drivers/block/acsi.c | 6 +- drivers/block/floppy.c | 32 +++---- drivers/cdrom/Config.help | 21 ----- drivers/cdrom/Config.in | 9 -- drivers/cdrom/Makefile | 3 - drivers/cdrom/gscd.c | 2 +- drivers/cdrom/sbpcd.c | 197 +++++++++++--------------------------------- drivers/cdrom/sbpcd.h | 20 ----- drivers/cdrom/sbpcd2.c | 5 -- drivers/cdrom/sbpcd3.c | 5 -- drivers/cdrom/sbpcd4.c | 5 -- drivers/cdrom/sonycd535.c | 8 +- drivers/ide/hd.c | 16 ++-- drivers/s390/block/xpram.c | 134 ++++-------------------------- include/linux/blk.h | 40 ++------- 16 files changed, 113 insertions(+), 406 deletions(-) delete mode 100644 drivers/cdrom/sbpcd2.c delete mode 100644 drivers/cdrom/sbpcd3.c delete mode 100644 drivers/cdrom/sbpcd4.c (limited to 'include') diff --git a/drivers/acorn/block/mfmhd.c b/drivers/acorn/block/mfmhd.c index de360a94edb2..1bfb0789d771 100644 --- a/drivers/acorn/block/mfmhd.c +++ b/drivers/acorn/block/mfmhd.c @@ -570,7 +570,7 @@ static void mfm_rw_intr(void) DBG("mfm_rw_intr: returned from cont->done\n"); } else { /* Its going to generate another interrupt */ - SET_INTR(mfm_rw_intr); + DEVICE_INTR = mfm_rw_intr; }; } @@ -578,7 +578,7 @@ static void mfm_setup_rw(void) { DBG("setting up for rw...\n"); - SET_INTR(mfm_rw_intr); + DEVICE_INTR = mfm_rw_intr; issue_command(raw_cmd.cmdcode, raw_cmd.cmddata, raw_cmd.cmdlen); } @@ -608,7 +608,7 @@ static void mfm_recal_intr(void) /* Command end without seek end (see data sheet p.20) for parallel seek - we have to send a POL command to wait for the seek */ if (mfm_status & STAT_CED) { - SET_INTR(mfm_recal_intr); + DEVICE_INTR = mfm_recal_intr; issue_command(CMD_POL, NULL, 0); return; } @@ -638,7 +638,7 @@ static void mfm_seek_intr(void) return; } if (mfm_status & STAT_CED) { - SET_INTR(mfm_seek_intr); + DEVICE_INTR = mfm_seek_intr; issue_command(CMD_POL, NULL, 0); return; } @@ -696,7 +696,7 @@ static void mfm_seek(void) DBG("seeking...\n"); if (MFM_DRV_INFO.cylinder < 0) { - SET_INTR(mfm_recal_intr); + DEVICE_INTR = mfm_recal_intr; DBG("mfm_seek: about to call specify\n"); mfm_specify (); /* DAG added this */ @@ -712,7 +712,7 @@ static void mfm_seek(void) cmdb[2] = raw_cmd.cylinder >> 8; cmdb[3] = raw_cmd.cylinder; - SET_INTR(mfm_seek_intr); + DEVICE_INTR = mfm_seek_intr; issue_command(CMD_SEK, cmdb, 4); } else mfm_setup_rw(); @@ -907,7 +907,7 @@ static void mfm_request(void) if (blk_queue_empty(QUEUE)) { printk("mfm_request: Exiting due to empty queue (pre)\n"); - CLEAR_INTR; + DEVICE_INTR = NULL; Busy = 0; return; } @@ -971,7 +971,7 @@ static void mfm_interrupt_handler(int unused, void *dev_id, struct pt_regs *regs { void (*handler) (void) = DEVICE_INTR; - CLEAR_INTR; + DEVICE_INTR = NULL; DBG("mfm_interrupt_handler (handler=0x%p)\n", handler); diff --git a/drivers/block/acsi.c b/drivers/block/acsi.c index 4ea1c91e0dcf..c54a1effd933 100644 --- a/drivers/block/acsi.c +++ b/drivers/block/acsi.c @@ -1041,7 +1041,7 @@ static void redo_acsi_request( void ) } CurrentBuffer = buffer; CurrentNSect = nsect; - + if (CURRENT->cmd == WRITE) { CMDSET_TARG_LUN( write_cmd, target, lun ); CMDSET_BLOCK( write_cmd, block ); @@ -1049,7 +1049,7 @@ static void redo_acsi_request( void ) if (buffer == acsi_buffer) copy_to_acsibuffer(); dma_cache_maintenance( pbuffer, nsect*512, 1 ); - SET_INTR(write_intr); + DEVICE_INTR = write_intr; if (!acsicmd_dma( write_cmd, buffer, nsect, 1, 1)) { CLEAR_INTR; printk( KERN_ERR "ACSI (write): Timeout in command block\n" ); @@ -1063,7 +1063,7 @@ static void redo_acsi_request( void ) CMDSET_TARG_LUN( read_cmd, target, lun ); CMDSET_BLOCK( read_cmd, block ); CMDSET_LEN( read_cmd, nsect ); - SET_INTR(read_intr); + DEVICE_INTR = read_intr; if (!acsicmd_dma( read_cmd, buffer, nsect, 0, 1)) { CLEAR_INTR; printk( KERN_ERR "ACSI (read): Timeout in command block\n" ); diff --git a/drivers/block/floppy.c b/drivers/block/floppy.c index a746c87e9e20..68bccecdd995 100644 --- a/drivers/block/floppy.c +++ b/drivers/block/floppy.c @@ -633,6 +633,8 @@ static void is_alive(const char *message) } #endif +static void (*do_floppy)(void) = NULL; + #ifdef FLOPPY_SANITY_CHECK #define OLOGSIZE 20 @@ -920,9 +922,9 @@ static inline void unlock_fdc(void) if (!fdc_busy) DPRINT("FDC access conflict!\n"); - if (DEVICE_INTR) + if (do_floppy) DPRINT("device interrupt still active at FDC release: %p!\n", - DEVICE_INTR); + do_floppy); command_status = FD_COMMAND_NONE; del_timer(&fd_timeout); cont = NULL; @@ -1005,7 +1007,7 @@ static struct timer_list fd_timer; static void cancel_activity(void) { - CLEAR_INTR; + do_floppy = NULL; floppy_tq.routine = (void *)(void *) empty; del_timer(&fd_timer); } @@ -1524,7 +1526,7 @@ static void setup_rw_floppy(void) setup_DMA(); if (flags & FD_RAW_INTR) - SET_INTR(main_command_interrupt); + do_floppy = main_command_interrupt; r=0; for (i=0; i< raw_cmd->cmd_count; i++) @@ -1656,7 +1658,7 @@ static void seek_floppy(void) } } - SET_INTR(seek_interrupt); + do_floppy = seek_interrupt; output_byte(FD_SEEK); output_byte(UNIT(current_drive)); LAST_OUT(track); @@ -1736,7 +1738,7 @@ static void print_result(char *message, int inr) /* interrupt handler. Note that this can be called externally on the Sparc */ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) { - void (*handler)(void) = DEVICE_INTR; + void (*handler)(void) = do_floppy; int do_print; unsigned long f; @@ -1746,9 +1748,9 @@ void floppy_interrupt(int irq, void *dev_id, struct pt_regs * regs) f=claim_dma_lock(); fd_disable_dma(); release_dma_lock(f); - + floppy_enable_hlt(); - CLEAR_INTR; + do_floppy = NULL; if (fdc >= N_FDC || FDCS->address == -1){ /* we don't even know which FDC is the culprit */ printk("DOR0=%x\n", fdc_state[0].dor); @@ -1795,7 +1797,7 @@ static void recalibrate_floppy(void) #ifdef DEBUGT debugt("recalibrate floppy:"); #endif - SET_INTR(recal_interrupt); + do_floppy = recal_interrupt; output_byte(FD_RECALIBRATE); LAST_OUT(UNIT(current_drive)); } @@ -1823,14 +1825,14 @@ static void reset_interrupt(void) static void reset_fdc(void) { unsigned long flags; - - SET_INTR(reset_interrupt); + + do_floppy = reset_interrupt; FDCS->reset = 0; reset_fdc_info(0); /* Pseudo-DMA may intercept 'reset finished' interrupt. */ /* Irrelevant for systems with true DMA (i386). */ - + flags=claim_dma_lock(); fd_disable_dma(); release_dma_lock(flags); @@ -1873,8 +1875,8 @@ static void show_floppy(void) printk("status=%x\n", fd_inb(FD_STATUS)); printk("fdc_busy=%lu\n", fdc_busy); - if (DEVICE_INTR) - printk("DEVICE_INTR=%p\n", DEVICE_INTR); + if (do_floppy) + printk("do_floppy=%p\n", do_floppy); if (floppy_tq.sync) printk("floppy_tq.routine=%p\n", floppy_tq.routine); if (timer_pending(&fd_timer)) @@ -2920,7 +2922,7 @@ static void redo_fd_request(void) for (;;) { if (blk_queue_empty(QUEUE)) { - CLEAR_INTR; + do_floppy = NULL; unlock_fdc(); return; } diff --git a/drivers/cdrom/Config.help b/drivers/cdrom/Config.help index 1dee585b6433..92e333a3a6fd 100644 --- a/drivers/cdrom/Config.help +++ b/drivers/cdrom/Config.help @@ -106,27 +106,6 @@ CONFIG_SBPCD The module will be called sbpcd.o. If you want to compile it as a module, say M here and read . -CONFIG_SBPCD2 - Say Y here only if you have two CD-ROM controller cards of this type - (usually only if you have more than four drives). You should enter - the parameters for the second, third and fourth interface card into - before compiling the new kernel. Read - the file . - -CONFIG_SBPCD3 - Say Y here only if you have three CD-ROM controller cards of this - type (usually only if you have more than six drives). You should - enter the parameters for the second, third and fourth interface card - into before compiling the new kernel. - Read the file . - -CONFIG_SBPCD4 - Say Y here only if you have four CD-ROM controller cards of this - type (usually only if you have more than eight drives). You should - enter the parameters for the second, third and fourth interface card - into before compiling the new kernel. - Read the file . - CONFIG_AZTCD This is your driver if you have an Aztech CDA268-01A, Orchid CD-3110, Okano or Wearnes CDD110, Conrad TXC, or CyCD-ROM CR520 or diff --git a/drivers/cdrom/Config.in b/drivers/cdrom/Config.in index 7ffbfb958d4e..c1ff66af9566 100644 --- a/drivers/cdrom/Config.in +++ b/drivers/cdrom/Config.in @@ -4,15 +4,6 @@ tristate ' Aztech/Orchid/Okano/Wearnes/TXC/CyDROM CDROM support' CONFIG_AZTCD tristate ' Goldstar R420 CDROM support' CONFIG_GSCD tristate ' Matsushita/Panasonic/Creative, Longshine, TEAC CDROM support' CONFIG_SBPCD -if [ "$CONFIG_SBPCD" = "y" ]; then - bool ' Matsushita/Panasonic, ... second CDROM controller support' CONFIG_SBPCD2 - if [ "$CONFIG_SBPCD2" = "y" ]; then - bool ' Matsushita/Panasonic, ... third CDROM controller support' CONFIG_SBPCD3 - if [ "$CONFIG_SBPCD3" = "y" ]; then - bool ' Matsushita/Panasonic, ... fourth CDROM controller support' CONFIG_SBPCD4 - fi - fi -fi tristate ' Mitsumi (standard) [no XA/Multisession] CDROM support' CONFIG_MCD if [ "$CONFIG_MCD" != "n" ]; then int 'MCD IRQ' CONFIG_MCD_IRQ 11 diff --git a/drivers/cdrom/Makefile b/drivers/cdrom/Makefile index f7def1b920e9..cddac1b5f798 100644 --- a/drivers/cdrom/Makefile +++ b/drivers/cdrom/Makefile @@ -34,9 +34,6 @@ obj-$(CONFIG_MCD) += mcd.o cdrom.o obj-$(CONFIG_MCDX) += mcdx.o cdrom.o obj-$(CONFIG_OPTCD) += optcd.o obj-$(CONFIG_SBPCD) += sbpcd.o cdrom.o -obj-$(CONFIG_SBPCD2) += sbpcd2.o cdrom.o -obj-$(CONFIG_SBPCD3) += sbpcd3.o cdrom.o -obj-$(CONFIG_SBPCD4) += sbpcd4.o cdrom.o obj-$(CONFIG_SJCD) += sjcd.o obj-$(CONFIG_CDU535) += sonycd535.o diff --git a/drivers/cdrom/gscd.c b/drivers/cdrom/gscd.c index de7844eaf6d9..ae2c2be7a871 100644 --- a/drivers/cdrom/gscd.c +++ b/drivers/cdrom/gscd.c @@ -292,7 +292,7 @@ static void __do_gscd_request(unsigned long dummy) goto out; if (CURRENT->cmd != READ) { - printk("GSCD: bad cmd %d\n", CURRENT->cmd); + printk("GSCD: bad cmd %p\n", CURRENT->cmd); end_request(0); goto repeat; } diff --git a/drivers/cdrom/sbpcd.c b/drivers/cdrom/sbpcd.c index 360d98d5203c..3299b6103324 100644 --- a/drivers/cdrom/sbpcd.c +++ b/drivers/cdrom/sbpcd.c @@ -1,5 +1,3 @@ - - /* * sbpcd.c CD-ROM device driver for the whole family of traditional, * non-ATAPI IDE-style Matsushita/Panasonic CR-5xx drives. @@ -341,16 +339,20 @@ /* * Trying to merge requests breaks this driver horribly (as in it goes - * boom and apparently has done so since 2.3.41). As it is a legacy - * driver for a horribly slow double speed CD on a hideous interface - * designed for polled operation, I won't loose any sleep in simply + * boom and apparently has done so since 2.3.41). As it is a legacy + * driver for a horribly slow double speed CD on a hideous interface + * designed for polled operation, I won't loose any sleep in simply * disallowing merging. Paul G. 02/2001 + * + * Thu May 30 14:14:47 CEST 2002: + * + * I have presumably found the reson for the above - there was a bogous + * end_request substitute, which was manipulating the request queues + * incorrectly. If someone has access to the actual hardware, and it's + * still operations - well please free to test it. + * + * Marcin Dalecki */ -#define DONT_MERGE_REQUESTS - -#ifndef SBPCD_ISSUE -#define SBPCD_ISSUE 1 -#endif /* SBPCD_ISSUE */ #include @@ -364,7 +366,7 @@ #include #include #include -#include +#include #include #include #include @@ -377,50 +379,19 @@ #include #include "sbpcd.h" -#if !(SBPCD_ISSUE-1) #define MAJOR_NR MATSUSHITA_CDROM_MAJOR -#endif -#if !(SBPCD_ISSUE-2) -#define MAJOR_NR MATSUSHITA_CDROM2_MAJOR /* second driver issue */ -#endif -#if !(SBPCD_ISSUE-3) -#define MAJOR_NR MATSUSHITA_CDROM3_MAJOR /* third driver issue */ -#endif -#if !(SBPCD_ISSUE-4) -#define MAJOR_NR MATSUSHITA_CDROM4_MAJOR /* fourth driver issue */ -#endif #include -/*==========================================================================*/ -/* - * provisions for more than 1 driver issues - * currently up to 4 drivers, expandable - */ -#if !(SBPCD_ISSUE-1) -#define DO_SBPCD_REQUEST(a) do_sbpcd_request(a) -#define SBPCD_INIT(a) sbpcd_init(a) -#endif -#if !(SBPCD_ISSUE-2) -#define DO_SBPCD_REQUEST(a) do_sbpcd2_request(a) -#define SBPCD_INIT(a) sbpcd2_init(a) -#endif -#if !(SBPCD_ISSUE-3) -#define DO_SBPCD_REQUEST(a) do_sbpcd3_request(a) -#define SBPCD_INIT(a) sbpcd3_init(a) -#endif -#if !(SBPCD_ISSUE-4) -#define DO_SBPCD_REQUEST(a) do_sbpcd4_request(a) -#define SBPCD_INIT(a) sbpcd4_init(a) -#endif /*==========================================================================*/ #if SBPCD_DIS_IRQ -#define SBPCD_CLI cli() -#define SBPCD_STI sti() +# define SBPCD_CLI cli() +# define SBPCD_STI sti() #else -#define SBPCD_CLI -#define SBPCD_STI -#endif /* SBPCD_DIS_IRQ */ +# define SBPCD_CLI +# define SBPCD_STI +#endif + /*==========================================================================*/ /* * auto-probing address list @@ -438,8 +409,7 @@ * send mail to emoenke@gwdg.de if your interface card is not FULLY * represented here. */ -#if !(SBPCD_ISSUE-1) -static int sbpcd[] = +static int sbpcd[] = { CDROM_PORT, SBPRO, /* probe with user's setup first */ #if DISTRIBUTION @@ -482,30 +452,17 @@ static int sbpcd[] = #endif #endif /* DISTRIBUTION */ }; -#else -static int sbpcd[] = {CDROM_PORT, SBPRO}; /* probe with user's setup only */ -#endif + +/* + * Protects access to global structures etc. + */ +static spinlock_t sbpcd_lock __cacheline_aligned = SPIN_LOCK_UNLOCKED; + MODULE_PARM(sbpcd, "2i"); MODULE_PARM(max_drives, "i"); #define NUM_PROBE (sizeof(sbpcd) / sizeof(int)) -/*==========================================================================*/ -/* - * the external references: - */ -#if !(SBPCD_ISSUE-1) -#ifdef CONFIG_SBPCD2 -extern int sbpcd2_init(void); -#endif -#ifdef CONFIG_SBPCD3 -extern int sbpcd3_init(void); -#endif -#ifdef CONFIG_SBPCD4 -extern int sbpcd4_init(void); -#endif -#endif - /*==========================================================================*/ #define INLINE inline @@ -604,19 +561,7 @@ static const char *str_lm = "LaserMate"; static const char *str_sp = "SPEA"; static const char *str_t16 = "Teac16bit"; static const char *type; - -#if !(SBPCD_ISSUE-1) static const char *major_name="sbpcd"; -#endif -#if !(SBPCD_ISSUE-2) -static const char *major_name="sbpcd2"; -#endif -#if !(SBPCD_ISSUE-3) -static const char *major_name="sbpcd3"; -#endif -#if !(SBPCD_ISSUE-4) -static const char *major_name="sbpcd4"; -#endif /*==========================================================================*/ @@ -4879,15 +4824,12 @@ static void sbp_transfer(struct request *req) * */ #undef DEBUG_GTL -static inline void sbpcd_end_request(struct request *req, int uptodate) { - list_add(&req->queue, &req->q->queue_head); - end_request(uptodate); -} + /*==========================================================================*/ /* * I/O request routine, called from Linux kernel. */ -static void DO_SBPCD_REQUEST(request_queue_t * q) +static void do_sbpcd_request(request_queue_t * q) { u_int block; u_int nsect; @@ -4921,11 +4863,11 @@ static void DO_SBPCD_REQUEST(request_queue_t * q) return; } - req=CURRENT; /* take out our request so no other */ + req = CURRENT; /* take out our request so no other */ blkdev_dequeue_request(req); /* task can fuck it up GTL */ if (req -> sector == -1) - sbpcd_end_request(req, 0); + end_request(0); spin_unlock_irq(q->queue_lock); down(&ioctl_read_sem); @@ -4967,7 +4909,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q) #endif up(&ioctl_read_sem); spin_lock_irq(q->queue_lock); - sbpcd_end_request(req, 1); + end_request(1); goto request_loop; } @@ -5008,7 +4950,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q) #endif up(&ioctl_read_sem); spin_lock_irq(q->queue_lock); - sbpcd_end_request(req, 1); + end_request(1); goto request_loop; } } @@ -5024,7 +4966,7 @@ static void DO_SBPCD_REQUEST(request_queue_t * q) up(&ioctl_read_sem); sbp_sleep(0); /* wait a bit, try again */ spin_lock_irq(q->queue_lock); - sbpcd_end_request(req, 0); + end_request(0); goto request_loop; } /*==========================================================================*/ @@ -5469,7 +5411,7 @@ static int sbpcd_open(struct cdrom_device_info *cdi, int purpose) static void sbpcd_release(struct cdrom_device_info * cdi) { int i; - + i = minor(cdi->dev); if ((i<0) || (i>=NR_SBPCD) || (D_S[i].drv_id==-1)) { @@ -5488,7 +5430,6 @@ static void sbpcd_release(struct cdrom_device_info * cdi) if (--D_S[d].open_count<=0) { D_S[d].sbp_first_frame=D_S[d].sbp_last_frame=-1; - invalidate_buffers(cdi->dev); if (D_S[d].audio_state!=audio_playing) if (D_S[d].f_eject) cc_SpinDown(); D_S[d].diskstate_flags &= ~cd_size_bit; @@ -5559,11 +5500,7 @@ static struct cdrom_device_info sbpcd_info = { * */ -#if (SBPCD_ISSUE-1) -static int sbpcd_setup(char *s) -#else int sbpcd_setup(char *s) -#endif { #ifndef MODULE int p[4]; @@ -5680,20 +5617,6 @@ static int __init config_spea(void) return (0); } -#ifdef DONT_MERGE_REQUESTS -static int dont_merge_requests_fn(request_queue_t *q, struct request *req, - struct request *next, int max_segments) -{ - return 0; -} - -static int dont_bh_merge_fn(request_queue_t *q, struct request *req, - struct buffer_head *bh, int max_segments) -{ - return 0; -} -#endif - /*==========================================================================*/ /* * Test for presence of drive and initialize it. @@ -5703,10 +5626,10 @@ static int dont_bh_merge_fn(request_queue_t *q, struct request *req, static devfs_handle_t devfs_handle; #ifdef MODULE -int __init __SBPCD_INIT(void) +int __init __sbpcd_init(void) #else -int __init SBPCD_INIT(void) -#endif /* MODULE */ +int __init sbpcd_init(void) +#endif { char nbuff[16]; int i=0, j=0; @@ -5841,7 +5764,7 @@ int __init SBPCD_INIT(void) i=SetSpeed(); if (i>=0) D_S[j].CD_changed=1; } - + /* * Turn on the CD audio channels. * The addresses are obtained from SOUND_BASE (see sbpcd.h). @@ -5849,8 +5772,8 @@ int __init SBPCD_INIT(void) #if SOUND_BASE OUT(MIXER_addr,MIXER_CD_Volume); /* select SB Pro mixer register */ OUT(MIXER_data,0xCC); /* one nibble per channel, max. value: 0xFF */ -#endif /* SOUND_BASE */ - +#endif /* SOUND_BASE */ + if (devfs_register_blkdev(MAJOR_NR, major_name, &sbpcd_bdops) != 0) { msg(DBG_INF, "Can't get MAJOR %d for Matsushita CDROM\n", MAJOR_NR); @@ -5860,16 +5783,10 @@ int __init SBPCD_INIT(void) goto init_done; #endif /* MODULE */ } - blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), DO_SBPCD_REQUEST, &sbpcd_lock); -#ifdef DONT_MERGE_REQUESTS - (BLK_DEFAULT_QUEUE(MAJOR_NR))->back_merge_fn = dont_bh_merge_fn; - (BLK_DEFAULT_QUEUE(MAJOR_NR))->front_merge_fn = dont_bh_merge_fn; - (BLK_DEFAULT_QUEUE(MAJOR_NR))->merge_requests_fn = dont_merge_requests_fn; -#endif - read_ahead[MAJOR_NR] = buffers * (CD_FRAMESIZE / 512); - + blk_init_queue(BLK_DEFAULT_QUEUE(MAJOR_NR), do_sbpcd_request, &sbpcd_lock); + request_region(CDo_command,4,major_name); - + devfs_handle = devfs_mk_dir (NULL, "sbp", NULL); for (j=0;jdev = MKDEV(MAJOR_NR, j); + sbpcd_infop->dev = mk_kdev(MAJOR_NR, j); strncpy(sbpcd_infop->name,major_name, sizeof(sbpcd_infop->name)); - sprintf (nbuff, "c%dt%d/cd", SBPCD_ISSUE - 1, D_S[j].drv_id); + sprintf (nbuff, "c0t%d/cd", D_S[j].drv_id); sbpcd_infop->de = devfs_register (devfs_handle, nbuff, DEVFS_FL_DEFAULT, MAJOR_NR, j, S_IFBLK | S_IRUGO | S_IWUGO, &sbpcd_bdops, NULL); if (register_cdrom(sbpcd_infop)) { - printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); + printk(" sbpcd: Unable to register with Uniform CD-ROm driver\n"); } } blk_queue_hardsect_size(BLK_DEFAULT_QUEUE(MAJOR_NR), CD_FRAMESIZE); #ifndef MODULE init_done: -#if !(SBPCD_ISSUE-1) -#ifdef CONFIG_SBPCD2 - sbpcd2_init(); -#endif /* CONFIG_SBPCD2 */ -#ifdef CONFIG_SBPCD3 - sbpcd3_init(); -#endif /* CONFIG_SBPCD3 */ -#ifdef CONFIG_SBPCD4 - sbpcd4_init(); -#endif /* CONFIG_SBPCD4 */ -#endif /* !(SBPCD_ISSUE-1) */ -#endif /* MODULE */ +#endif return 0; } /*==========================================================================*/ @@ -5978,14 +5884,11 @@ void sbpcd_exit(void) msg(DBG_INF, "%s module released.\n", major_name); } - -#ifdef MODULE -module_init(__SBPCD_INIT) /*HACK!*/; -#endif +module_init(__sbpcd_init) /*HACK!*/; module_exit(sbpcd_exit); -#endif /* MODULE */ +#endif /* MODULE */ /*==========================================================================*/ /* * Check if the media has changed in the CD-ROM drive. @@ -6003,7 +5906,7 @@ static int sbpcd_chk_disk_change(kdev_t full_dev) D_S[i].CD_changed=0; msg(DBG_CHK,"medium changed (drive %d)\n", i); /* BUG! Should invalidate buffers! --AJK */ - invalidate_buffers(full_dev); + /* Why should it do the above at all?! --mdcki */ D_S[d].diskstate_flags &= ~toc_bit; D_S[d].diskstate_flags &= ~cd_size_bit; #if SAFE_MIXED diff --git a/drivers/cdrom/sbpcd.h b/drivers/cdrom/sbpcd.h index 6632fa48ca80..74255554611d 100644 --- a/drivers/cdrom/sbpcd.h +++ b/drivers/cdrom/sbpcd.h @@ -74,30 +74,10 @@ * Example: #define SOUND_BASE 0x220 enables the sound card's CD channels * #define SOUND_BASE 0 leaves the soundcard untouched */ -#if !(SBPCD_ISSUE-1) /* first (or if you have only one) interface board: */ #define CDROM_PORT 0x340 /* <-----------<< port address */ #define SBPRO 0 /* <-----------<< interface type */ #define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ #define SOUND_BASE 0x220 /* <-----------<< sound address of this card or 0 */ -#endif -#if !(SBPCD_ISSUE-2) /* ==================== second interface board: === */ -#define CDROM_PORT 0x344 /* <-----------<< port address */ -#define SBPRO 0 /* <-----------<< interface type */ -#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ -#define SOUND_BASE 0x000 /* <-----------<< sound address of this card or 0 */ -#endif -#if !(SBPCD_ISSUE-3) /* ===================== third interface board: === */ -#define CDROM_PORT 0x630 /* <-----------<< port address */ -#define SBPRO 1 /* <-----------<< interface type */ -#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ -#define SOUND_BASE 0x240 /* <-----------<< sound address of this card or 0 */ -#endif -#if !(SBPCD_ISSUE-4) /* ==================== fourth interface board: === */ -#define CDROM_PORT 0x634 /* <-----------<< port address */ -#define SBPRO 0 /* <-----------<< interface type */ -#define MAX_DRIVES 4 /* set to 1 if the card does not use "drive select" */ -#define SOUND_BASE 0x000 /* <-----------<< sound address of this card or 0 */ -#endif /* * some more or less user dependent definitions - service them! diff --git a/drivers/cdrom/sbpcd2.c b/drivers/cdrom/sbpcd2.c deleted file mode 100644 index 82e2c68ed435..000000000000 --- a/drivers/cdrom/sbpcd2.c +++ /dev/null @@ -1,5 +0,0 @@ -/* - * duplication of sbpcd.c for multiple interfaces - */ -#define SBPCD_ISSUE 2 -#include "sbpcd.c" diff --git a/drivers/cdrom/sbpcd3.c b/drivers/cdrom/sbpcd3.c deleted file mode 100644 index 0e79c4155953..000000000000 --- a/drivers/cdrom/sbpcd3.c +++ /dev/null @@ -1,5 +0,0 @@ -/* - * duplication of sbpcd.c for multiple interfaces - */ -#define SBPCD_ISSUE 3 -#include "sbpcd.c" diff --git a/drivers/cdrom/sbpcd4.c b/drivers/cdrom/sbpcd4.c deleted file mode 100644 index f4b34cc293a9..000000000000 --- a/drivers/cdrom/sbpcd4.c +++ /dev/null @@ -1,5 +0,0 @@ -/* - * duplication of sbpcd.c for multiple interfaces - */ -#define SBPCD_ISSUE 4 -#include "sbpcd.c" diff --git a/drivers/cdrom/sonycd535.c b/drivers/cdrom/sonycd535.c index 545bc98ef807..bb0e7dc3c44e 100644 --- a/drivers/cdrom/sonycd535.c +++ b/drivers/cdrom/sonycd535.c @@ -118,6 +118,7 @@ #include #include #include +#include #include #include #include @@ -134,7 +135,8 @@ #include #define MAJOR_NR CDU535_CDROM_MAJOR -# include +#include + #define sony535_cd_base_io sonycd535 /* for compatible parameter passing with "insmod" */ #include "sonycd535.h" @@ -1589,7 +1591,6 @@ sony535_init(void) &cdu_fops, NULL); if (devfs_register_blkdev(MAJOR_NR, CDU535_HANDLE, &cdu_fops)) { printk("Unable to get major %d for %s\n", - devfs_unregister(sony_devfs_handle); MAJOR_NR, CDU535_MESSAGE_NAME); return -EIO; } @@ -1663,8 +1664,7 @@ sony535_init(void) devfs_unregister(sony_devfs_handle); if (sony535_irq_used) free_irq(sony535_irq_used, NULL); - } - + return -EIO; } register_disk(NULL, mk_kdev(MAJOR_NR,0), 1, &cdu_fops, 0); diff --git a/drivers/ide/hd.c b/drivers/ide/hd.c index 36ea5c8447b9..cafa9da8c325 100644 --- a/drivers/ide/hd.c +++ b/drivers/ide/hd.c @@ -111,20 +111,16 @@ static int hd_sizes[MAX_HD<<6]; static struct timer_list device_timer; -#define SET_TIMER \ +#define SET_TIMER \ do { \ mod_timer(&device_timer, jiffies + TIMEOUT_VALUE); \ } while (0) -#define CLEAR_TIMER del_timer(&device_timer); - -#undef SET_INTR - -#define SET_INTR(x) \ +#define SET_HANDLER(x) \ if ((DEVICE_INTR = (x)) != NULL) \ SET_TIMER; \ else \ - CLEAR_TIMER; + del_timer(&device_timer); #if (HD_DELAY > 0) @@ -280,7 +276,7 @@ static void hd_out(unsigned int drive,unsigned int nsect,unsigned int sect, reset = 1; return; } - SET_INTR(intr_addr); + SET_HANDLER(intr_addr); outb_p(hd_info[drive].ctl,HD_CMD); port=HD_DATA; outb_p(hd_info[drive].wpcom>>2,++port); @@ -430,7 +426,7 @@ ok_to_read: if (CURRENT->current_nr_sectors <= 0) end_request(1); if (i > 0) { - SET_INTR(&read_intr); + SET_HANDLER(&read_intr); return; } (void) inb_p(HD_STATUS); @@ -468,7 +464,7 @@ ok_to_write: if (!i || (CURRENT->bio && !SUBSECTOR(i))) end_request(1); if (i > 0) { - SET_INTR(&write_intr); + SET_HANDLER(&write_intr); outsw(HD_DATA,CURRENT->buffer,256); sti(); } else { diff --git a/drivers/s390/block/xpram.c b/drivers/s390/block/xpram.c index 7c85ee6565c4..b41fe8df6bd1 100644 --- a/drivers/s390/block/xpram.c +++ b/drivers/s390/block/xpram.c @@ -59,25 +59,15 @@ #include #ifdef MODULE -char kernel_version [] = UTS_RELEASE; +char kernel_version [] = UTS_RELEASE; #endif -#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,3,98)) -# define XPRAM_VERSION 24 -#else -# define XPRAM_VERSION 22 -#endif - -#if (XPRAM_VERSION == 24) -# include -# include -#endif /* V24 */ +#include +#include #include #include /* printk() */ #include /* kmalloc() */ -#if (XPRAM_VERSION == 24) -# include -#endif /* V24 */ +#include #include /* everything... */ #include /* error codes */ #include @@ -89,7 +79,6 @@ char kernel_version [] = UTS_RELEASE; #include /* cli(), *_flags */ #include /* put_user */ -#if (XPRAM_VERSION == 24) #define MAJOR_NR xpram_major /* force definitions on in blk.h */ int xpram_major; /* must be declared before including blk.h */ devfs_handle_t xpram_devfs_handle; @@ -105,7 +94,6 @@ devfs_handle_t xpram_devfs_handle; #include "xpram.h" /* local definitions */ __setup("xpram_parts=", xpram_setup); -#endif /* V24 */ /* define the debug levels: @@ -133,26 +121,7 @@ __setup("xpram_parts=", xpram_setup); #define PRINT_WARN(x...) printk ( KERN_DEBUG PRINTK_HEADER "warning:" x ) #define PRINT_ERR(x...) printk ( KERN_DEBUG PRINTK_HEADER "error:" x ) #define PRINT_FATAL(x...) printk ( KERN_DEBUG PRINTK_HEADER "panic:" x ) -#endif - -#if (XPRAM_VERSION == 22) -#define MAJOR_NR xpram_major /* force definitions on in blk.h */ -int xpram_major; /* must be declared before including blk.h */ - -#define DEVICE_NR(device) MINOR(device) /* xpram has no partition bits */ -#define DEVICE_NAME "xpram" /* name for messaging */ -#define DEVICE_INTR xpram_intrptr /* pointer to the bottom half */ -#define DEVICE_NO_RANDOM /* no entropy to contribute */ - - -#define DEVICE_OFF(d) /* do-nothing */ - -#define DEVICE_REQUEST *xpram_dummy_device_request /* dummy function variable - * to prevent warnings - */#include - -#include "xpram.h" /* local definitions */ -#endif /* V22 */ +#endif /* * Non-prefixed symbols are static. They are meant to be assigned at @@ -659,13 +628,6 @@ int xpram_ioctl (struct inode *inode, struct file *filp, case BLKRRPART: /* re-read partition table: can't do it, 0x1259 */ return -EINVAL; -#if (XPRAM_VERSION == 22) - RO_IOCTLS(inode->i_rdev, arg); /* the default RO operations - * BLKROSET - * BLKROGET - */ -#endif /* V22 */ - case HDIO_GETGEO: /* * get geometry: we have to fake one... trim the size to a @@ -695,27 +657,6 @@ int xpram_ioctl (struct inode *inode, struct file *filp, /* * The file operations */ - -#if (XPRAM_VERSION == 22) -struct file_operations xpram_fops = { - NULL, /* lseek: default */ - block_read, - block_write, - NULL, /* xpram_readdir */ - NULL, /* xpram_select */ - xpram_ioctl, - NULL, /* xpram_mmap */ - xpram_open, - NULL, /* flush */ - xpram_release, - block_fsync, - NULL, /* xpram_fasync */ - NULL, - NULL -}; -#endif /* V22 */ - -#if (XPRAM_VERSION == 24) struct block_device_operations xpram_devops = { owner: THIS_MODULE, @@ -723,7 +664,6 @@ struct block_device_operations xpram_devops = open: xpram_open, release: xpram_release, }; -#endif /* V24 */ /* * Block-driver specific functions @@ -740,11 +680,7 @@ void xpram_request(request_queue_t * queue) char * buffer; /* local pointer into buffer cache */ int dev_no; /* device number of request */ int fault; /* faulty access to expanded memory */ -#if ( XPRAM_VERSION == 24 ) struct request * current_req; /* working request */ -#else -# define current_req CURRENT -#endif /* V24 */ while(1) { if (blk_queue_empty(QUEUE)) { @@ -753,10 +689,8 @@ void xpram_request(request_queue_t * queue) } fault=0; -#if ( XPRAM_VERSION == 24 ) current_req = CURRENT; -#endif /* V24 */ - dev_no = DEVICE_NR(current_req->rq_dev); + dev_no = DEVICE_NR(current_req->rq_dev); /* Check if the minor number is in range */ if ( dev_no > xpram_devs ) { static int count = 0; @@ -872,26 +806,18 @@ void xpram_request(request_queue_t * queue) * partition size (if provided). A parsing error of a value * results in this value being set to -EINVAL. */ -#if (XPRAM_VERSION == 22) -void xpram_setup (char *str, int *ints) -#else int xpram_setup (char *str) -#endif /* V22 */ { devs = xpram_read_int(&str); - if ( devs != -EINVAL ) - if ( xpram_read_size_list_tail(&str,devs,sizes) < 0 ) { + if ( devs != -EINVAL ) + if ( xpram_read_size_list_tail(&str,devs,sizes) < 0 ) { PRINT_ERR("error while reading xpram parameters.\n"); -#if (XPRAM_VERSION == 24) return -EINVAL; -#endif /* V24 */ - } -#if (XPRAM_VERSION == 24) - else return 0; - else return -EINVAL; -#elif (XPRAM_VERSION == 22) - return; -#endif /* V24/V22 */ + } + else + return 0; + else + return -EINVAL; } /* @@ -911,12 +837,10 @@ int xpram_init(void) int mem_auto_no=0; /* number of (implicit) zero parameters in sizes */ int mem_auto; /* automatically determined device size */ -#if (XPRAM_VERSION == 24) int minor_length; /* store the length of a minor (w/o '\0') */ int minor_thresh; /* threshhold for minor lenght */ request_queue_t *q; /* request queue */ -#endif /* V24 */ /* * Copy the (static) cfg variables to public prefixed ones to allow @@ -975,29 +899,23 @@ int xpram_init(void) /* * Register your major, and accept a dynamic number */ -#if (XPRAM_VERSION == 22) - result = register_blkdev(xpram_major, "xpram", &xpram_fops); -#elif (XPRAM_VERSION == 24) result = devfs_register_blkdev(xpram_major, "xpram", &xpram_devops); -#endif /* V22/V24 */ if (result < 0) { PRINT_ERR("Can't get major %d\n",xpram_major); PRINT_ERR("Giving up xpram\n"); return result; } -#if (XPRAM_VERSION == 24) xpram_devfs_handle = devfs_mk_dir (NULL, "slram", NULL); devfs_register_series (xpram_devfs_handle, "%u", XPRAM_MAX_DEVS, DEVFS_FL_DEFAULT, XPRAM_MAJOR, 0, S_IFBLK | S_IRUSR | S_IWUSR, &xpram_devops, NULL); -#endif /* V22/V24 */ if (xpram_major == 0) xpram_major = result; /* dynamic */ major = xpram_major; /* Use `major' later on to save typing */ result = -ENOMEM; /* for the possible errors */ - /* + /* * measure expanded memory */ @@ -1018,13 +936,9 @@ int xpram_init(void) * arrays if it uses the default values. */ -#if (XPRAM_VERSION == 22) - blk_dev[major].request_fn = xpram_request; -#elif (XPRAM_VERSION == 24) - q = BLK_DEFAULT_QUEUE (major); + q = BLK_DEFAULT_QUEUE(major); blk_init_queue (q, xpram_request); blk_queue_hardsect_size(q, xpram_hardsect); -#endif /* V22/V24 */ /* we want to have XPRAM_UNUSED blocks security buffer between devices */ mem_usable=xpram_mem_avail-(XPRAM_UNUSED*(xpram_devs-1)); @@ -1076,15 +990,12 @@ int xpram_init(void) goto fail_malloc_devices; } memset(xpram_devices, 0, xpram_devs * sizeof (Xpram_Dev)); -#if (XPRAM_VERSION == 24) minor_length = 1; minor_thresh = 10; -#endif /* V24 */ for (i=0; i < xpram_devs; i++) { /* data and usage remain zeroed */ xpram_devices[i].size = xpram_sizes[i]; /* size in kB not in bytes */ atomic_set(&(xpram_devices[i].usage),0); -#if (XPRAM_VERSION == 24) if (i == minor_thresh) { minor_length++; minor_thresh *= 10; @@ -1119,27 +1030,20 @@ int xpram_init(void) goto fail_devfs_register; } #endif /* WHY? */ -#endif /* V24 */ - } return 0; /* succeed */ /* clean up memory in case of failures */ -#if (XPRAM_VERSION == 24) fail_devfs_register: for (i=0; i < xpram_devs; i++) { if ( xpram_devices[i].device_name ) kfree(xpram_devices[i].device_name); } kfree(xpram_devices); -#endif /* V24 */ kfree (xpram_offsets); fail_malloc_devices: fail_malloc: -#if (XPRAM_VERSION == 22) - blk_dev[major].request_fn = NULL; -#endif /* V22 */ /* ??? unregister_chrdev(major, "xpram"); */ unregister_blkdev(major, "xpram"); return result; @@ -1168,20 +1072,12 @@ void cleanup_module(void) int i; /* first of all, reset all the data structures */ - -#if (XPRAM_VERSION == 22) - blk_dev[major].request_fn = NULL; -#endif /* V22 */ kfree(xpram_offsets); blk_clear(major); /* finally, the usual cleanup */ -#if (XPRAM_VERSION == 22) - unregister_blkdev(major, "xpram"); -#elif (XPRAM_VERSION == 24) devfs_unregister(xpram_devfs_handle); if (devfs_unregister_blkdev(MAJOR_NR, "xpram")) printk(KERN_WARNING "xpram: cannot unregister blkdev\n"); -#endif /* V22/V24 */ kfree(xpram_devices); } diff --git a/include/linux/blk.h b/include/linux/blk.h index 8126a0cc27fd..de2f1acc9071 100644 --- a/include/linux/blk.h +++ b/include/linux/blk.h @@ -125,7 +125,6 @@ extern inline struct request *elv_next_request(request_queue_t *q) static void floppy_off(unsigned int nr); #define DEVICE_NAME "floppy" -#define DEVICE_INTR do_floppy #define DEVICE_NR(device) ( (minor(device) & 3) | ((minor(device) & 0x80 ) >> 5 )) #elif (MAJOR_NR == HD_MAJOR) @@ -149,14 +148,14 @@ static void floppy_off(unsigned int nr); #elif (MAJOR_NR == SCSI_TAPE_MAJOR) #define DEVICE_NAME "scsitape" -#define DEVICE_INTR do_st +#define DEVICE_INTR do_st #define DEVICE_NR(device) (minor(device) & 0x7f) #elif (MAJOR_NR == OSST_MAJOR) -#define DEVICE_NAME "onstream" +#define DEVICE_NAME "onstream" #define DEVICE_INTR do_osst -#define DEVICE_NR(device) (minor(device) & 0x7f) +#define DEVICE_NR(device) (minor(device) & 0x7f) #elif (MAJOR_NR == SCSI_CDROM_MAJOR) @@ -187,33 +186,16 @@ static void floppy_off(unsigned int nr); #elif (MAJOR_NR == MITSUMI_CDROM_MAJOR) #define DEVICE_NAME "Mitsumi CD-ROM" -/* #define DEVICE_INTR do_mcd */ #define DEVICE_NR(device) (minor(device)) #elif (MAJOR_NR == MITSUMI_X_CDROM_MAJOR) #define DEVICE_NAME "Mitsumi CD-ROM" -/* #define DEVICE_INTR do_mcdx */ #define DEVICE_NR(device) (minor(device)) #elif (MAJOR_NR == MATSUSHITA_CDROM_MAJOR) -#define DEVICE_NAME "Matsushita CD-ROM controller #1" -#define DEVICE_NR(device) (minor(device)) - -#elif (MAJOR_NR == MATSUSHITA_CDROM2_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #2" -#define DEVICE_NR(device) (minor(device)) - -#elif (MAJOR_NR == MATSUSHITA_CDROM3_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #3" -#define DEVICE_NR(device) (minor(device)) - -#elif (MAJOR_NR == MATSUSHITA_CDROM4_MAJOR) - -#define DEVICE_NAME "Matsushita CD-ROM controller #4" +#define DEVICE_NAME "Matsushita CD-ROM controller" #define DEVICE_NR(device) (minor(device)) #elif (MAJOR_NR == AZTECH_CDROM_MAJOR) @@ -292,27 +274,23 @@ static void floppy_off(unsigned int nr); #if (MAJOR_NR != SCSI_TAPE_MAJOR) && (MAJOR_NR != OSST_MAJOR) #if !defined(IDE_DRIVER) -#ifndef CURRENT -# define CURRENT elv_next_request(&blk_dev[MAJOR_NR].request_queue) -#endif #ifndef QUEUE # define QUEUE (&blk_dev[MAJOR_NR].request_queue) #endif +#ifndef CURRENT +# define CURRENT elv_next_request(QUEUE) +#endif #ifndef DEVICE_NAME # define DEVICE_NAME "unknown" #endif #ifdef DEVICE_INTR static void (*DEVICE_INTR)(void) = NULL; -#endif - -#define SET_INTR(x) (DEVICE_INTR = (x)) - -# ifdef DEVICE_INTR -# define CLEAR_INTR SET_INTR(NULL) +# define CLEAR_INTR DEVICE_INTR = NULL # else # define CLEAR_INTR # endif + #endif /* !defined(IDE_DRIVER) */ /* -- cgit v1.2.3 From 866559c19b5edb4166a85c41cc2a5a77846ad4f6 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 2 Jun 2002 03:43:24 -0700 Subject: Allow to be used even without NULL defined yet. --- include/linux/list.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'include') diff --git a/include/linux/list.h b/include/linux/list.h index 6331739453a0..f6ea9d2d9f25 100644 --- a/include/linux/list.h +++ b/include/linux/list.h @@ -94,8 +94,8 @@ static __inline__ void __list_del(struct list_head * prev, static __inline__ void list_del(struct list_head *entry) { __list_del(entry->prev, entry->next); - entry->next = NULL; - entry->prev = NULL; + entry->next = (void *) 0; + entry->prev = (void *) 0; } /** -- cgit v1.2.3