Commit d861eb67 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] 2.5.21 IDE 87

 - Sync with 2.5.21

 - Don't call put_device inside idedisk_cleanup(). This is apparently triggering
   some bug inside the handling of device trees. Or we don't register the device
   properly within the tree. Check this later.

 - Further work on the channel register file access locking.  Push the locking
   out from __ide_end_request to ide_end_request.  Rename those functions to
   respective __ata_end_request() and ata_end_request().

 - Move ide_wait_status to device.c rename it to ata_status_poll().

 - Further work on locking scope issues.

 - devfs showed us once again that it changed the policy from agnostic numbers
   to unpleasant string names.
parent 96ba040a
...@@ -79,8 +79,30 @@ void ata_mask(struct ata_device *drive) ...@@ -79,8 +79,30 @@ void ata_mask(struct ata_device *drive)
ch->maskproc(drive); ch->maskproc(drive);
} }
/*
* Spin until the drive is no longer busy.
*
* Not exported, since it's not used within any modules.
*/
int ata_busy_poll(struct ata_device *drive, unsigned long timeout)
{
/* spec allows drive 400ns to assert "BUSY" */
udelay(1);
if (!ata_status(drive, 0, BUSY_STAT)) {
timeout += jiffies;
while (!ata_status(drive, 0, BUSY_STAT)) {
if (time_after(jiffies, timeout))
return 1;
}
}
return 0;
}
/* /*
* Check the state of the status register. * Check the state of the status register.
*
* FIXME: Channel lock should be held.
*/ */
int ata_status(struct ata_device *drive, u8 good, u8 bad) int ata_status(struct ata_device *drive, u8 good, u8 bad)
{ {
...@@ -93,6 +115,57 @@ int ata_status(struct ata_device *drive, u8 good, u8 bad) ...@@ -93,6 +115,57 @@ int ata_status(struct ata_device *drive, u8 good, u8 bad)
EXPORT_SYMBOL(ata_status); EXPORT_SYMBOL(ata_status);
/*
* 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
* returns 0. All other cases return 1 after invoking error handler -- caller
* should just return.
*
* This routine should get fixed to not hog the cpu during extra long waits..
* That could be done by busy-waiting for the first jiffy or two, and then
* setting a timer to wake up at half second intervals thereafter, until
* timeout is achieved, before timing out.
*
* FIXME: Channel lock should be held.
*/
int ata_status_poll(struct ata_device *drive, u8 good, u8 bad,
unsigned long timeout,
struct request *rq, ide_startstop_t *startstop)
{
int i;
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
*startstop = ide_stopped;
return 1;
}
if (ata_busy_poll(drive, timeout)) {
*startstop = ata_error(drive, rq, "status timeout");
return 1;
}
/*
* Allow status to settle, then read it again. A few rare drives
* vastly violate the 400ns spec here, so we'll wait up to 10usec for a
* "good" status rather than expensively fail things immediately. This
* fix courtesy of Matthew Faupel & Niccolo Rigacci.
*/
for (i = 0; i < 10; i++) {
udelay(1);
if (ata_status(drive, good, bad))
return 0;
}
*startstop = ata_error(drive, rq, "status error");
return 1;
}
EXPORT_SYMBOL(ata_status_poll);
/* /*
* Handle the nIEN - negated Interrupt ENable of the drive. * Handle the nIEN - negated Interrupt ENable of the drive.
* This is controlling whatever the drive will acnowlenge commands * This is controlling whatever the drive will acnowlenge commands
...@@ -160,7 +233,7 @@ void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) ...@@ -160,7 +233,7 @@ void ata_out_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf)
} }
/* /*
* Output a complete register file. * Input a complete register file.
*/ */
void ata_in_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf) void ata_in_regfile(struct ata_device *drive, struct hd_drive_task_hdr *rf)
{ {
......
...@@ -556,7 +556,7 @@ static void cdrom_end_request(struct ata_device *drive, struct request *rq, int ...@@ -556,7 +556,7 @@ static void cdrom_end_request(struct ata_device *drive, struct request *rq, int
if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors) if ((rq->flags & REQ_CMD) && !rq->current_nr_sectors)
uptodate = 1; uptodate = 1;
ide_end_request(drive, rq, uptodate); ata_end_request(drive, rq, uptodate);
} }
...@@ -734,7 +734,7 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive, ...@@ -734,7 +734,7 @@ static ide_startstop_t cdrom_start_packet_command(struct ata_device *drive,
struct cdrom_info *info = drive->driver_data; struct cdrom_info *info = drive->driver_data;
/* Wait for the controller to be idle. */ /* Wait for the controller to be idle. */
if (ide_wait_stat(&startstop, drive, rq, 0, BUSY_STAT, WAIT_READY)) if (ata_status_poll(drive, 0, BUSY_STAT, WAIT_READY, rq, &startstop))
return startstop; return startstop;
spin_lock_irqsave(ch->lock, flags); spin_lock_irqsave(ch->lock, flags);
...@@ -798,7 +798,8 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive, ...@@ -798,7 +798,8 @@ static ide_startstop_t cdrom_transfer_packet_command(struct ata_device *drive,
return startstop; return startstop;
} else { } else {
/* Otherwise, we must wait for DRQ to get set. */ /* Otherwise, we must wait for DRQ to get set. */
if (ide_wait_stat(&startstop, drive, rq, DRQ_STAT, BUSY_STAT, WAIT_READY)) if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
WAIT_READY, rq, &startstop))
return startstop; return startstop;
} }
...@@ -926,7 +927,14 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request ...@@ -926,7 +927,14 @@ static ide_startstop_t cdrom_read_intr(struct ata_device *drive, struct request
if (dma) { if (dma) {
if (!dma_error) { if (!dma_error) {
__ide_end_request(drive, rq, 1, rq->nr_sectors); /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
__ata_end_request(drive, rq, 1, rq->nr_sectors);
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
} else } else
return ata_error(drive, rq, "dma error"); return ata_error(drive, rq, "dma error");
...@@ -1518,7 +1526,14 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request ...@@ -1518,7 +1526,14 @@ static ide_startstop_t cdrom_write_intr(struct ata_device *drive, struct request
if (dma_error) if (dma_error)
return ata_error(drive, rq, "dma error"); return ata_error(drive, rq, "dma error");
__ide_end_request(drive, rq, 1, rq->nr_sectors); /* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
__ata_end_request(drive, rq, 1, rq->nr_sectors);
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
} }
......
...@@ -91,104 +91,99 @@ static int lba_capacity_is_ok(struct hd_driveid *id) ...@@ -91,104 +91,99 @@ static int lba_capacity_is_ok(struct hd_driveid *id)
} }
/* /*
* Handler for command with PIO data-in phase * Handler for command with PIO data-in phase.
*/ */
static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t task_in_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags; unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
char *buf = NULL; int ret;
spin_lock_irqsave(ch->lock, flags);
if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
if (drive->status & (ERR_STAT|DRQ_STAT)) if (drive->status & (ERR_STAT|DRQ_STAT)) {
spin_unlock_irqrestore(ch->lock, flags);
return ata_error(drive, rq, __FUNCTION__); return ata_error(drive, rq, __FUNCTION__);
}
if (!(drive->status & BUSY_STAT)) { if (!(drive->status & BUSY_STAT)) {
#if 0 // printk("task_in_intr to Soon wait for next interrupt\n");
printk("task_in_intr to Soon wait for next interrupt\n");
#endif
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL); ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
} }
buf = ide_map_rq(rq, &flags);
#if 0
printk("Read: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors);
#endif
ata_read(drive, buf, SECTOR_WORDS); // printk("Read: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors);
ide_unmap_rq(rq, buf, &flags); {
unsigned long flags;
char *buf;
buf = ide_map_rq(rq, &flags);
ata_read(drive, buf, SECTOR_WORDS);
ide_unmap_rq(rq, buf, &flags);
}
/* First segment of the request is complete. note that this does not /* First segment of the request is complete. note that this does not
* necessarily mean that the entire request is done!! this is only true * necessarily mean that the entire request is done!! this is only true
* if ide_end_request() returns 0. * if ata_end_request() returns 0.
*/ */
if (--rq->current_nr_sectors <= 0) { if (--rq->current_nr_sectors <= 0 && !__ata_end_request(drive, rq, 1, 0)) {
#if 0 // printk("Request Ended stat: %02x\n", drive->status);
printk("Request Ended stat: %02x\n", drive->status); ret = ide_stopped;
#endif } else {
if (!ide_end_request(drive, rq, 1)) /* still data left to transfer */
return ide_stopped; ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
}
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags); ret = ide_started;
/* still data left to transfer */ }
ata_set_handler(drive, task_in_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ret;
} }
/* /*
* Handler for command with PIO data-out phase * Handler for command with PIO data-out phase.
*/ */
static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t task_out_intr(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags; unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
char *buf = NULL; int ret;
if (!ata_status(drive, DRIVE_READY, drive->bad_wstat)) spin_lock_irqsave(ch->lock, flags);
return ata_error(drive, rq, __FUNCTION__); if (!ata_status(drive, DRIVE_READY, drive->bad_wstat)) {
spin_unlock_irqrestore(ch->lock, flags);
if (!rq->current_nr_sectors) return ata_error(drive, rq, __FUNCTION__);
if (!ide_end_request(drive, rq, 1)) }
return ide_stopped;
if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) { if (!rq->current_nr_sectors && !__ata_end_request(drive, rq, 1, 0)) {
buf = ide_map_rq(rq, &flags); ret = ide_stopped;
#if 0 } else {
printk("write: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors); if ((rq->nr_sectors == 1) != (drive->status & DRQ_STAT)) {
#endif unsigned long flags;
char *buf;
ata_write(drive, buf, SECTOR_WORDS); // printk("write: %p, rq->current_nr_sectors: %d\n", buf, (int) rq->current_nr_sectors);
ide_unmap_rq(rq, buf, &flags); buf = ide_map_rq(rq, &flags);
rq->errors = 0; ata_write(drive, buf, SECTOR_WORDS);
rq->current_nr_sectors--; ide_unmap_rq(rq, buf, &flags);
}
/* FIXME: this locking should encompass the above register rq->errors = 0;
* file access too. --rq->current_nr_sectors;
*/ }
ata_set_handler(drive, task_out_intr, WAIT_CMD, NULL);
spin_lock_irqsave(ch->lock, flags); ret = ide_started;
ata_set_handler(drive, task_out_intr, WAIT_CMD, NULL); }
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ret;
} }
/* /*
...@@ -198,63 +193,68 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request ...@@ -198,63 +193,68 @@ static ide_startstop_t task_mulin_intr(struct ata_device *drive, struct request
{ {
unsigned long flags; unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
char *buf = NULL; int ret;
unsigned int msect;
unsigned int nsect;
spin_lock_irqsave(ch->lock, flags);
if (!ata_status(drive, DATA_READY, BAD_R_STAT)) { if (!ata_status(drive, DATA_READY, BAD_R_STAT)) {
if (drive->status & (ERR_STAT|DRQ_STAT)) if (drive->status & (ERR_STAT|DRQ_STAT)) {
return ata_error(drive, rq, __FUNCTION__); spin_unlock_irqrestore(ch->lock, flags);
/* FIXME: this locking should encompass the above register return ata_error(drive, rq, __FUNCTION__);
* file access too. }
*/
spin_lock_irqsave(ch->lock, flags);
/* no data yet, so wait for another interrupt */ /* no data yet, so wait for another interrupt */
ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; ret = ide_started;
} } else {
unsigned int msect;
/* (ks/hs): Fixed Multi-Sector transfer */ /* (ks/hs): Fixed Multi-Sector transfer */
msect = drive->mult_count; msect = drive->mult_count;
do { do {
nsect = rq->current_nr_sectors; unsigned int nsect;
if (nsect > msect)
nsect = msect;
buf = ide_map_rq(rq, &flags); nsect = rq->current_nr_sectors;
if (nsect > msect)
nsect = msect;
#if 0 #if 0
printk("Multiread: %p, nsect: %d , rq->current_nr_sectors: %d\n", printk("Multiread: %p, nsect: %d , rq->current_nr_sectors: %d\n",
buf, nsect, rq->current_nr_sectors); buf, nsect, rq->current_nr_sectors);
#endif #endif
ata_read(drive, buf, nsect * SECTOR_WORDS); {
ide_unmap_rq(rq, buf, &flags); unsigned long flags;
rq->errors = 0; char *buf;
rq->current_nr_sectors -= nsect;
msect -= nsect;
if (!rq->current_nr_sectors) {
if (!ide_end_request(drive, rq, 1))
return ide_stopped;
}
} while (msect);
/* FIXME: this locking should encompass the above register buf = ide_map_rq(rq, &flags);
* file access too. ata_read(drive, buf, nsect * SECTOR_WORDS);
*/ ide_unmap_rq(rq, buf, &flags);
}
spin_lock_irqsave(ch->lock, flags); rq->errors = 0;
/* rq->current_nr_sectors -= nsect;
* more data left msect -= nsect;
*/
ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL); /* FIXME: this seems buggy */
if (!rq->current_nr_sectors) {
if (!__ata_end_request(drive, rq, 1, 0)) {
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped;
}
}
} while (msect);
/* more data left */
ata_set_handler(drive, task_mulin_intr, WAIT_CMD, NULL);
ret = ide_started;
}
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ret;
} }
static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq) static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request *rq)
...@@ -262,9 +262,9 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request ...@@ -262,9 +262,9 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
unsigned long flags; unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
int ok; int ok;
int mcount = drive->mult_count; int ret;
ide_startstop_t startstop;
spin_lock_irqsave(ch->lock, flags);
/* /*
* FIXME: the drive->status checks here seem to be messy. * FIXME: the drive->status checks here seem to be messy.
...@@ -277,80 +277,67 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request ...@@ -277,80 +277,67 @@ static ide_startstop_t task_mulout_intr(struct ata_device *drive, struct request
if (!ok || !rq->nr_sectors) { if (!ok || !rq->nr_sectors) {
if (drive->status & (ERR_STAT | DRQ_STAT)) { if (drive->status & (ERR_STAT | DRQ_STAT)) {
startstop = ata_error(drive, rq, __FUNCTION__); spin_unlock_irqrestore(ch->lock, flags);
return startstop; return ata_error(drive, rq, __FUNCTION__);
} }
} }
if (!rq->nr_sectors) { if (!rq->nr_sectors) {
__ide_end_request(drive, rq, 1, rq->hard_nr_sectors); __ata_end_request(drive, rq, 1, rq->hard_nr_sectors);
rq->bio = NULL; rq->bio = NULL;
ret = ide_stopped;
return ide_stopped; } else if (!ok) {
}
if (!ok) {
/* no data yet, so wait for another interrupt */ /* no data yet, so wait for another interrupt */
if (!ch->handler) { if (!ch->handler)
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL); ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags); ret = ide_started;
} } else {
int mcount = drive->mult_count;
return ide_started;
} do {
char *buf;
do { int nsect = rq->current_nr_sectors;
char *buffer; unsigned long flags;
int nsect = rq->current_nr_sectors;
unsigned long flags; if (nsect > mcount)
nsect = mcount;
if (nsect > mcount) mcount -= nsect;
nsect = mcount;
mcount -= nsect; buf = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq);
rq->sector += nsect;
buffer = bio_kmap_irq(rq->bio, &flags) + ide_rq_offset(rq); rq->nr_sectors -= nsect;
rq->sector += nsect; rq->current_nr_sectors -= nsect;
rq->nr_sectors -= nsect;
rq->current_nr_sectors -= nsect; /* Do we move to the next bio after this? */
if (!rq->current_nr_sectors) {
/* remember to fix this up /jens */
struct bio *bio = rq->bio->bi_next;
/* end early if we ran out of requests */
if (!bio) {
mcount = 0;
} else {
rq->bio = bio;
rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
}
}
/* Do we move to the next bio after this? */ /*
if (!rq->current_nr_sectors) { * Ok, we're all setup for the interrupt re-entering us on the
/* remember to fix this up /jens */ * last transfer.
struct bio *bio = rq->bio->bi_next; */
ata_write(drive, buf, nsect * SECTOR_WORDS);
bio_kunmap_irq(buffer, &flags);
} while (mcount);
/* end early if we ran out of requests */ rq->errors = 0;
if (!bio) {
mcount = 0;
} else {
rq->bio = bio;
rq->current_nr_sectors = bio_iovec(bio)->bv_len >> 9;
}
}
/* if (!ch->handler)
* Ok, we're all setup for the interrupt re-entering us on the ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
* last transfer.
*/
ata_write(drive, buffer, nsect * SECTOR_WORDS);
bio_kunmap_irq(buffer, &flags);
} while (mcount);
rq->errors = 0;
if (!ch->handler) {
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags); ret = ide_started;
ata_set_handler(drive, task_mulout_intr, WAIT_CMD, NULL);
spin_unlock_irqrestore(ch->lock, flags);
} }
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
...@@ -571,24 +558,34 @@ static ide_startstop_t lba48_do_request(struct ata_device *drive, struct request ...@@ -571,24 +558,34 @@ static ide_startstop_t lba48_do_request(struct ata_device *drive, struct request
*/ */
static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct request *rq, sector_t block) static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct request *rq, sector_t block)
{ {
/* unsigned long flags;
* Wait until all request have bin finished. struct ata_channel *ch = drive->channel;
*/ int ret;
/* make sure all request have bin finished
* FIXME: this check doesn't make sense go! */
while (drive->blocked) { while (drive->blocked) {
yield(); yield();
printk(KERN_ERR "ide: Request while drive blocked?"); printk(KERN_ERR "ide: Request while drive blocked?");
} }
/* FIXME: Move this lock entiery upstream. */
spin_lock_irqsave(ch->lock, flags);
/* FIXME: this check doesn't make sense */
if (!(rq->flags & REQ_CMD)) { if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "idedisk_do_request - bad command"); blk_dump_rq_flags(rq, "idedisk_do_request - bad command");
ide_end_request(drive, rq, 0); __ata_end_request(drive, rq, 0, 0);
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
} }
if (IS_PDC4030_DRIVE) { if (IS_PDC4030_DRIVE) {
extern ide_startstop_t promise_do_request(struct ata_device *, struct request *, sector_t); extern ide_startstop_t promise_do_request(struct ata_device *, struct request *, sector_t);
spin_unlock_irqrestore(drive->channel->lock, flags);
return promise_do_request(drive, rq, block); return promise_do_request(drive, rq, block);
} }
...@@ -596,11 +593,8 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -596,11 +593,8 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
* start a tagged operation * start a tagged operation
*/ */
if (drive->using_tcq) { if (drive->using_tcq) {
unsigned long flags;
int ret; int ret;
spin_lock_irqsave(drive->channel->lock, flags);
ret = blk_queue_start_tag(&drive->queue, rq); ret = blk_queue_start_tag(&drive->queue, rq);
if (ata_pending_commands(drive) > drive->max_depth) if (ata_pending_commands(drive) > drive->max_depth)
...@@ -608,27 +602,27 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque ...@@ -608,27 +602,27 @@ static ide_startstop_t idedisk_do_request(struct ata_device *drive, struct reque
if (ata_pending_commands(drive) > drive->max_last_depth) if (ata_pending_commands(drive) > drive->max_last_depth)
drive->max_last_depth = ata_pending_commands(drive); drive->max_last_depth = ata_pending_commands(drive);
spin_unlock_irqrestore(drive->channel->lock, flags);
if (ret) { if (ret) {
BUG_ON(!ata_pending_commands(drive)); BUG_ON(!ata_pending_commands(drive));
spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ide_started;
} }
} }
/* 48-bit LBA */
if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing)) if ((drive->id->cfs_enable_2 & 0x0400) && (drive->addressing))
return lba48_do_request(drive, rq, block); ret = lba48_do_request(drive, rq, block);
else if (drive->select.b.lba)
ret = lba28_do_request(drive, rq, block);
else
ret = chs_do_request(drive, rq, block);
/* 28-bit LBA */ spin_unlock_irqrestore(ch->lock, flags);
if (drive->select.b.lba)
return lba28_do_request(drive, rq, block);
/* 28-bit CHS */ return ret;
return chs_do_request(drive, rq, block);
} }
static int idedisk_open (struct inode *inode, struct file *filp, struct ata_device *drive) static int idedisk_open(struct inode *inode, struct file *filp, struct ata_device *drive)
{ {
MOD_INC_USE_COUNT; MOD_INC_USE_COUNT;
if (drive->removable && drive->usage == 1) { if (drive->removable && drive->usage == 1) {
...@@ -648,10 +642,11 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi ...@@ -648,10 +642,11 @@ static int idedisk_open (struct inode *inode, struct file *filp, struct ata_devi
drive->doorlocking = 0; drive->doorlocking = 0;
} }
} }
return 0; return 0;
} }
static int idedisk_flushcache(struct ata_device *drive) static int flush_cache(struct ata_device *drive)
{ {
struct ata_taskfile args; struct ata_taskfile args;
...@@ -661,6 +656,7 @@ static int idedisk_flushcache(struct ata_device *drive) ...@@ -661,6 +656,7 @@ static int idedisk_flushcache(struct ata_device *drive)
args.cmd = WIN_FLUSH_CACHE_EXT; args.cmd = WIN_FLUSH_CACHE_EXT;
else else
args.cmd = WIN_FLUSH_CACHE; args.cmd = WIN_FLUSH_CACHE;
return ide_raw_taskfile(drive, &args); return ide_raw_taskfile(drive, &args);
} }
...@@ -680,7 +676,7 @@ static void idedisk_release(struct inode *inode, struct file *filp, struct ata_d ...@@ -680,7 +676,7 @@ static void idedisk_release(struct inode *inode, struct file *filp, struct ata_d
} }
} }
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache)
if (idedisk_flushcache(drive)) if (flush_cache(drive))
printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
drive->name); drive->name);
MOD_DEC_USE_COUNT; MOD_DEC_USE_COUNT;
...@@ -1244,15 +1240,27 @@ static void idedisk_setup(struct ata_device *drive) ...@@ -1244,15 +1240,27 @@ static void idedisk_setup(struct ata_device *drive)
static int idedisk_cleanup(struct ata_device *drive) static int idedisk_cleanup(struct ata_device *drive)
{ {
int ret;
if (!drive) if (!drive)
return 0; return 0;
put_device(&drive->device); if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) {
if ((drive->id->cfs_enable_2 & 0x3000) && drive->wcache) if (flush_cache(drive))
if (idedisk_flushcache(drive))
printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n", printk (KERN_INFO "%s: Write Cache FAILED Flushing!\n",
drive->name); drive->name);
return ide_unregister_subdriver(drive); }
ret = ide_unregister_subdriver(drive);
/* FIXME: This is killing the kernel with BUG 185 at asm/spinlocks.h
* horribly. Check whatever we did REGISTER the device properly
* in front?
*/
#if 0
put_device(&drive->device);
#endif
return ret;
} }
static int idedisk_ioctl(struct ata_device *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg) static int idedisk_ioctl(struct ata_device *drive, struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
......
...@@ -608,7 +608,7 @@ typedef struct { ...@@ -608,7 +608,7 @@ typedef struct {
/* /*
* idefloppy_end_request is used to finish servicing a request. * idefloppy_end_request is used to finish servicing a request.
* *
* For read/write requests, we will call ide_end_request to pass to the * For read/write requests, we will call ata_end_request to pass to the
* next buffer. * next buffer.
*/ */
static int idefloppy_end_request(struct ata_device *drive, struct request *rq, int uptodate) static int idefloppy_end_request(struct ata_device *drive, struct request *rq, int uptodate)
...@@ -632,7 +632,7 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i ...@@ -632,7 +632,7 @@ static int idefloppy_end_request(struct ata_device *drive, struct request *rq, i
return 0; return 0;
if (!(rq->flags & REQ_SPECIAL)) { if (!(rq->flags & REQ_SPECIAL)) {
ide_end_request(drive, rq, uptodate); ata_end_request(drive, rq, uptodate);
return 0; return 0;
} }
...@@ -956,9 +956,12 @@ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct re ...@@ -956,9 +956,12 @@ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct re
ide_startstop_t startstop; ide_startstop_t startstop;
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
idefloppy_ireason_reg_t ireason; idefloppy_ireason_reg_t ireason;
int ret;
if (ide_wait_stat (&startstop, drive, rq, DRQ_STAT, BUSY_STAT, WAIT_READY)) { if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
WAIT_READY, rq, &startstop)) {
printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop; return startstop;
} }
...@@ -968,18 +971,18 @@ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct re ...@@ -968,18 +971,18 @@ static ide_startstop_t idefloppy_transfer_pc(struct ata_device *drive, struct re
spin_lock_irqsave(ch->lock, flags); spin_lock_irqsave(ch->lock, flags);
ireason.all=IN_BYTE (IDE_IREASON_REG); ireason.all=IN_BYTE (IDE_IREASON_REG);
if (!ireason.b.cod || ireason.b.io) {
spin_unlock_irqrestore(ch->lock, flags);
if (!ireason.b.cod || ireason.b.io) {
printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped; ret = ide_stopped;
} else {
ata_set_handler (drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */
ret = ide_started;
} }
ata_set_handler (drive, idefloppy_pc_intr, IDEFLOPPY_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_write(drive, floppy->pc->c, 12); /* Send the actual packet */
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ret;
} }
...@@ -1010,39 +1013,43 @@ static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct r ...@@ -1010,39 +1013,43 @@ static ide_startstop_t idefloppy_transfer_pc1(struct ata_device *drive, struct r
idefloppy_floppy_t *floppy = drive->driver_data; idefloppy_floppy_t *floppy = drive->driver_data;
ide_startstop_t startstop; ide_startstop_t startstop;
idefloppy_ireason_reg_t ireason; idefloppy_ireason_reg_t ireason;
int ret;
if (ide_wait_stat(&startstop, drive, rq, DRQ_STAT, BUSY_STAT, WAIT_READY)) { if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
WAIT_READY, rq, &startstop)) {
printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n"); printk (KERN_ERR "ide-floppy: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop; return startstop;
} }
/* FIXME: this locking should encompass the above register /* FIXME: this locking should encompass the above register
* file access too. * file access too.
*/ */
spin_lock_irqsave(ch->lock, flags); spin_lock_irqsave(ch->lock, flags);
ireason.all=IN_BYTE (IDE_IREASON_REG); ireason.all=IN_BYTE(IDE_IREASON_REG);
if (!ireason.b.cod || ireason.b.io) { if (!ireason.b.cod || ireason.b.io) {
spin_unlock_irqrestore(ch->lock, flags);
printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n"); printk (KERN_ERR "ide-floppy: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped; ret = ide_stopped;
} } else {
/* /*
* The following delay solves a problem with ATAPI Zip 100 drives where * The following delay solves a problem with ATAPI Zip 100 drives where
* the Busy flag was apparently being deasserted before the unit was * the Busy flag was apparently being deasserted before the unit was
* ready to receive data. This was happening on a 1200 MHz Athlon * ready to receive data. This was happening on a 1200 MHz Athlon
* system. 10/26/01 25msec is too short, 40 and 50msec work well. * system. 10/26/01 25msec is too short, 40 and 50msec work well.
* idefloppy_pc_intr will not be actually used until after the packet * idefloppy_pc_intr will not be actually used until after the packet
* is moved in about 50 msec. * is moved in about 50 msec.
*/ */
ata_set_handler(drive, ata_set_handler(drive,
idefloppy_pc_intr, /* service routine for packet command */ idefloppy_pc_intr, /* service routine for packet command */
floppy->ticks, /* wait this long before "failing" */ floppy->ticks, /* wait this long before "failing" */
idefloppy_transfer_pc2); /* fail == transfer_pc2 */ idefloppy_transfer_pc2); /* fail == transfer_pc2 */
ret = ide_started;
}
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ret;
} }
/* /*
......
...@@ -2196,9 +2196,12 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ ...@@ -2196,9 +2196,12 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ
idetape_ireason_reg_t ireason; idetape_ireason_reg_t ireason;
int retries = 100; int retries = 100;
ide_startstop_t startstop; ide_startstop_t startstop;
int ret;
if (ide_wait_stat(&startstop, drive, rq, DRQ_STAT, BUSY_STAT, WAIT_READY)) { if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
WAIT_READY, rq, &startstop)) {
printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n"); printk (KERN_ERR "ide-tape: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop; return startstop;
} }
...@@ -2220,16 +2223,16 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ ...@@ -2220,16 +2223,16 @@ static ide_startstop_t idetape_transfer_pc(struct ata_device *drive, struct requ
} }
if (!ireason.b.cod || ireason.b.io) { if (!ireason.b.cod || ireason.b.io) {
printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n"); printk (KERN_ERR "ide-tape: (IO,CoD) != (0,1) while issuing a packet command\n");
spin_unlock_irqrestore(ch->lock, flags); ret = ide_stopped;
} else {
return ide_stopped; tape->cmd_start_time = jiffies;
ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_write(drive,pc->c,12); /* Send the actual packet */
ret = ide_started;
} }
tape->cmd_start_time = jiffies;
ata_set_handler(drive, idetape_pc_intr, IDETAPE_WAIT_CMD, NULL); /* Set the interrupt routine */
atapi_write(drive,pc->c,12); /* Send the actual packet */
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
return ide_started; return ret;
} }
static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive, static ide_startstop_t idetape_issue_packet_command(struct ata_device *drive,
...@@ -2618,7 +2621,7 @@ static ide_startstop_t idetape_do_request(struct ata_device *drive, struct reque ...@@ -2618,7 +2621,7 @@ static ide_startstop_t idetape_do_request(struct ata_device *drive, struct reque
* We do not support buffer cache originated requests. * We do not support buffer cache originated requests.
*/ */
printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%ld)\n", drive->name, rq->flags); printk (KERN_NOTICE "ide-tape: %s: Unsupported command in request queue (%ld)\n", drive->name, rq->flags);
ide_end_request(drive, rq, 0); /* Let the common code handle it */ ata_end_request(drive, rq, 0); /* Let the common code handle it */
return ide_stopped; return ide_stopped;
} }
......
...@@ -233,7 +233,8 @@ ide_startstop_t ata_taskfile(struct ata_device *drive, ...@@ -233,7 +233,8 @@ ide_startstop_t ata_taskfile(struct ata_device *drive,
ar->cmd == WIN_MULTWRITE_EXT) { ar->cmd == WIN_MULTWRITE_EXT) {
ide_startstop_t startstop; ide_startstop_t startstop;
if (ide_wait_stat(&startstop, drive, rq, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { if (ata_status_poll(drive, DATA_READY, drive->bad_wstat,
WAIT_DRQ, rq, &startstop)) {
printk(KERN_ERR "%s: no DRQ after issuing %s\n", printk(KERN_ERR "%s: no DRQ after issuing %s\n",
drive->name, drive->mult_count ? "MULTWRITE" : "WRITE"); drive->name, drive->mult_count ? "MULTWRITE" : "WRITE");
return startstop; return startstop;
......
...@@ -106,18 +106,19 @@ int drive_is_flashcard(struct ata_device *drive) ...@@ -106,18 +106,19 @@ int drive_is_flashcard(struct ata_device *drive)
return 0; return 0;
} }
int __ide_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs) /*
* Not locking variabt of the end_request method.
*
* Channel lock should be held.
*/
int __ata_end_request(struct ata_device *drive, struct request *rq, int uptodate, unsigned int nr_secs)
{ {
unsigned long flags;
int ret = 1; int ret = 1;
spin_lock_irqsave(drive->channel->lock, flags);
BUG_ON(!(rq->flags & REQ_STARTED)); BUG_ON(!(rq->flags & REQ_STARTED));
/* /* FIXME: Make this "small" hack to eliminate locking from
* small hack to eliminate locking from ide_end_request to grab * ata_end_request to grab the first segment number of sectors go away.
* the first segment number of sectors
*/ */
if (!nr_secs) if (!nr_secs)
nr_secs = rq->hard_cur_sectors; nr_secs = rq->hard_cur_sectors;
...@@ -126,7 +127,6 @@ int __ide_end_request(struct ata_device *drive, struct request *rq, int uptodate ...@@ -126,7 +127,6 @@ int __ide_end_request(struct ata_device *drive, struct request *rq, int uptodate
* Decide whether to reenable DMA -- 3 is a random magic for now, * Decide whether to reenable DMA -- 3 is a random magic for now,
* if we DMA timeout more than 3 times, just stay in PIO. * if we DMA timeout more than 3 times, just stay in PIO.
*/ */
if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) { if (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
drive->state = 0; drive->state = 0;
udma_enable(drive, 1, 1); udma_enable(drive, 1, 1);
...@@ -143,15 +143,24 @@ int __ide_end_request(struct ata_device *drive, struct request *rq, int uptodate ...@@ -143,15 +143,24 @@ int __ide_end_request(struct ata_device *drive, struct request *rq, int uptodate
ret = 0; ret = 0;
} }
spin_unlock_irqrestore(drive->channel->lock, flags);
return ret; return ret;
} }
/* This is the default end request function as well */ /*
int ide_end_request(struct ata_device *drive, struct request *rq, int uptodate) * This is the default end request function as well
*/
int ata_end_request(struct ata_device *drive, struct request *rq, int uptodate)
{ {
return __ide_end_request(drive, rq, uptodate, 0); unsigned long flags;
struct ata_channel *ch = drive->channel;
int ret;
spin_lock_irqsave(ch->lock, flags);
ret = __ata_end_request(drive, rq, uptodate, 0);
spin_unlock_irqrestore(drive->channel->lock, flags);
return ret;
} }
/* /*
...@@ -260,24 +269,25 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req ...@@ -260,24 +269,25 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
int ret = ide_stopped; int ret = ide_stopped;
spin_lock_irqsave(ch->lock, flags);
ata_select(drive, 10); ata_select(drive, 10);
if (!ata_status(drive, 0, BUSY_STAT)) { if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
spin_unlock_irqrestore(ch->lock, flags);
ret = ide_started; /* continue polling */ ret = ide_started; /* continue polling */
} else { } else {
ch->poll_timeout = 0; /* end of polling */ ch->poll_timeout = 0; /* end of polling */
printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status); printk("%s: ATAPI reset timed out, status=0x%02x\n", drive->name, drive->status);
ret = do_reset1(drive, 1); /* do it the old fashioned way */ ret = do_reset1(drive, 0); /* do it the old fashioned way */
} }
} else { } else {
printk("%s: ATAPI reset complete\n", drive->name); printk("%s: ATAPI reset complete\n", drive->name);
ch->poll_timeout = 0; /* done polling */ ch->poll_timeout = 0; /* done polling */
ret = ide_stopped;
} }
spin_unlock_irqrestore(ch->lock, flags);
return ret; return ret;
} }
...@@ -289,20 +299,20 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req ...@@ -289,20 +299,20 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req
*/ */
static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq) static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
int ret;
spin_lock_irqsave(ch->lock, flags);
if (!ata_status(drive, 0, BUSY_STAT)) { if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
unsigned long flags;
spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, reset_pollfunc, HZ/20, NULL); ata_set_handler(drive, reset_pollfunc, HZ/20, NULL);
spin_unlock_irqrestore(ch->lock, flags); ret = ide_started; /* continue polling */
} else {
return ide_started; /* continue polling */ printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status);
++drive->failures;
ret = ide_stopped;
} }
printk("%s: reset timed out, status=0x%02x\n", ch->name, drive->status);
++drive->failures;
} else { } else {
u8 stat; u8 stat;
...@@ -333,8 +343,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * ...@@ -333,8 +343,11 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
printk(KERN_ERR "%s error [%02x]\n", msg, stat); printk(KERN_ERR "%s error [%02x]\n", msg, stat);
++drive->failures; ++drive->failures;
} }
ret = ide_stopped;
} }
ch->poll_timeout = 0; /* done polling */ ch->poll_timeout = 0; /* done polling */
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
} }
...@@ -357,7 +370,7 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request * ...@@ -357,7 +370,7 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
* Channel lock should be held. * Channel lock should be held.
*/ */
static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) static ide_startstop_t do_reset1(struct ata_device *drive, int try_atapi)
{ {
unsigned int unit; unsigned int unit;
unsigned long flags; unsigned long flags;
...@@ -367,15 +380,17 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi) ...@@ -367,15 +380,17 @@ static ide_startstop_t do_reset1(struct ata_device *drive, int do_not_try_atapi)
__cli(); /* local CPU only */ __cli(); /* local CPU only */
/* For an ATAPI device, first try an ATAPI SRST. */ /* For an ATAPI device, first try an ATAPI SRST. */
if (drive->type != ATA_DISK && !do_not_try_atapi) { if (try_atapi) {
check_crc_errors(drive); if (drive->type != ATA_DISK) {
ata_select(drive, 20); check_crc_errors(drive);
OUT_BYTE(WIN_SRST, IDE_COMMAND_REG); ata_select(drive, 20);
ch->poll_timeout = jiffies + WAIT_WORSTCASE; OUT_BYTE(WIN_SRST, IDE_COMMAND_REG);
ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL); ch->poll_timeout = jiffies + WAIT_WORSTCASE;
__restore_flags(flags); /* local CPU only */ ata_set_handler(drive, atapi_reset_pollfunc, HZ/20, NULL);
__restore_flags(flags); /* local CPU only */
return ide_started;
return ide_started;
}
} }
/* /*
...@@ -572,6 +587,7 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch ...@@ -572,6 +587,7 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
return ide_stopped; return ide_stopped;
} }
/* other bits are useless when BUSY */ /* other bits are useless when BUSY */
if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr)) if (stat & BUSY_STAT || ((stat & WRERR_STAT) && !drive->nowerr))
rq->errors |= ERROR_RESET; /* FIXME: What's that?! */ rq->errors |= ERROR_RESET; /* FIXME: What's that?! */
...@@ -598,14 +614,15 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch ...@@ -598,14 +614,15 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
if (rq->errors >= ERROR_MAX) { if (rq->errors >= ERROR_MAX) {
printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name); printk(KERN_ERR "%s: max number of retries exceeded!\n", drive->name);
/* FIXME: make sure all end_request implementations are lock free */
if (ata_ops(drive) && ata_ops(drive)->end_request) if (ata_ops(drive) && ata_ops(drive)->end_request)
ata_ops(drive)->end_request(drive, rq, 0); ata_ops(drive)->end_request(drive, rq, 0);
else else
ide_end_request(drive, rq, 0); __ata_end_request(drive, rq, 0, 0);
} else { } else {
++rq->errors; ++rq->errors;
if ((rq->errors & ERROR_RESET) == ERROR_RESET) if ((rq->errors & ERROR_RESET) == ERROR_RESET)
return do_reset1(drive, 0); return do_reset1(drive, 1);
if ((rq->errors & ERROR_RECAL) == ERROR_RECAL) if ((rq->errors & ERROR_RECAL) == ERROR_RECAL)
return do_recalibrate(drive); return do_recalibrate(drive);
} }
...@@ -613,60 +630,6 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch ...@@ -613,60 +630,6 @@ ide_startstop_t ata_error(struct ata_device *drive, struct request *rq, const ch
return ide_stopped; 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
* returns 0. All other cases return 1 after invoking error handler -- caller
* should just return.
*
* This routine should get fixed to not hog the cpu during extra long waits..
* That could be done by busy-waiting for the first jiffy or two, and then
* setting a timer to wake up at half second intervals thereafter, until
* timeout is achieved, before timing out.
*
* FIXME: Channel lock should be held.
*/
int ide_wait_stat(ide_startstop_t *startstop,
struct ata_device *drive, struct request *rq,
byte good, byte bad, unsigned long timeout)
{
int i;
/* bail early if we've exceeded max_failures */
if (drive->max_failures && (drive->failures > drive->max_failures)) {
*startstop = ide_stopped;
return 1;
}
/* spec allows drive 400ns to assert "BUSY" */
udelay(1);
if (!ata_status(drive, 0, BUSY_STAT)) {
timeout += jiffies;
while (!ata_status(drive, 0, BUSY_STAT)) {
if (time_after(jiffies, timeout)) {
*startstop = ata_error(drive, rq, "status timeout");
return 1;
}
}
}
/*
* Allow status to settle, then read it again. A few rare drives
* vastly violate the 400ns spec here, so we'll wait up to 10usec for a
* "good" status rather than expensively fail things immediately. This
* fix courtesy of Matthew Faupel & Niccolo Rigacci.
*/
for (i = 0; i < 10; i++) {
udelay(1);
if (ata_status(drive, good, bad))
return 0;
}
*startstop = ata_error(drive, rq, "status error");
return 1;
}
/* /*
* This initiates handling of a new I/O request. * This initiates handling of a new I/O request.
*/ */
...@@ -710,8 +673,8 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r ...@@ -710,8 +673,8 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
ide_startstop_t res; ide_startstop_t res;
ata_select(drive, 0); ata_select(drive, 0);
if (ide_wait_stat(&res, drive, rq, drive->ready_stat, if (ata_status_poll(drive, drive->ready_stat, BUSY_STAT | DRQ_STAT,
BUSY_STAT|DRQ_STAT, WAIT_READY)) { WAIT_READY, rq, &res)) {
printk(KERN_WARNING "%s: drive not ready for command\n", drive->name); printk(KERN_WARNING "%s: drive not ready for command\n", drive->name);
return res; return res;
...@@ -731,7 +694,7 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r ...@@ -731,7 +694,7 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
if (ata_ops(drive)->do_request) if (ata_ops(drive)->do_request)
return ata_ops(drive)->do_request(drive, rq, block); return ata_ops(drive)->do_request(drive, rq, block);
else { else {
ide_end_request(drive, rq, 0); ata_end_request(drive, rq, 0);
return ide_stopped; return ide_stopped;
} }
...@@ -748,7 +711,7 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r ...@@ -748,7 +711,7 @@ static ide_startstop_t start_request(struct ata_device *drive, struct request *r
if (ata_ops(drive) && ata_ops(drive)->end_request) if (ata_ops(drive) && ata_ops(drive)->end_request)
ata_ops(drive)->end_request(drive, rq, 0); ata_ops(drive)->end_request(drive, rq, 0);
else else
ide_end_request(drive, rq, 0); ata_end_request(drive, rq, 0);
return ide_stopped; return ide_stopped;
} }
...@@ -1007,65 +970,25 @@ void do_ide_request(request_queue_t *q) ...@@ -1007,65 +970,25 @@ void do_ide_request(request_queue_t *q)
do_request(q->queuedata); do_request(q->queuedata);
} }
/*
* Un-busy the hwgroup etc, and clear any pending DMA status. we want to
* retry the current request in PIO mode instead of risking tossing it
* all away
*/
static void dma_timeout_retry(struct ata_device *drive, struct request *rq)
{
/*
* end current dma transaction
*/
udma_stop(drive);
udma_timeout(drive);
/*
* Disable dma for now, but remember that we did so because of
* a timeout -- we'll reenable after we finish this next request
* (or rather the first chunk of it) in pio.
*/
drive->retry_pio++;
drive->state = DMA_PIO_RETRY;
udma_enable(drive, 0, 0);
/*
* un-busy drive etc (hwgroup->busy is cleared on return) and
* make sure request is sane
*/
drive->rq = NULL;
rq->errors = 0;
if (rq->bio) {
rq->sector = rq->bio->bi_sector;
rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
rq->buffer = NULL;
}
}
/* /*
* This is our timeout function for all drive operations. But note that it can * This is our timeout function for all drive operations. But note that it can
* also be invoked as a result of a "sleep" operation triggered by the * also be invoked as a result of a "sleep" operation triggered by the
* mod_timer() call in do_request. * mod_timer() call in do_request.
*
* FIXME: this should take a drive context instead of a channel.
*/ */
void ide_timer_expiry(unsigned long data) void ide_timer_expiry(unsigned long data)
{ {
struct ata_channel *ch = (struct ata_channel *) data;
ata_handler_t *handler;
ata_expiry_t *expiry;
unsigned long flags; unsigned long flags;
unsigned long wait; struct ata_channel *ch = (struct ata_channel *) data;
/*
* A global lock protects timers etc -- shouldn't get contention
* worth mentioning.
*/
spin_lock_irqsave(ch->lock, flags); spin_lock_irqsave(ch->lock, flags);
del_timer(&ch->timer); del_timer(&ch->timer);
handler = ch->handler; if (!ch->drive) {
if (!handler) { printk(KERN_ERR "%s: IRQ handler was NULL\n", __FUNCTION__);
ch->handler = NULL;
} else if (!ch->handler) {
/* /*
* Either a marginal timeout occurred (got the interrupt just * Either a marginal timeout occurred (got the interrupt just
...@@ -1078,69 +1001,103 @@ void ide_timer_expiry(unsigned long data) ...@@ -1078,69 +1001,103 @@ void ide_timer_expiry(unsigned long data)
clear_bit(IDE_BUSY, ch->active); clear_bit(IDE_BUSY, ch->active);
} else { } else {
struct ata_device *drive = ch->drive; struct ata_device *drive = ch->drive;
if (!drive) { ide_startstop_t ret;
printk(KERN_ERR "ide_timer_expiry: IRQ handler was NULL\n"); ata_handler_t *handler;
ch->handler = NULL;
} else {
ide_startstop_t startstop;
/* paranoia */ /* paranoia */
if (!test_and_set_bit(IDE_BUSY, ch->active)) if (!test_and_set_bit(IDE_BUSY, ch->active))
printk(KERN_ERR "%s: ide_timer_expiry: IRQ handler was not busy??\n", drive->name); printk(KERN_ERR "%s: %s: IRQ handler was not busy?!\n",
if ((expiry = ch->expiry) != NULL) { drive->name, __FUNCTION__);
/* continue */
if ((wait = expiry(drive, drive->rq)) != 0) {
/* reengage timer */
ch->timer.expires = jiffies + wait;
add_timer(&ch->timer);
spin_unlock_irqrestore(ch->lock, flags); if (ch->expiry) {
unsigned long wait;
return; /* continue */
} if ((wait = ch->expiry(drive, drive->rq)) != 0) {
/* reengage timer */
ch->timer.expires = jiffies + wait;
add_timer(&ch->timer);
spin_unlock_irqrestore(ch->lock, flags);
return;
} }
ch->handler = NULL; }
/*
* We need to simulate a real interrupt when invoking /*
* the handler() function, which means we need to globally * We need to simulate a real interrupt when invoking the
* mask the specific IRQ: * handler() function, which means we need to globally mask the
*/ * specific IRQ:
*/
spin_unlock(ch->lock); handler = ch->handler;
ch->handler = NULL;
spin_unlock(ch->lock);
ch = drive->channel; ch = drive->channel;
#if DISABLE_IRQ_NOSYNC #if DISABLE_IRQ_NOSYNC
disable_irq_nosync(ch->irq); disable_irq_nosync(ch->irq);
#else #else
disable_irq(ch->irq); /* disable_irq_nosync ?? */ disable_irq(ch->irq); /* disable_irq_nosync ?? */
#endif #endif
__cli(); /* local CPU only, as if we were handling an interrupt */ __cli(); /* local CPU only, as if we were handling an interrupt */
if (ch->poll_timeout != 0) { if (ch->poll_timeout) {
startstop = handler(drive, drive->rq); ret = handler(drive, drive->rq);
} else if (drive_is_ready(drive)) { } else if (drive_is_ready(drive)) {
if (drive->waiting_for_dma) if (drive->waiting_for_dma)
udma_irq_lost(drive); udma_irq_lost(drive);
(void) ide_ack_intr(ch); (void) ide_ack_intr(ch);
printk("%s: lost interrupt\n", drive->name); printk("%s: lost interrupt\n", drive->name);
startstop = handler(drive, drive->rq); ret = handler(drive, drive->rq);
} else { } else if (drive->waiting_for_dma) {
if (drive->waiting_for_dma) { struct request *rq = drive->rq;
startstop = ide_stopped;
dma_timeout_retry(drive, drive->rq); /*
} else * Un-busy the hwgroup etc, and clear any pending DMA
startstop = ata_error(drive, drive->rq, "irq timeout"); * status. we want to retry the current request in PIO
* mode instead of risking tossing it all away.
*/
udma_stop(drive);
udma_timeout(drive);
/* Disable dma for now, but remember that we did so
* because of a timeout -- we'll reenable after we
* finish this next request (or rather the first chunk
* of it) in pio.
*/
drive->retry_pio++;
drive->state = DMA_PIO_RETRY;
udma_enable(drive, 0, 0);
/* Un-busy drive etc (hwgroup->busy is cleared on
* return) and make sure request is sane.
*/
drive->rq = NULL;
rq->errors = 0;
if (rq->bio) {
rq->sector = rq->bio->bi_sector;
rq->current_nr_sectors = bio_iovec(rq->bio)->bv_len >> 9;
rq->buffer = NULL;
} }
enable_irq(ch->irq); ret = ide_stopped;
} else
ret = ata_error(drive, drive->rq, "irq timeout");
spin_lock_irq(ch->lock); enable_irq(ch->irq);
if (startstop == ide_stopped) spin_lock_irq(ch->lock);
clear_bit(IDE_BUSY, ch->active);
} if (ret == ide_stopped)
} clear_bit(IDE_BUSY, ch->active);
do_request(ch->drive->channel);
/* Reenter the request handling engine */
do_request(ch);
}
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
} }
...@@ -1440,11 +1397,10 @@ EXPORT_SYMBOL(ata_set_handler); ...@@ -1440,11 +1397,10 @@ EXPORT_SYMBOL(ata_set_handler);
EXPORT_SYMBOL(ata_dump); EXPORT_SYMBOL(ata_dump);
EXPORT_SYMBOL(ata_error); EXPORT_SYMBOL(ata_error);
EXPORT_SYMBOL(ide_wait_stat);
/* FIXME: this is a trully bad name */ /* FIXME: this is a trully bad name */
EXPORT_SYMBOL(restart_request); EXPORT_SYMBOL(restart_request);
EXPORT_SYMBOL(__ide_end_request); EXPORT_SYMBOL(ata_end_request);
EXPORT_SYMBOL(ide_end_request); EXPORT_SYMBOL(__ata_end_request);
EXPORT_SYMBOL(ide_stall_queue); EXPORT_SYMBOL(ide_stall_queue);
EXPORT_SYMBOL(ide_setup_ports); EXPORT_SYMBOL(ide_setup_ports);
...@@ -430,7 +430,7 @@ void ide_unregister(struct ata_channel *ch) ...@@ -430,7 +430,7 @@ void ide_unregister(struct ata_channel *ch)
struct ata_device *drive = &ch->drives[i]; struct ata_device *drive = &ch->drives[i];
if (drive->de) { if (drive->de) {
devfs_unregister (drive->de); devfs_unregister(drive->de);
drive->de = NULL; drive->de = NULL;
} }
if (!drive->present) if (!drive->present)
...@@ -1246,7 +1246,7 @@ static int ata_sys_notify(struct notifier_block *this, unsigned long event, void ...@@ -1246,7 +1246,7 @@ static int ata_sys_notify(struct notifier_block *this, unsigned long event, void
return NOTIFY_DONE; return NOTIFY_DONE;
} }
printk("flushing ide devices: "); printk(KERN_INFO "flushing ATA/ATAPI devices: ");
for (i = 0; i < MAX_HWIFS; i++) { for (i = 0; i < MAX_HWIFS; i++) {
int unit; int unit;
...@@ -1264,9 +1264,10 @@ static int ata_sys_notify(struct notifier_block *this, unsigned long event, void ...@@ -1264,9 +1264,10 @@ static int ata_sys_notify(struct notifier_block *this, unsigned long event, void
/* set the drive to standby */ /* set the drive to standby */
printk("%s ", drive->name); printk("%s ", drive->name);
if (ata_ops(drive)) { if (ata_ops(drive)) {
if (event != SYS_RESTART) if (event != SYS_RESTART) {
if (ata_ops(drive)->standby && ata_ops(drive)->standby(drive)) if (ata_ops(drive)->standby && ata_ops(drive)->standby(drive))
continue; continue;
}
if (ata_ops(drive)->cleanup) if (ata_ops(drive)->cleanup)
ata_ops(drive)->cleanup(drive); ata_ops(drive)->cleanup(drive);
...@@ -1290,8 +1291,7 @@ static int __init ata_module_init(void) ...@@ -1290,8 +1291,7 @@ static int __init ata_module_init(void)
{ {
printk(KERN_INFO "ATA/ATAPI device driver v" VERSION "\n"); printk(KERN_INFO "ATA/ATAPI device driver v" VERSION "\n");
ide_devfs_handle = devfs_mk_dir(NULL, "ata", NULL); ide_devfs_handle = devfs_mk_dir(NULL, "ide", NULL);
devfs_mk_symlink(NULL, "ide", DEVFS_FL_DEFAULT, "ata", NULL, NULL);
/* /*
* Because most of the ATA adapters represent the timings in unit of * Because most of the ATA adapters represent the timings in unit of
......
...@@ -44,7 +44,17 @@ ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq) ...@@ -44,7 +44,17 @@ ide_startstop_t ide_dma_intr(struct ata_device *drive, struct request *rq)
if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) { if (ata_status(drive, DRIVE_READY, drive->bad_wstat | DRQ_STAT)) {
if (!dma_stat) { if (!dma_stat) {
__ide_end_request(drive, rq, 1, rq->nr_sectors); unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
__ata_end_request(drive, rq, 1, rq->nr_sectors);
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
} }
printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n", printk(KERN_ERR "%s: dma_intr: bad DMA status (dma_stat=%x)\n",
......
...@@ -247,7 +247,8 @@ int __init setup_pdc4030(struct ata_channel *hwif) ...@@ -247,7 +247,8 @@ int __init setup_pdc4030(struct ata_channel *hwif)
if (pdc4030_cmd(drive, PROMISE_GET_CONFIG)) { if (pdc4030_cmd(drive, PROMISE_GET_CONFIG)) {
return 0; return 0;
} }
if (ide_wait_stat(&startstop, drive, NULL, DATA_READY,BAD_W_STAT,WAIT_DRQ)) { if (ata_status_poll(drive, DATA_READY, BAD_W_STAT,
WAIT_DRQ, NULL, &startstop)) {
printk(KERN_INFO printk(KERN_INFO
"%s: Failed Promise read config!\n",hwif->name); "%s: Failed Promise read config!\n",hwif->name);
return 0; return 0;
...@@ -407,7 +408,8 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques ...@@ -407,7 +408,8 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques
rq->nr_sectors -= nsect; rq->nr_sectors -= nsect;
total_remaining = rq->nr_sectors; total_remaining = rq->nr_sectors;
if ((rq->current_nr_sectors -= nsect) <= 0) { if ((rq->current_nr_sectors -= nsect) <= 0) {
ide_end_request(drive, rq, 1); /* FIXME: no queue locking above! */
ata_end_request(drive, rq, 1);
} }
/* /*
...@@ -461,13 +463,11 @@ static ide_startstop_t promise_read_intr(struct ata_device *drive, struct reques ...@@ -461,13 +463,11 @@ 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) static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel; struct ata_channel *ch = drive->channel;
if (!ata_status(drive, 0, BUSY_STAT)) { if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) { if (time_before(jiffies, ch->poll_timeout)) {
unsigned long flags;
struct ata_channel *ch = drive->channel;
/* FIXME: this locking should encompass the above /* FIXME: this locking should encompass the above
* register file access too. * register file access too.
*/ */
...@@ -488,7 +488,13 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc ...@@ -488,7 +488,13 @@ static ide_startstop_t promise_complete_pollfunc(struct ata_device *drive, struc
#ifdef DEBUG_WRITE #ifdef DEBUG_WRITE
printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name); printk(KERN_DEBUG "%s: Write complete - end_request\n", drive->name);
#endif #endif
__ide_end_request(drive, rq, 1, rq->nr_sectors); /* FIXME: this locking should encompass the above
* register file access too.
*/
spin_lock_irqsave(ch->lock, flags);
__ata_end_request(drive, rq, 1, rq->nr_sectors);
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped; return ide_stopped;
} }
...@@ -653,7 +659,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg ...@@ -653,7 +659,7 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
/* Check that it's a regular command. If not, bomb out early. */ /* Check that it's a regular command. If not, bomb out early. */
if (!(rq->flags & REQ_CMD)) { if (!(rq->flags & REQ_CMD)) {
blk_dump_rq_flags(rq, "pdc4030 bad flags"); blk_dump_rq_flags(rq, "pdc4030 bad flags");
ide_end_request(drive, rq, 0); ata_end_request(drive, rq, 0);
return ide_stopped; return ide_stopped;
} }
...@@ -721,7 +727,8 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg ...@@ -721,7 +727,8 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
* call the promise_write function to deal with writing the data out * call the promise_write function to deal with writing the data out
* NOTE: No interrupts are generated on writes. Write completion must be polled * NOTE: No interrupts are generated on writes. Write completion must be polled
*/ */
if (ide_wait_stat(&startstop, drive, rq, DATA_READY, drive->bad_wstat, WAIT_DRQ)) { if (ata_status_poll(drive, DATA_READY, drive->bad_wstat,
WAIT_DRQ, rq, &startstop )) {
printk(KERN_ERR "%s: no DRQ after issuing " printk(KERN_ERR "%s: no DRQ after issuing "
"PROMISE_WRITE\n", drive->name); "PROMISE_WRITE\n", drive->name);
return startstop; return startstop;
...@@ -733,7 +740,8 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg ...@@ -733,7 +740,8 @@ ide_startstop_t do_pdc4030_io(struct ata_device *drive, struct ata_taskfile *arg
default: default:
printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n"); printk(KERN_ERR "pdc4030: command not READ or WRITE! Huh?\n");
ide_end_request(drive, rq, 0); /* FIXME: This should already run under the lock. */
ata_end_request(drive, rq, 0);
return ide_stopped; return ide_stopped;
} }
} }
......
...@@ -307,16 +307,7 @@ byte eighty_ninty_three(struct ata_device *drive) ...@@ -307,16 +307,7 @@ byte eighty_ninty_three(struct ata_device *drive)
(drive->id->hw_config & 0x6000)) ? 1 : 0); (drive->id->hw_config & 0x6000)) ? 1 : 0);
} }
/* /* FIXME: Channel lock should be held.
* Similar to ide_wait_stat(), except it never calls ata_error internally.
* This is a kludge to handle the new ide_config_drive_speed() function,
* and should not otherwise be used anywhere. Eventually, the tuneproc's
* should be updated to return ide_startstop_t, in which case we can get
* rid of this abomination again. :) -ml
*
* It is gone..........
*
* const char *msg == consider adding for verbose errors.
*/ */
int ide_config_drive_speed(struct ata_device *drive, byte speed) int ide_config_drive_speed(struct ata_device *drive, byte speed)
{ {
...@@ -329,12 +320,10 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed) ...@@ -329,12 +320,10 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed)
outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2); outb(inb(ch->dma_base + 2) & ~(1 << (5 + unit)), ch->dma_base + 2);
#endif #endif
/* /* Don't use ide_wait_cmd here - it will attempt to set_geometry and
* Don't use ide_wait_cmd here - it will attempt to set_geometry and
* recalibrate, but for some reason these don't work at this point * recalibrate, but for some reason these don't work at this point
* (lost interrupt). * (lost interrupt).
*/ *
/*
* Select the drive, and issue the SETFEATURES command * Select the drive, and issue the SETFEATURES command
*/ */
disable_irq(ch->irq); /* disable_irq_nosync ?? */ disable_irq(ch->irq); /* disable_irq_nosync ?? */
...@@ -350,20 +339,7 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed) ...@@ -350,20 +339,7 @@ int ide_config_drive_speed(struct ata_device *drive, byte speed)
ata_irq_enable(drive, 1); ata_irq_enable(drive, 1);
udelay(1); udelay(1);
/* ata_busy_poll(drive, WAIT_CMD);
* Wait for drive to become non-BUSY
*/
if (!ata_status(drive, 0, BUSY_STAT)) {
unsigned long flags, timeout;
__save_flags(flags); /* local CPU only */
ide__sti(); /* local CPU only -- for jiffies */
timeout = jiffies + WAIT_CMD;
while (!ata_status(drive, 0, BUSY_STAT)) {
if (time_after(jiffies, timeout))
break;
}
__restore_flags(flags); /* local CPU only */
}
/* /*
* Allow status to settle, then read it again. * Allow status to settle, then read it again.
......
...@@ -327,6 +327,8 @@ static ide_startstop_t check_service(struct ata_device *drive, struct request *r ...@@ -327,6 +327,8 @@ static ide_startstop_t check_service(struct ata_device *drive, struct request *r
static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *rq) static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *rq)
{ {
unsigned long flags;
struct ata_channel *ch = drive->channel;
u8 dma_stat; u8 dma_stat;
/* /*
...@@ -348,7 +350,14 @@ static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *r ...@@ -348,7 +350,14 @@ static ide_startstop_t dmaq_complete(struct ata_device *drive, struct request *r
printk("%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat); printk("%s: bad DMA status (dma_stat=%x)\n", drive->name, dma_stat);
TCQ_PRINTK("%s: ending %p, tag %d\n", __FUNCTION__, rq, rq->tag); TCQ_PRINTK("%s: ending %p, tag %d\n", __FUNCTION__, rq, rq->tag);
__ide_end_request(drive, rq, !dma_stat, rq->nr_sectors);
/* FIXME: this locking should encompass the above register
* file access too.
*/
spin_lock_irqsave(ch->lock, flags);
__ata_end_request(drive, rq, !dma_stat, rq->nr_sectors);
spin_unlock_irqrestore(ch->lock, flags);
/* /*
* we completed this command, check if we can service a new command * we completed this command, check if we can service a new command
......
...@@ -244,7 +244,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int ...@@ -244,7 +244,7 @@ static int idescsi_end_request(struct ata_device *drive, struct request *rq, int
unsigned long flags; unsigned long flags;
if (!(rq->flags & REQ_PC)) { if (!(rq->flags & REQ_PC)) {
ide_end_request(drive, rq, uptodate); ata_end_request(drive, rq, uptodate);
return 0; return 0;
} }
...@@ -399,29 +399,33 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct requ ...@@ -399,29 +399,33 @@ static ide_startstop_t idescsi_transfer_pc(struct ata_device *drive, struct requ
struct Scsi_Host *host = drive->driver_data; struct Scsi_Host *host = drive->driver_data;
idescsi_scsi_t *scsi = idescsi_private(host); idescsi_scsi_t *scsi = idescsi_private(host);
struct atapi_packet_command *pc = scsi->pc; struct atapi_packet_command *pc = scsi->pc;
byte ireason; u8 ireason;
ide_startstop_t startstop; ide_startstop_t startstop;
int ret;
if (ide_wait_stat(&startstop, drive, rq, DRQ_STAT, BUSY_STAT, WAIT_READY)) { if (ata_status_poll(drive, DRQ_STAT, BUSY_STAT,
WAIT_READY, rq, &startstop)) {
printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n"); printk (KERN_ERR "ide-scsi: Strange, packet command initiated yet DRQ isn't asserted\n");
return startstop; return startstop;
} }
ireason = IN_BYTE (IDE_IREASON_REG);
if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) {
printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n");
return ide_stopped;
}
/* FIXME: this locking should encompass the above register /* FIXME: this locking should encompass the above register
* file access too. * file access too.
*/ */
spin_lock_irqsave(ch->lock, flags); spin_lock_irqsave(ch->lock, flags);
ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL); /* Set the interrupt routine */ ireason = IN_BYTE(IDE_IREASON_REG);
if ((ireason & (IDESCSI_IREASON_IO | IDESCSI_IREASON_COD)) != IDESCSI_IREASON_COD) {
printk (KERN_ERR "ide-scsi: (IO,CoD) != (0,1) while issuing a packet command\n");
ret = ide_stopped;
} else {
ata_set_handler(drive, idescsi_pc_intr, get_timeout(pc), NULL);
atapi_write(drive, scsi->pc->c, 12);
ret = ide_started;
}
spin_unlock_irqrestore(ch->lock, flags); spin_unlock_irqrestore(ch->lock, flags);
atapi_write(drive, scsi->pc->c, 12); /* Send the actual packet */ return ret;
return ide_started;
} }
/* /*
......
...@@ -601,8 +601,9 @@ extern int noautodma; ...@@ -601,8 +601,9 @@ extern int noautodma;
#define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */ #define LOCAL_END_REQUEST /* Don't generate end_request in blk.h */
#include <linux/blk.h> #include <linux/blk.h>
extern int __ide_end_request(struct ata_device *, struct request *, int, unsigned int); /* Not locking and locking variant: */
extern int ide_end_request(struct ata_device *drive, struct request *, int); extern int __ata_end_request(struct ata_device *, struct request *, int, unsigned int);
extern int ata_end_request(struct ata_device *drive, struct request *, int);
extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler, extern void ata_set_handler(struct ata_device *drive, ata_handler_t handler,
unsigned long timeout, ata_expiry_t expiry); unsigned long timeout, ata_expiry_t expiry);
...@@ -611,11 +612,6 @@ extern u8 ata_dump(struct ata_device *, struct request *, const char *); ...@@ -611,11 +612,6 @@ extern u8 ata_dump(struct ata_device *, struct request *, const char *);
extern ide_startstop_t ata_error(struct ata_device *, struct request *rq, const char *); extern ide_startstop_t ata_error(struct ata_device *, struct request *rq, const char *);
extern void ide_fixstring(char *s, const int bytecount, const int byteswap); extern void ide_fixstring(char *s, const int bytecount, const int byteswap);
extern int ide_wait_stat(ide_startstop_t *,
struct ata_device *, struct request *rq,
byte, byte, unsigned long);
extern int ide_wait_noerr(struct ata_device *, byte, byte, unsigned long); extern int ide_wait_noerr(struct ata_device *, byte, byte, unsigned long);
/* /*
...@@ -831,7 +827,11 @@ extern int drive_is_ready(struct ata_device *drive); ...@@ -831,7 +827,11 @@ extern int drive_is_ready(struct ata_device *drive);
extern void ata_select(struct ata_device *, unsigned long); extern void ata_select(struct ata_device *, unsigned long);
extern void ata_mask(struct ata_device *); extern void ata_mask(struct ata_device *);
extern int ata_busy_poll(struct ata_device *, unsigned long);
extern int ata_status(struct ata_device *, u8, u8); extern int ata_status(struct ata_device *, u8, u8);
extern int ata_status_poll( struct ata_device *, u8, u8,
unsigned long, struct request *rq, ide_startstop_t *);
extern int ata_irq_enable(struct ata_device *, int); extern int ata_irq_enable(struct ata_device *, int);
extern void ata_reset(struct ata_channel *); extern void ata_reset(struct ata_channel *);
extern void ata_out_regfile(struct ata_device *, struct hd_drive_task_hdr *); extern void ata_out_regfile(struct ata_device *, struct hd_drive_task_hdr *);
......
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