git.openpandora.org
/
pandora-kernel.git
/ blobdiff
commit
grep
author
committer
pickaxe
?
search:
re
summary
|
shortlog
|
log
|
commit
|
commitdiff
|
tree
raw
|
inline
| side by side
IDE: Report errors during drive reset back to user space
[pandora-kernel.git]
/
drivers
/
ide
/
ide-iops.c
diff --git
a/drivers/ide/ide-iops.c
b/drivers/ide/ide-iops.c
index
57d9a9a
..
44aaec2
100644
(file)
--- a/
drivers/ide/ide-iops.c
+++ b/
drivers/ide/ide-iops.c
@@
-42,7
+42,7
@@
static void ide_outb (u8 val, unsigned long port)
outb(val, port);
}
outb(val, port);
}
-static void ide_outbsync
(ide_drive_t *drive
, u8 addr, unsigned long port)
+static void ide_outbsync
(ide_hwif_t *hwif
, u8 addr, unsigned long port)
{
outb(addr, port);
}
{
outb(addr, port);
}
@@
-68,7
+68,7
@@
static void ide_mm_outb (u8 value, unsigned long port)
writeb(value, (void __iomem *) port);
}
writeb(value, (void __iomem *) port);
}
-static void ide_mm_outbsync
(ide_drive_t *drive
, u8 value, unsigned long port)
+static void ide_mm_outbsync
(ide_hwif_t *hwif
, u8 value, unsigned long port)
{
writeb(value, (void __iomem *) port);
}
{
writeb(value, (void __iomem *) port);
}
@@
-95,7
+95,7
@@
void SELECT_DRIVE (ide_drive_t *drive)
hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
}
hwif->OUTB(drive->select.all, hwif->io_ports.device_addr);
}
-void SELECT_MASK
(ide_drive_t *drive, int mask)
+void SELECT_MASK(ide_drive_t *drive, int mask)
{
const struct ide_port_ops *port_ops = drive->hwif->port_ops;
{
const struct ide_port_ops *port_ops = drive->hwif->port_ops;
@@
-120,11
+120,6
@@
static void ide_tf_load(ide_drive_t *drive, ide_task_t *task)
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
if (task->tf_flags & IDE_TFLAG_FLAGGED)
HIHI = 0xFF;
- ide_set_irq(drive, 1);
-
- if ((task->tf_flags & IDE_TFLAG_NO_SELECT_MASK) == 0)
- SELECT_MASK(drive, 0);
-
if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
u16 data = (tf->hob_data << 8) | tf->data;
if (task->tf_flags & IDE_TFLAG_OUT_DATA) {
u16 data = (tf->hob_data << 8) | tf->data;
@@
-191,7
+186,7
@@
static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
}
/* be sure we're looking at the low order bits */
}
/* be sure we're looking at the low order bits */
- tf_outb(
drive->ctl
& ~0x80, io_ports->ctl_addr);
+ tf_outb(
ATA_DEVCTL_OBS
& ~0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = tf_inb(io_ports->nsect_addr);
if (task->tf_flags & IDE_TFLAG_IN_NSECT)
tf->nsect = tf_inb(io_ports->nsect_addr);
@@
-205,7
+200,7
@@
static void ide_tf_read(ide_drive_t *drive, ide_task_t *task)
tf->device = tf_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
tf->device = tf_inb(io_ports->device_addr);
if (task->tf_flags & IDE_TFLAG_LBA48) {
- tf_outb(
drive->ctl
| 0x80, io_ports->ctl_addr);
+ tf_outb(
ATA_DEVCTL_OBS
| 0x80, io_ports->ctl_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = tf_inb(io_ports->feature_addr);
if (task->tf_flags & IDE_TFLAG_IN_HOB_FEATURE)
tf->hob_feature = tf_inb(io_ports->feature_addr);
@@
-689,9
+684,9
@@
int ide_driveid_update(ide_drive_t *drive)
*/
SELECT_MASK(drive, 1);
*/
SELECT_MASK(drive, 1);
- ide_set_irq(drive,
1
);
+ ide_set_irq(drive,
0
);
msleep(50);
msleep(50);
- hwif->OUTBSYNC(
drive
, WIN_IDENTIFY, hwif->io_ports.command_addr);
+ hwif->OUTBSYNC(
hwif
, WIN_IDENTIFY, hwif->io_ports.command_addr);
timeout = jiffies + WAIT_WORSTCASE;
do {
if (time_after(jiffies, timeout)) {
timeout = jiffies + WAIT_WORSTCASE;
do {
if (time_after(jiffies, timeout)) {
@@
-744,9
+739,6
@@
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
int error = 0;
u8 stat;
int error = 0;
u8 stat;
-// while (HWGROUP(drive)->busy)
-// msleep(50);
-
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_ops) /* check if host supports DMA */
hwif->dma_ops->dma_host_set(drive, 0);
#ifdef CONFIG_BLK_DEV_IDEDMA
if (hwif->dma_ops) /* check if host supports DMA */
hwif->dma_ops->dma_host_set(drive, 0);
@@
-781,7
+773,7
@@
int ide_config_drive_speed(ide_drive_t *drive, u8 speed)
ide_set_irq(drive, 0);
hwif->OUTB(speed, io_ports->nsect_addr);
hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
ide_set_irq(drive, 0);
hwif->OUTB(speed, io_ports->nsect_addr);
hwif->OUTB(SETFEATURES_XFER, io_ports->feature_addr);
- hwif->OUTBSYNC(
drive
, WIN_SETFEATURES, io_ports->command_addr);
+ hwif->OUTBSYNC(
hwif
, WIN_SETFEATURES, io_ports->command_addr);
if (drive->quirk_list == 2)
ide_set_irq(drive, 1);
if (drive->quirk_list == 2)
ide_set_irq(drive, 1);
@@
-889,7
+881,7
@@
void ide_execute_command(ide_drive_t *drive, u8 cmd, ide_handler_t *handler,
spin_lock_irqsave(&ide_lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
spin_lock_irqsave(&ide_lock, flags);
__ide_set_handler(drive, handler, timeout, expiry);
- hwif->OUTBSYNC(
drive
, cmd, hwif->io_ports.command_addr);
+ hwif->OUTBSYNC(
hwif
, cmd, hwif->io_ports.command_addr);
/*
* Drive takes 400nS to respond, we must avoid the IRQ being
* serviced before that.
/*
* Drive takes 400nS to respond, we must avoid the IRQ being
* serviced before that.
@@
-907,12
+899,20
@@
void ide_execute_pkt_cmd(ide_drive_t *drive)
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
unsigned long flags;
spin_lock_irqsave(&ide_lock, flags);
- hwif->OUTBSYNC(
drive
, WIN_PACKETCMD, hwif->io_ports.command_addr);
+ hwif->OUTBSYNC(
hwif
, WIN_PACKETCMD, hwif->io_ports.command_addr);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
ndelay(400);
spin_unlock_irqrestore(&ide_lock, flags);
}
EXPORT_SYMBOL_GPL(ide_execute_pkt_cmd);
+static inline void ide_complete_drive_reset(ide_drive_t *drive, int err)
+{
+ struct request *rq = drive->hwif->hwgroup->rq;
+
+ if (rq && blk_special_request(rq) && rq->cmd[0] == REQ_DRIVE_RESET)
+ ide_end_request(drive, err ? err : 1, 0);
+}
+
/* needed below */
static ide_startstop_t do_reset1 (ide_drive_t *, int);
/* needed below */
static ide_startstop_t do_reset1 (ide_drive_t *, int);
@@
-948,7
+948,7
@@
static ide_startstop_t atapi_reset_pollfunc (ide_drive_t *drive)
}
/* done polling */
hwgroup->polling = 0;
}
/* done polling */
hwgroup->polling = 0;
-
hwgroup->resetting = 0
;
+
ide_complete_drive_reset(drive, 0)
;
return ide_stopped;
}
return ide_stopped;
}
@@
-964,12
+964,14
@@
static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
ide_hwif_t *hwif = HWIF(drive);
const struct ide_port_ops *port_ops = hwif->port_ops;
u8 tmp;
ide_hwif_t *hwif = HWIF(drive);
const struct ide_port_ops *port_ops = hwif->port_ops;
u8 tmp;
+ int err = 0;
if (port_ops && port_ops->reset_poll) {
if (port_ops && port_ops->reset_poll) {
- if (port_ops->reset_poll(drive)) {
+ err = port_ops->reset_poll(drive);
+ if (err) {
printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
hwif->name, drive->name);
printk(KERN_ERR "%s: host reset_poll failure for %s.\n",
hwif->name, drive->name);
-
return ide_stopped
;
+
goto out
;
}
}
}
}
@@
-983,6
+985,7
@@
static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
}
printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
drive->failures++;
}
printk("%s: reset timed-out, status=0x%02x\n", hwif->name, tmp);
drive->failures++;
+ err = -EIO;
} else {
printk("%s: reset: ", hwif->name);
tmp = ide_read_error(drive);
} else {
printk("%s: reset: ", hwif->name);
tmp = ide_read_error(drive);
@@
-1009,10
+1012,12
@@
static ide_startstop_t reset_pollfunc (ide_drive_t *drive)
if (tmp & 0x80)
printk("; slave: failed");
printk("\n");
if (tmp & 0x80)
printk("; slave: failed");
printk("\n");
+ err = -EIO;
}
}
}
}
+out:
hwgroup->polling = 0; /* done polling */
hwgroup->polling = 0; /* done polling */
- hwgroup->resetting = 0; /* done reset attempt */
+ ide_complete_drive_reset(drive, err);
return ide_stopped;
}
return ide_stopped;
}
@@
-1098,11
+1103,10
@@
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->media != ide_disk && !do_not_try_atapi) {
/* For an ATAPI device, first try an ATAPI SRST. */
if (drive->media != ide_disk && !do_not_try_atapi) {
- hwgroup->resetting = 1;
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
pre_reset(drive);
SELECT_DRIVE(drive);
udelay (20);
- hwif->OUTBSYNC(
drive
, WIN_SRST, io_ports->command_addr);
+ hwif->OUTBSYNC(
hwif
, WIN_SRST, io_ports->command_addr);
ndelay(400);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
ndelay(400);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
hwgroup->polling = 1;
@@
-1120,10
+1124,10
@@
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
if (io_ports->ctl_addr == 0) {
spin_unlock_irqrestore(&ide_lock, flags);
if (io_ports->ctl_addr == 0) {
spin_unlock_irqrestore(&ide_lock, flags);
+ ide_complete_drive_reset(drive, -ENXIO);
return ide_stopped;
}
return ide_stopped;
}
- hwgroup->resetting = 1;
/*
* Note that we also set nIEN while resetting the device,
* to mask unwanted interrupts from the interface during the reset.
/*
* Note that we also set nIEN while resetting the device,
* to mask unwanted interrupts from the interface during the reset.
@@
-1133,14
+1137,14
@@
static ide_startstop_t do_reset1 (ide_drive_t *drive, int do_not_try_atapi)
* recover from reset very quickly, saving us the first 50ms wait time.
*/
/* set SRST and nIEN */
* recover from reset very quickly, saving us the first 50ms wait time.
*/
/* set SRST and nIEN */
- hwif->OUTBSYNC(
drive, drive->ctl|
6, io_ports->ctl_addr);
+ hwif->OUTBSYNC(
hwif, ATA_DEVCTL_OBS |
6, io_ports->ctl_addr);
/* more than enough time */
udelay(10);
if (drive->quirk_list == 2)
/* more than enough time */
udelay(10);
if (drive->quirk_list == 2)
- ctl =
drive->ctl;
/* clear SRST and nIEN */
+ ctl =
ATA_DEVCTL_OBS;
/* clear SRST and nIEN */
else
else
- ctl =
drive->ctl | 2;
/* clear SRST, leave nIEN */
- hwif->OUTBSYNC(
drive
, ctl, io_ports->ctl_addr);
+ ctl =
ATA_DEVCTL_OBS | 2;
/* clear SRST, leave nIEN */
+ hwif->OUTBSYNC(
hwif
, ctl, io_ports->ctl_addr);
/* more than enough time */
udelay(10);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;
/* more than enough time */
udelay(10);
hwgroup->poll_timeout = jiffies + WAIT_WORSTCASE;