Commit 470d15bb authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.14 IDE 56

 - Push poll_timeout down from the hwgroup to the channel. We are resetting the
   channel and not a whole hwgroup. This way using multiple pdc202xxx cards
   should magically start to work with multiple performance and resets will no
   longer lock the system.

 - Updates for PDC4030 by Peter Denison <peterd@marshadder.uklinux.net>.

 - Make ide_raw_taskfile don't care about request buffers. They where always
   NULL.

 - Port set multi mode count over from the special setting interface to
   ide_raw_taskfile. Fix errors in the corresponding interrupt handler in one go
   as well. It turned out that this is precisely the same code as in
   task_no_data_intr, so we can nuke it altogether. And finally we have found
   some problems with the set_pio_mode() command which can fail with -EBUSY -
   this is in esp. probably *very* common during boot hdparm usage those days!
   (OK it was masked by reportig too early that it finished...  Crap Crap utter
   crap it was!!!) Right now hdparm should just be extendid to properly
   sync and retry on   -EBUSY and everything should be fine.

   And now the 1 Milion EUR question for everybody who loves to put driver
   settings in to /proc:

   How the hell could echo > /proc/ide/ide0/settings blah blah blah blah handle
   properly cases like -EIO, -EBUSY and so on??? Having the possibility o do it
   does not mean that it is a good idea to use it.

   OK. After realizing the simple fact that quite a lot of low level hardware
   manipulating ioctls may require assistance in usage from proper logic which is
   *very* unlikely to be implemented in a bash (for me preferable still ksh) I
   have made my mind up.

	/proc/ide will be nuked.

 - Execute the recalibration for error recovery on precisely the same request as
   the one which failed.

 - Remove set geometry.  It's crap by means of standard specification. Because:

   1. We rely on the existence of the identify command anyway.

   2. This command was obsoleted *before* the identify command existed as far
   as I can see.

   2. I'm able to have a look at what other ATA/ATAPI drivers in the wild do:
   They don't do it.

 - Just call tuneproc in set_pio_mode() directly - we are already behind the rq
   queue there.

 - After we have uncovered the broken logics behind the whole ioctl handling we
   now just have made ide_spin_wait_hwgroup() waiting for a proper somehow
   longer timeout before giving up. This was previously just hiding the broken
   concept of setting ioctl values through /proc/ide/ideX/settings - now it just
   really helps hdparm to not to give up too early. (It shouldn't probably play
   wreck havock on the global driver spin lock as well. I will look in to this
   later.)

 - Scrap the non necessary, to say the least, disabling of interrupts for 3,
   read it again please, 3 seconds, on the local CPU inside
   ide_spin_wait_hwgroup().  Spin lock handling needs checking there badly as I
   see now as well...

