summaryrefslogtreecommitdiff
path: root/drivers/ide
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/ide')
-rw-r--r--drivers/ide/ide-cd.c120
-rw-r--r--drivers/ide/ide-disk.c2
-rw-r--r--drivers/ide/ide-floppy.c2
-rw-r--r--drivers/ide/ide-io.c61
-rw-r--r--drivers/ide/ide-lib.c4
-rw-r--r--drivers/ide/ide-tape.c49
-rw-r--r--drivers/ide/ide-timing.h8
-rw-r--r--drivers/ide/pci/pdc202xx_old.c40
-rw-r--r--drivers/ide/pci/piix.c12
9 files changed, 206 insertions, 92 deletions
diff --git a/drivers/ide/ide-cd.c b/drivers/ide/ide-cd.c
index 6de3cd3d6e8e..99fa42402e71 100644
--- a/drivers/ide/ide-cd.c
+++ b/drivers/ide/ide-cd.c
@@ -395,7 +395,8 @@ static int cdrom_log_sense(ide_drive_t *drive, struct request *rq,
* we cannot reliably check if drive can auto-close
*/
if (rq->cmd[0] == GPCMD_START_STOP_UNIT && sense->asc == 0x24)
- log = 0;
+ break;
+ log = 1;
break;
case UNIT_ATTENTION:
/*
@@ -417,6 +418,11 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
struct request *failed_command,
struct request_sense *sense)
{
+ unsigned long sector;
+ unsigned long bio_sectors;
+ unsigned long valid;
+ struct cdrom_info *info = drive->driver_data;
+
if (!cdrom_log_sense(drive, failed_command, sense))
return;
@@ -429,6 +435,37 @@ void cdrom_analyze_sense_data(ide_drive_t *drive,
if (sense->sense_key == 0x05 && sense->asc == 0x24)
return;
+ if (sense->error_code == 0x70) { /* Current Error */
+ switch(sense->sense_key) {
+ case MEDIUM_ERROR:
+ case VOLUME_OVERFLOW:
+ case ILLEGAL_REQUEST:
+ if (!sense->valid)
+ break;
+ if (failed_command == NULL ||
+ !blk_fs_request(failed_command))
+ break;
+ sector = (sense->information[0] << 24) |
+ (sense->information[1] << 16) |
+ (sense->information[2] << 8) |
+ (sense->information[3]);
+
+ bio_sectors = bio_sectors(failed_command->bio);
+ if (bio_sectors < 4)
+ bio_sectors = 4;
+ if (drive->queue->hardsect_size == 2048)
+ sector <<= 2; /* Device sector size is 2K */
+ sector &= ~(bio_sectors -1);
+ valid = (sector - failed_command->sector) << 9;
+
+ if (valid < 0)
+ valid = 0;
+ if (sector < get_capacity(info->disk) &&
+ drive->probed_capacity - sector < 4 * 75) {
+ set_capacity(info->disk, sector);
+ }
+ }
+ }
#if VERBOSE_IDE_CD_ERRORS
{
int i;
@@ -609,17 +646,23 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
sense = failed->sense;
failed->sense_len = rq->sense_len;
}
-
+ cdrom_analyze_sense_data(drive, failed, sense);
/*
* now end failed request
*/
- spin_lock_irqsave(&ide_lock, flags);
- end_that_request_chunk(failed, 0, failed->data_len);
- end_that_request_last(failed, 0);
- spin_unlock_irqrestore(&ide_lock, flags);
- }
-
- cdrom_analyze_sense_data(drive, failed, sense);
+ if (blk_fs_request(failed)) {
+ if (ide_end_dequeued_request(drive, failed, 0,
+ failed->hard_nr_sectors))
+ BUG();
+ } else {
+ spin_lock_irqsave(&ide_lock, flags);
+ end_that_request_chunk(failed, 0,
+ failed->data_len);
+ end_that_request_last(failed, 0);
+ spin_unlock_irqrestore(&ide_lock, flags);
+ }
+ } else
+ cdrom_analyze_sense_data(drive, NULL, sense);
}
if (!rq->current_nr_sectors && blk_fs_request(rq))
@@ -633,6 +676,13 @@ static void cdrom_end_request (ide_drive_t *drive, int uptodate)
ide_end_request(drive, uptodate, nsectors);
}
+static void ide_dump_status_no_sense(ide_drive_t *drive, const char *msg, u8 stat)
+{
+ if (stat & 0x80)
+ return;
+ ide_dump_status(drive, msg, stat);
+}
+
/* Returns 0 if the request should be continued.
Returns 1 if the request was ended. */
static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
@@ -761,16 +811,16 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
sense_key == DATA_PROTECT) {
/* No point in retrying after an illegal
request or data protect error.*/
- ide_dump_status (drive, "command error", stat);
+ ide_dump_status_no_sense (drive, "command error", stat);
do_end_request = 1;
} else if (sense_key == MEDIUM_ERROR) {
/* No point in re-trying a zillion times on a bad
* sector... If we got here the error is not correctable */
- ide_dump_status (drive, "media error (bad sector)", stat);
+ ide_dump_status_no_sense (drive, "media error (bad sector)", stat);
do_end_request = 1;
} else if (sense_key == BLANK_CHECK) {
/* Disk appears blank ?? */
- ide_dump_status (drive, "media error (blank)", stat);
+ ide_dump_status_no_sense (drive, "media error (blank)", stat);
do_end_request = 1;
} else if ((err & ~ABRT_ERR) != 0) {
/* Go to the default handler
@@ -782,13 +832,27 @@ static int cdrom_decode_status(ide_drive_t *drive, int good_stat, int *stat_ret)
do_end_request = 1;
}
- if (do_end_request)
- cdrom_end_request(drive, 0);
-
- /* If we got a CHECK_CONDITION status,
- queue a request sense command. */
- if ((stat & ERR_STAT) != 0)
- cdrom_queue_request_sense(drive, NULL, NULL);
+ /* End a request through request sense analysis when we have
+ sense data. We need this in order to perform end of media
+ processing */
+
+ if (do_end_request) {
+ if (stat & ERR_STAT) {
+ unsigned long flags;
+ spin_lock_irqsave(&ide_lock, flags);
+ blkdev_dequeue_request(rq);
+ HWGROUP(drive)->rq = NULL;
+ spin_unlock_irqrestore(&ide_lock, flags);
+
+ cdrom_queue_request_sense(drive, rq->sense, rq);
+ } else
+ cdrom_end_request(drive, 0);
+ } else {
+ /* If we got a CHECK_CONDITION status,
+ queue a request sense command. */
+ if (stat & ERR_STAT)
+ cdrom_queue_request_sense(drive, NULL, NULL);
+ }
} else {
blk_dump_rq_flags(rq, "ide-cd: bad rq");
cdrom_end_request(drive, 0);
@@ -1491,8 +1555,7 @@ static ide_startstop_t cdrom_do_packet_command (ide_drive_t *drive)
}
-static
-int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
+static int cdrom_queue_packet_command(ide_drive_t *drive, struct request *rq)
{
struct request_sense sense;
int retries = 10;
@@ -2220,6 +2283,9 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
toc->capacity = 0x1fffff;
set_capacity(info->disk, toc->capacity * sectors_per_frame);
+ /* Save a private copy of te TOC capacity for error handling */
+ drive->probed_capacity = toc->capacity * sectors_per_frame;
+
blk_queue_hardsect_size(drive->queue,
sectors_per_frame << SECTOR_BITS);
@@ -2342,6 +2408,7 @@ static int cdrom_read_toc(ide_drive_t *drive, struct request_sense *sense)
if (!stat && (last_written > toc->capacity)) {
toc->capacity = last_written;
set_capacity(info->disk, toc->capacity * sectors_per_frame);
+ drive->probed_capacity = toc->capacity * sectors_per_frame;
}
/* Remember that we've read this stuff. */
@@ -2698,14 +2765,11 @@ int ide_cdrom_drive_status (struct cdrom_device_info *cdi, int slot_nr)
* any other way to detect this...
*/
if (sense.sense_key == NOT_READY) {
- if (sense.asc == 0x3a) {
- if (sense.ascq == 1)
- return CDS_NO_DISC;
- else if (sense.ascq == 0 || sense.ascq == 2)
- return CDS_TRAY_OPEN;
- }
+ if (sense.asc == 0x3a && sense.ascq == 1)
+ return CDS_NO_DISC;
+ else
+ return CDS_TRAY_OPEN;
}
-
return CDS_DRIVE_NOT_READY;
}
diff --git a/drivers/ide/ide-disk.c b/drivers/ide/ide-disk.c
index a5017de72da5..f033d732f387 100644
--- a/drivers/ide/ide-disk.c
+++ b/drivers/ide/ide-disk.c
@@ -37,7 +37,7 @@
* Version 1.15 convert all calls to ide_raw_taskfile
* since args will return register content.
* Version 1.16 added suspend-resume-checkpower
- * Version 1.17 do flush on standy, do flush on ATA < ATA6
+ * Version 1.17 do flush on standby, do flush on ATA < ATA6
* fix wcache setup.
*/
diff --git a/drivers/ide/ide-floppy.c b/drivers/ide/ide-floppy.c
index a1179e924962..4656587aa2f7 100644
--- a/drivers/ide/ide-floppy.c
+++ b/drivers/ide/ide-floppy.c
@@ -1284,7 +1284,7 @@ static ide_startstop_t idefloppy_do_request (ide_drive_t *drive, struct request
debug_log(KERN_INFO "rq_status: %d, dev: %s, flags: %lx, errors: %d\n",
rq->rq_status,
- rq->rq_disk ? rq->rq_disk->disk_name ? "?",
+ rq->rq_disk ? rq->rq_disk->disk_name : "?",
rq->flags, rq->errors);
debug_log(KERN_INFO "sector: %ld, nr_sectors: %ld, "
"current_nr_sectors: %d\n", (long)rq->sector,
diff --git a/drivers/ide/ide-io.c b/drivers/ide/ide-io.c
index 4f2f138de2ca..935cb2583770 100644
--- a/drivers/ide/ide-io.c
+++ b/drivers/ide/ide-io.c
@@ -223,6 +223,63 @@ static ide_startstop_t ide_start_power_step(ide_drive_t *drive, struct request *
}
/**
+ * ide_end_dequeued_request - complete an IDE I/O
+ * @drive: IDE device for the I/O
+ * @uptodate:
+ * @nr_sectors: number of sectors completed
+ *
+ * Complete an I/O that is no longer on the request queue. This
+ * typically occurs when we pull the request and issue a REQUEST_SENSE.
+ * We must still finish the old request but we must not tamper with the
+ * queue in the meantime.
+ *
+ * NOTE: This path does not handle barrier, but barrier is not supported
+ * on ide-cd anyway.
+ */
+
+int ide_end_dequeued_request(ide_drive_t *drive, struct request *rq,
+ int uptodate, int nr_sectors)
+{
+ unsigned long flags;
+ int ret = 1;
+
+ spin_lock_irqsave(&ide_lock, flags);
+
+ BUG_ON(!(rq->flags & REQ_STARTED));
+
+ /*
+ * if failfast is set on a request, override number of sectors and
+ * complete the whole request right now
+ */
+ if (blk_noretry_request(rq) && end_io_error(uptodate))
+ nr_sectors = rq->hard_nr_sectors;
+
+ if (!blk_fs_request(rq) && end_io_error(uptodate) && !rq->errors)
+ rq->errors = -EIO;
+
+ /*
+ * 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 (drive->state == DMA_PIO_RETRY && drive->retry_pio <= 3) {
+ drive->state = 0;
+ HWGROUP(drive)->hwif->ide_dma_on(drive);
+ }
+
+ if (!end_that_request_first(rq, uptodate, nr_sectors)) {
+ add_disk_randomness(rq->rq_disk);
+ if (blk_rq_tagged(rq))
+ blk_queue_end_tag(drive->queue, rq);
+ end_that_request_last(rq, uptodate);
+ ret = 0;
+ }
+ spin_unlock_irqrestore(&ide_lock, flags);
+ return ret;
+}
+EXPORT_SYMBOL_GPL(ide_end_dequeued_request);
+
+
+/**
* ide_complete_pm_request - end the current Power Management request
* @drive: target drive
* @rq: request
@@ -902,7 +959,7 @@ static void ide_check_pm_state(ide_drive_t *drive, struct request *rq)
printk(KERN_WARNING "%s: bus not ready on wakeup\n", drive->name);
SELECT_DRIVE(drive);
HWIF(drive)->OUTB(8, HWIF(drive)->io_ports[IDE_CONTROL_OFFSET]);
- rc = ide_wait_not_busy(HWIF(drive), 10000);
+ rc = ide_wait_not_busy(HWIF(drive), 100000);
if (rc)
printk(KERN_WARNING "%s: drive not ready on wakeup\n", drive->name);
}
@@ -1608,7 +1665,7 @@ irqreturn_t ide_intr (int irq, void *dev_id, struct pt_regs *regs)
* Initialize a request before we fill it in and send it down to
* ide_do_drive_cmd. Commands must be set up by this function. Right
* now it doesn't do a lot, but if that changes abusers will have a
- * nasty suprise.
+ * nasty surprise.
*/
void ide_init_drive_cmd (struct request *rq)
diff --git a/drivers/ide/ide-lib.c b/drivers/ide/ide-lib.c
index 16a143133f93..7ddb11828731 100644
--- a/drivers/ide/ide-lib.c
+++ b/drivers/ide/ide-lib.c
@@ -485,7 +485,7 @@ static u8 ide_dump_ata_status(ide_drive_t *drive, const char *msg, u8 stat)
unsigned long flags;
u8 err = 0;
- local_irq_set(flags);
+ local_irq_save(flags);
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
if (stat & BUSY_STAT)
printk("Busy ");
@@ -567,7 +567,7 @@ static u8 ide_dump_atapi_status(ide_drive_t *drive, const char *msg, u8 stat)
status.all = stat;
error.all = 0;
- local_irq_set(flags);
+ local_irq_save(flags);
printk("%s: %s: status=0x%02x { ", drive->name, msg, stat);
if (status.b.bsy)
printk("Busy ");
diff --git a/drivers/ide/ide-tape.c b/drivers/ide/ide-tape.c
index f04791a58df0..09f3a7dab28a 100644
--- a/drivers/ide/ide-tape.c
+++ b/drivers/ide/ide-tape.c
@@ -2646,21 +2646,23 @@ static idetape_stage_t *idetape_kmalloc_stage (idetape_tape_t *tape)
return __idetape_kmalloc_stage(tape, 0, 0);
}
-static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
+static int idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t *stage, const char __user *buf, int n)
{
struct idetape_bh *bh = tape->bh;
int count;
+ int ret = 0;
while (n) {
#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_from_user\n");
- return;
+ return 1;
}
#endif /* IDETAPE_DEBUG_BUGS */
count = min((unsigned int)(bh->b_size - atomic_read(&bh->b_count)), (unsigned int)n);
- copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count);
+ if (copy_from_user(bh->b_data + atomic_read(&bh->b_count), buf, count))
+ ret = 1;
n -= count;
atomic_add(count, &bh->b_count);
buf += count;
@@ -2671,23 +2673,26 @@ static void idetape_copy_stage_from_user (idetape_tape_t *tape, idetape_stage_t
}
}
tape->bh = bh;
+ return ret;
}
-static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
+static int idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf, idetape_stage_t *stage, int n)
{
struct idetape_bh *bh = tape->bh;
int count;
+ int ret = 0;
while (n) {
#if IDETAPE_DEBUG_BUGS
if (bh == NULL) {
printk(KERN_ERR "ide-tape: bh == NULL in "
"idetape_copy_stage_to_user\n");
- return;
+ return 1;
}
#endif /* IDETAPE_DEBUG_BUGS */
count = min(tape->b_count, n);
- copy_to_user(buf, tape->b_data, count);
+ if (copy_to_user(buf, tape->b_data, count))
+ ret = 1;
n -= count;
tape->b_data += count;
tape->b_count -= count;
@@ -2700,6 +2705,7 @@ static void idetape_copy_stage_to_user (idetape_tape_t *tape, char __user *buf,
}
}
}
+ return ret;
}
static void idetape_init_merge_stage (idetape_tape_t *tape)
@@ -3719,6 +3725,7 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
struct ide_tape_obj *tape = ide_tape_f(file);
ide_drive_t *drive = tape->drive;
ssize_t bytes_read,temp, actually_read = 0, rc;
+ ssize_t ret = 0;
#if IDETAPE_DEBUG_LOG
if (tape->debug_level >= 3)
@@ -3737,7 +3744,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
return (0);
if (tape->merge_stage_size) {
actually_read = min((unsigned int)(tape->merge_stage_size), (unsigned int)count);
- idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read);
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, actually_read))
+ ret = -EFAULT;
buf += actually_read;
tape->merge_stage_size -= actually_read;
count -= actually_read;
@@ -3746,7 +3754,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
bytes_read = idetape_add_chrdev_read_request(drive, tape->capabilities.ctl);
if (bytes_read <= 0)
goto finish;
- idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read);
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, bytes_read))
+ ret = -EFAULT;
buf += bytes_read;
count -= bytes_read;
actually_read += bytes_read;
@@ -3756,7 +3765,8 @@ static ssize_t idetape_chrdev_read (struct file *file, char __user *buf,
if (bytes_read <= 0)
goto finish;
temp = min((unsigned long)count, (unsigned long)bytes_read);
- idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp);
+ if (idetape_copy_stage_to_user(tape, buf, tape->merge_stage, temp))
+ ret = -EFAULT;
actually_read += temp;
tape->merge_stage_size = bytes_read-temp;
}
@@ -3769,7 +3779,8 @@ finish:
idetape_space_over_filemarks(drive, MTFSF, 1);
return 0;
}
- return actually_read;
+
+ return (ret) ? ret : actually_read;
}
static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
@@ -3777,7 +3788,8 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
{
struct ide_tape_obj *tape = ide_tape_f(file);
ide_drive_t *drive = tape->drive;
- ssize_t retval, actually_written = 0;
+ ssize_t actually_written = 0;
+ ssize_t ret = 0;
/* The drive is write protected. */
if (tape->write_prot)
@@ -3813,7 +3825,7 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
* some drives (Seagate STT3401A) will return an error.
*/
if (drive->dsc_overlap) {
- retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
+ ssize_t retval = idetape_queue_rw_tail(drive, REQ_IDETAPE_WRITE, 0, tape->merge_stage->bh);
if (retval < 0) {
__idetape_kfree_stage(tape->merge_stage);
tape->merge_stage = NULL;
@@ -3834,12 +3846,14 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
}
#endif /* IDETAPE_DEBUG_BUGS */
actually_written = min((unsigned int)(tape->stage_size - tape->merge_stage_size), (unsigned int)count);
- idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written);
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, actually_written))
+ ret = -EFAULT;
buf += actually_written;
tape->merge_stage_size += actually_written;
count -= actually_written;
if (tape->merge_stage_size == tape->stage_size) {
+ ssize_t retval;
tape->merge_stage_size = 0;
retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
if (retval <= 0)
@@ -3847,7 +3861,9 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
}
}
while (count >= tape->stage_size) {
- idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size);
+ ssize_t retval;
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, tape->stage_size))
+ ret = -EFAULT;
buf += tape->stage_size;
count -= tape->stage_size;
retval = idetape_add_chrdev_write_request(drive, tape->capabilities.ctl);
@@ -3857,10 +3873,11 @@ static ssize_t idetape_chrdev_write (struct file *file, const char __user *buf,
}
if (count) {
actually_written += count;
- idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count);
+ if (idetape_copy_stage_from_user(tape, tape->merge_stage, buf, count))
+ ret = -EFAULT;
tape->merge_stage_size += count;
}
- return (actually_written);
+ return (ret) ? ret : actually_written;
}
static int idetape_write_filemark (ide_drive_t *drive)
diff --git a/drivers/ide/ide-timing.h b/drivers/ide/ide-timing.h
index 2fcfac6e967a..c0864b1e9228 100644
--- a/drivers/ide/ide-timing.h
+++ b/drivers/ide/ide-timing.h
@@ -220,6 +220,12 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
return -EINVAL;
/*
+ * Copy the timing from the table.
+ */
+
+ *t = *s;
+
+/*
* If the drive is an EIDE drive, it can tell us it needs extended
* PIO/MWDMA cycle timing.
*/
@@ -247,7 +253,7 @@ static int ide_timing_compute(ide_drive_t *drive, short speed, struct ide_timing
* Convert the timing to bus clock counts.
*/
- ide_timing_quantize(s, t, T, UT);
+ ide_timing_quantize(t, t, T, UT);
/*
* Even in DMA/UDMA modes we still use PIO access for IDENTIFY, S.M.A.R.T
diff --git a/drivers/ide/pci/pdc202xx_old.c b/drivers/ide/pci/pdc202xx_old.c
index 7ce5bf783688..22d17548ecdb 100644
--- a/drivers/ide/pci/pdc202xx_old.c
+++ b/drivers/ide/pci/pdc202xx_old.c
@@ -370,7 +370,6 @@ chipset_is_set:
if (!(speed)) {
/* restore original pci-config space */
pci_write_config_dword(dev, drive_pci, drive_conf);
- hwif->tuneproc(drive, 5);
return 0;
}
@@ -415,8 +414,6 @@ static void pdc202xx_old_ide_dma_start(ide_drive_t *drive)
if (drive->addressing == 1) {
struct request *rq = HWGROUP(drive)->rq;
ide_hwif_t *hwif = HWIF(drive);
-// struct pci_dev *dev = hwif->pci_dev;
-// unsgned long high_16 = pci_resource_start(dev, 4);
unsigned long high_16 = hwif->dma_master;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u32 word_count = 0;
@@ -436,7 +433,6 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
{
if (drive->addressing == 1) {
ide_hwif_t *hwif = HWIF(drive);
-// unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4);
unsigned long high_16 = hwif->dma_master;
unsigned long atapi_reg = high_16 + (hwif->channel ? 0x24 : 0x20);
u8 clock = 0;
@@ -453,8 +449,6 @@ static int pdc202xx_old_ide_dma_end(ide_drive_t *drive)
static int pdc202xx_old_ide_dma_test_irq(ide_drive_t *drive)
{
ide_hwif_t *hwif = HWIF(drive);
-// struct pci_dev *dev = hwif->pci_dev;
-// unsigned long high_16 = pci_resource_start(dev, 4);
unsigned long high_16 = hwif->dma_master;
u8 dma_stat = hwif->INB(hwif->dma_status);
u8 sc1d = hwif->INB((high_16 + 0x001d));
@@ -492,12 +486,7 @@ static int pdc202xx_ide_dma_timeout(ide_drive_t *drive)
static void pdc202xx_reset_host (ide_hwif_t *hwif)
{
-#ifdef CONFIG_BLK_DEV_IDEDMA
-// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel));
unsigned long high_16 = hwif->dma_master;
-#else /* !CONFIG_BLK_DEV_IDEDMA */
- unsigned long high_16 = pci_resource_start(hwif->pci_dev, 4);
-#endif /* CONFIG_BLK_DEV_IDEDMA */
u8 udma_speed_flag = hwif->INB(high_16|0x001f);
hwif->OUTB((udma_speed_flag | 0x10), (high_16|0x001f));
@@ -550,31 +539,6 @@ static void pdc202xx_reset (ide_drive_t *drive)
#endif
}
-/*
- * Since SUN Cobalt is attempting to do this operation, I should disclose
- * this has been a long time ago Thu Jul 27 16:40:57 2000 was the patch date
- * HOTSWAP ATA Infrastructure.
- */
-static int pdc202xx_tristate (ide_drive_t * drive, int state)
-{
- ide_hwif_t *hwif = HWIF(drive);
-// unsigned long high_16 = hwif->dma_base - (8*(hwif->channel));
- unsigned long high_16 = hwif->dma_master;
- u8 sc1f = hwif->INB(high_16|0x001f);
-
- if (!hwif)
- return -EINVAL;
-
-// hwif->bus_state = state;
-
- if (state) {
- hwif->OUTB(sc1f | 0x08, (high_16|0x001f));
- } else {
- hwif->OUTB(sc1f & ~0x08, (high_16|0x001f));
- }
- return 0;
-}
-
static unsigned int __devinit init_chipset_pdc202xx(struct pci_dev *dev, const char *name)
{
if (dev->resource[PCI_ROM_RESOURCE].start) {
@@ -624,10 +588,8 @@ static void __devinit init_hwif_pdc202xx(ide_hwif_t *hwif)
hwif->tuneproc = &config_chipset_for_pio;
hwif->quirkproc = &pdc202xx_quirkproc;
- if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246) {
- hwif->busproc = &pdc202xx_tristate;
+ if (hwif->pci_dev->device != PCI_DEVICE_ID_PROMISE_20246)
hwif->resetproc = &pdc202xx_reset;
- }
hwif->speedproc = &pdc202xx_tune_chipset;
diff --git a/drivers/ide/pci/piix.c b/drivers/ide/pci/piix.c
index e9b83e1a3028..7fac6f57b5d6 100644
--- a/drivers/ide/pci/piix.c
+++ b/drivers/ide/pci/piix.c
@@ -222,6 +222,8 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
unsigned long flags;
u16 master_data;
u8 slave_data;
+ static DEFINE_SPINLOCK(tune_lock);
+
/* ISP RTC */
u8 timings[][2] = { { 0, 0 },
{ 0, 0 },
@@ -230,7 +232,13 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
{ 2, 3 }, };
pio = ide_get_best_pio_mode(drive, pio, 5, NULL);
- spin_lock_irqsave(&ide_lock, flags);
+
+ /*
+ * Master vs slave is synchronized above us but the slave register is
+ * shared by the two hwifs so the corner case of two slave timeouts in
+ * parallel must be locked.
+ */
+ spin_lock_irqsave(&tune_lock, flags);
pci_read_config_word(dev, master_port, &master_data);
if (is_slave) {
master_data = master_data | 0x4000;
@@ -250,7 +258,7 @@ static void piix_tune_drive (ide_drive_t *drive, u8 pio)
pci_write_config_word(dev, master_port, master_data);
if (is_slave)
pci_write_config_byte(dev, slave_port, slave_data);
- spin_unlock_irqrestore(&ide_lock, flags);
+ spin_unlock_irqrestore(&tune_lock, flags);
}
/**