Hey apparently any "special" requests are gone. We now have only
to deal with REQ_DEVICE_ACB and REQ_DEVICE_CMD. One of them is still too
much and will be killed.
parent 537ad07f
This diff is collapsed.
......@@ -4272,16 +4272,6 @@ static void idetape_blkdev_release (struct inode *inode, struct file *filp, ide_
#endif
}
/*
* idetape_pre_reset is called before an ATAPI/ATA software reset.
*/
static void idetape_pre_reset (ide_drive_t *drive)
{
idetape_tape_t *tape = drive->driver_data;
if (tape != NULL)
set_bit (IDETAPE_IGNORE_DSC, &tape->flags);
}
/*
* Character device interface functions
*/
......@@ -6164,8 +6154,6 @@ static struct ata_operations idetape_driver = {
release: idetape_blkdev_release,
check_media_change: NULL,
revalidate: idetape_revalidate,
pre_reset: idetape_pre_reset,
capacity: NULL,
proc: idetape_proc
};
......
......@@ -488,40 +488,6 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
return ide_started;
}
/*
* This is invoked on completion of a WIN_SETMULT cmd.
*/
ide_startstop_t set_multmode_intr(struct ata_device *drive, struct request *__rq)
{
u8 stat;
if (OK_STAT(stat = GET_STAT(),READY_STAT,BAD_STAT)) {
drive->mult_count = drive->mult_req;
} else {
drive->mult_req = drive->mult_count = 0;
drive->special_cmd |= ATA_SPECIAL_RECALIBRATE;
ide_dump_status(drive, "set_multmode", stat);
}
return ide_stopped;
}
/*
* This is invoked on completion of a WIN_SPECIFY cmd.
*/
ide_startstop_t set_geometry_intr(struct ata_device *drive, struct request *__rq)
{
u8 stat;
if (OK_STAT(stat=GET_STAT(),READY_STAT,BAD_STAT))
return ide_stopped;
if (stat & (ERR_STAT|DRQ_STAT))
return ide_error(drive, "set_geometry_intr", stat);
ide_set_handler(drive, set_geometry_intr, WAIT_CMD, NULL);
return ide_started;
}
/*
* This is invoked on completion of a WIN_RESTORE (recalibrate) cmd.
*/
......@@ -729,11 +695,11 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
args->command_type = IDE_DRIVE_TASK_IN;
return;
case CFA_WRITE_SECT_WO_ERASE:
case WIN_WRITE:
case WIN_WRITE_EXT:
case WIN_WRITE_VERIFY:
case WIN_WRITE_BUFFER:
case CFA_WRITE_SECT_WO_ERASE:
case WIN_DOWNLOAD_MICROCODE:
args->prehandler = pre_task_out_intr;
args->handler = task_out_intr;
......@@ -832,7 +798,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
}
case WIN_SPECIFY:
args->handler = set_geometry_intr;
args->handler = task_no_data_intr;
args->command_type = IDE_DRIVE_TASK_NO_DATA;
return;
......@@ -874,7 +840,7 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
return;
case WIN_SETMULT:
args->handler = set_multmode_intr;
args->handler = task_no_data_intr;
args->command_type = IDE_DRIVE_TASK_NO_DATA;
return;
......@@ -894,19 +860,19 @@ void ide_cmd_type_parser(struct ata_taskfile *args)
}
}
int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args, byte *buf)
int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *args)
{
struct request rq;
memset(&rq, 0, sizeof(rq));
rq.flags = REQ_DRIVE_ACB;
rq.buffer = buf;
#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);
......@@ -996,8 +962,6 @@ EXPORT_SYMBOL(atapi_read);
EXPORT_SYMBOL(atapi_write);
EXPORT_SYMBOL(ata_taskfile);
EXPORT_SYMBOL(recal_intr);
EXPORT_SYMBOL(set_geometry_intr);
EXPORT_SYMBOL(set_multmode_intr);
EXPORT_SYMBOL(task_no_data_intr);
EXPORT_SYMBOL(ide_raw_taskfile);
EXPORT_SYMBOL(ide_cmd_type_parser);
......
This diff is collapsed.
......@@ -39,6 +39,7 @@
* Version 0.90 Transition to BETA code. No lost/unexpected interrupts
* Version 0.91 Bring in line with new bio code in 2.5.1
* Version 0.92 Update for IDE driver taskfile changes
* Version 0.93 Sync with 2.5.10, minor taskfile changes
*/
/*
......@@ -380,6 +381,7 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques
}
/*
* promise_complete_pollfunc()
* This is the polling function for waiting (nicely!) until drive stops
* being busy. It is invoked at the end of a write, after the previous poll
* has finished.
......@@ -388,20 +390,20 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques
*/
static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struct request *rq)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct ata_channel *ch = drive->channel;
if (GET_STAT() & BUSY_STAT) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
return ide_started; /* continue polling... */
}
hwgroup->poll_timeout = 0;
ch->poll_timeout = 0;
printk(KERN_ERR "%s: completion timeout - still busy!\n",
drive->name);
return ide_error(drive, "busy timeout", GET_STAT());
}
hwgroup->poll_timeout = 0;
ch->poll_timeout = 0;
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
#endif
......@@ -432,7 +434,7 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int
nsect = mcount;
mcount -= nsect;
buffer = bio_kmap_irq(rq->bio, flags) + ide_rq_offset(rq);
buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
rq->sector += nsect;
rq->nr_sectors -= nsect;
rq->current_nr_sectors -= nsect;
......@@ -467,23 +469,23 @@ int promise_multwrite(struct ata_device *drive, struct request *rq, unsigned int
*/
static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct request *rq)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct ata_channel *ch = drive->channel;
if (IN_BYTE(IDE_NSECTOR_REG) != 0) {
if (time_before(jiffies, hwgroup->poll_timeout)) {
if (time_before(jiffies, ch->poll_timeout)) {
ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
return ide_started; /* continue polling... */
}
hwgroup->poll_timeout = 0;
ch->poll_timeout = 0;
printk(KERN_ERR "%s: write timed-out!\n",drive->name);
return ide_error (drive, "write timeout", GET_STAT());
return ide_error(drive, "write timeout", GET_STAT());
}
/*
* Now write out last 4 sectors and poll for not BUSY
*/
promise_multwrite(drive, rq, 4);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Done last 4 sectors - status = %02x\n",
......@@ -501,7 +503,7 @@ static ide_startstop_t promise_write_pollfunc(struct ata_device *drive, struct r
*/
static ide_startstop_t promise_write(struct ata_device *drive, struct request *rq)
{
ide_hwgroup_t *hwgroup = HWGROUP(drive);
struct ata_channel *ch = drive->channel;
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: sectors(%ld-%ld), "
......@@ -516,7 +518,7 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r
if (rq->nr_sectors > 4) {
if (promise_multwrite(drive, rq, rq->nr_sectors - 4))
return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_write_pollfunc, HZ/100, NULL);
return ide_started;
} else {
......@@ -526,7 +528,7 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r
*/
if (promise_multwrite(drive, rq, rq->nr_sectors))
return ide_stopped;
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
ch->poll_timeout = jiffies + WAIT_WORSTCASE;
ide_set_handler(drive, promise_complete_pollfunc, HZ/100, NULL);
#ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: promise_write: <= 4 sectors, "
......@@ -537,13 +539,13 @@ static ide_startstop_t promise_write(struct ata_device *drive, struct request *r
}
/*
* do_pdc4030_io() is called from do_rw_disk, having had the block number
* already set up. It issues a READ or WRITE command to the Promise
* do_pdc4030_io() is called from promise_do_request, having had the block
* number already set up. It issues a READ or WRITE command to the Promise
* controller, assuming LBA has been used to set up the block number.
*/
ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *task, struct request *rq)
ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *args, struct request *rq)
{
struct hd_drive_task_hdr *taskfile = &task->taskfile;
struct hd_drive_task_hdr *taskfile = &(args->taskfile);
unsigned long timeout;
byte stat;
......@@ -628,7 +630,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *tas
}
}
ide_startstop_t promise_rw_disk(struct ata_device *drive, struct request *rq, sector_t block)
ide_startstop_t promise_do_request(struct ata_device *drive, struct request *rq, sector_t block)
{
struct ata_taskfile args;
......@@ -647,12 +649,12 @@ ide_startstop_t promise_rw_disk(struct ata_device *drive, struct request *rq, se
args.taskfile.device_head = ((block>>8)&0x0f)|drive->select.all;
args.taskfile.command = (rq_data_dir(rq)==READ)?PROMISE_READ:PROMISE_WRITE;
ide_cmd_type_parser(&args);
/* We don't use the generic inerrupt handlers here? */
args.prehandler = NULL;
/* 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;
return do_pdc4030_io(drive, &args, rq);
}
......@@ -418,7 +418,7 @@ static int check_autopoll(struct ata_device *drive)
* pass NOP with sub-code 0x01 to device, so the command will not
* fail there
*/
ide_raw_taskfile(drive, &args, NULL);
ide_raw_taskfile(drive, &args);
if (args.taskfile.feature & ABRT_ERR)
return 1;
......@@ -448,7 +448,7 @@ static int configure_tcq(struct ata_device *drive)
args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args, NULL)) {
if (ide_raw_taskfile(drive, &args)) {
printk("%s: failed to enable write cache\n", drive->name);
return 1;
}
......@@ -462,7 +462,7 @@ static int configure_tcq(struct ata_device *drive)
args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args, NULL)) {
if (ide_raw_taskfile(drive, &args)) {
printk("%s: disabling release interrupt fail\n", drive->name);
return 1;
}
......@@ -476,7 +476,7 @@ static int configure_tcq(struct ata_device *drive)
args.taskfile.command = WIN_SETFEATURES;
ide_cmd_type_parser(&args);
if (ide_raw_taskfile(drive, &args, NULL)) {
if (ide_raw_taskfile(drive, &args)) {
printk("%s: enabling service interrupt fail\n", drive->name);
return 1;
}
......
......@@ -47,7 +47,7 @@
# define DISK_RECOVERY_TIME 0 /* for hardware that needs it */
#endif
#ifndef OK_TO_RESET_CONTROLLER /* 1 needed for good error recovery */
# define OK_TO_RESET_CONTROLLER 1 /* 0 for use with AH2372A/B interface */
# 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 */
......@@ -327,19 +327,9 @@ struct ata_device {
*/
request_queue_t queue; /* per device request queue */
unsigned long sleep; /* sleep until this time */
/* Flags requesting/indicating one of the following special commands
* executed on the request queue.
*/
#define ATA_SPECIAL_GEOMETRY 0x01
#define ATA_SPECIAL_RECALIBRATE 0x02
#define ATA_SPECIAL_MMODE 0x04
#define ATA_SPECIAL_TUNE 0x08
unsigned char special_cmd;
u8 mult_req; /* requested multiple sector setting */
u8 tune_req; /* requested drive tuning setting */
u8 XXX_tune_req; /* requested drive tuning setting */
byte using_dma; /* disk is using dma for read/write */
byte using_tcq; /* disk is using queueing */
......@@ -409,6 +399,7 @@ struct ata_device {
unsigned int failures; /* current failure count */
unsigned int max_failures; /* maximum allowed failure count */
struct device device; /* global device tree handle */
/*
* tcq statistics
*/
......@@ -517,6 +508,8 @@ struct ata_channel {
/* driver soft-power interface */
int (*busproc)(struct ata_device *, int);
byte bus_state; /* power state of the IDE bus */
unsigned long poll_timeout; /* timeout value during polled operations */
};
/*
......@@ -565,17 +558,19 @@ static inline int ata_can_queue(struct ata_device *drive)
return 1;
}
#else
#define ata_pending_commands(drive) (0)
#define ata_can_queue(drive) (1)
# define ata_pending_commands(drive) (0)
# define ata_can_queue(drive) (1)
#endif
typedef struct hwgroup_s {
/* FIXME: We should look for busy request queues instead of looking at
* the !NULL state of this field.
*/
ide_startstop_t (*handler)(struct ata_device *, struct request *); /* irq handler, if active */
unsigned long flags; /* BUSY, SLEEPING */
struct ata_device *XXX_drive; /* current drive */
struct request *rq; /* current request */
struct timer_list timer; /* failsafe timer */
unsigned long poll_timeout; /* timeout value during long polls */
int (*expiry)(struct ata_device *, struct request *); /* irq handler, if active */
} ide_hwgroup_t;
......@@ -675,9 +670,7 @@ struct ata_operations {
int (*check_media_change)(struct ata_device *);
void (*revalidate)(struct ata_device *);
void (*pre_reset)(struct ata_device *);
sector_t (*capacity)(struct ata_device *);
ide_startstop_t (*special)(struct ata_device *);
ide_proc_entry_t *proc;
};
......@@ -827,15 +820,13 @@ extern ide_startstop_t ata_taskfile(struct ata_device *,
*/
extern ide_startstop_t recal_intr(struct ata_device *, struct request *);
extern ide_startstop_t set_geometry_intr(struct ata_device *, struct request *);
extern ide_startstop_t set_multmode_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 *drive, struct ata_taskfile *cmd, byte *buf);
extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *);
extern int ide_cmd_ioctl(struct ata_device *drive, unsigned long arg);
void ide_delay_50ms(void);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment