Commit 68c14a04 authored by Martin Dalecki's avatar Martin Dalecki Committed by Linus Torvalds

[PATCH] IDE 93

 - Revert patch number 92. It turned out to be broken behind hope.  Personally I
   attribute this to the recent heat wave over here and apologize for the
   problems this may have caused. Turned out that my note about the change
   beeing dnagerous in the last change log was more then true...

 - Locking issues for ioctl handling.

 - Remove waiting_for_dma bit field. Use IDE_DMA bit flag instead.
   Apply this bit globally and not in the corresponding implementation
   functions.
parent da873d20
......@@ -597,7 +597,6 @@ static int cmd64x_udma_stop(struct ata_device *drive)
struct pci_dev *dev = ch->pci_dev;
u8 jack_slap = ((dev->device == PCI_DEVICE_ID_CMD_648) || (dev->device == PCI_DEVICE_ID_CMD_649)) ? 1 : 0;
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......@@ -647,7 +646,6 @@ static int cmd646_1_udma_stop(struct ata_device *drive)
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
drive->waiting_for_dma = 0;
dma_stat = inb(dma_base+2); /* get DMA status */
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......
......@@ -157,7 +157,6 @@ static int hpt34x_udma_stop(struct ata_device *drive)
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......@@ -184,7 +183,6 @@ static int hpt34x_udma_init(struct ata_device *drive, struct request *rq)
outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
outb(cmd, dma_base); /* specify r/w */
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
drive->waiting_for_dma = 1;
if (drive->type == ATA_DISK) {
ata_set_handler(drive, ide_dma_intr, WAIT_CMD, NULL); /* issue cmd to drive */
......
......@@ -890,7 +890,6 @@ static int hpt370_udma_stop(struct ata_device *drive)
do_udma_start(drive);
}
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......@@ -913,7 +912,6 @@ static int hpt374_udma_stop(struct ata_device *drive)
if ((bwsr_stat & bwsr_mask) == bwsr_mask)
pci_write_config_byte(dev, mscreg, msc_stat|0x30);
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......
......@@ -440,7 +440,6 @@ static int icside_dma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
drive->waiting_for_dma = 0;
disable_dma(ch->hw.dma);
icside_destroy_dmatable(drive);
......@@ -508,8 +507,6 @@ icside_dma_common(struct ata_device *drive, struct request *rq,
set_dma_sg(ch->hw.dma, ch->sg_table, count);
set_dma_mode(ch->hw.dma, dma_mode);
drive->waiting_for_dma = 1;
return 0;
}
......
This diff is collapsed.
......@@ -1378,7 +1378,6 @@ static int pmac_udma_stop(struct ata_device *drive)
ata4 = (pmac_ide[ix].kind == controller_kl_ata4 ||
pmac_ide[ix].kind == controller_kl_ata4_80);
drive->waiting_for_dma = 0;
dstat = in_le32(&dma->status);
out_le32(&dma->control, ((RUN|WAKE|DEAD) << 16));
pmac_ide_destroy_dmatable(drive->channel, ix);
......@@ -1418,7 +1417,7 @@ static int pmac_udma_init(struct ata_device *drive, struct request *rq)
((reading) ? 0x00800000UL : 0));
(void)in_le32((unsigned *)(IDE_DATA_REG + IDE_TIMING_CONFIG + _IO_BASE));
}
drive->waiting_for_dma = 1;
if (drive->type != ATA_DISK)
return ide_started;
......@@ -1466,6 +1465,8 @@ static int pmac_udma_irq_status(struct ata_device *drive)
* - The dbdma fifo hasn't yet finished flushing to to system memory
* when the disk interrupt occurs.
*
* FIXME: The following *trick* is broken:
*
* The trick here is to increment drive->waiting_for_dma, and return as
* if no interrupt occured. If the counter reach a certain timeout
* value, we then return 1. If we really got the interrupt, it will
......@@ -1480,15 +1481,16 @@ static int pmac_udma_irq_status(struct ata_device *drive)
*/
if (!(in_le32(&dma->status) & ACTIVE))
return 1;
if (!drive->waiting_for_dma)
if (!test_bit(IDE_DMA, drive->channel->active))
printk(KERN_WARNING "ide%d, ide_dma_test_irq \
called while not waiting\n", ix);
/* If dbdma didn't execute the STOP command yet, the
* active bit is still set */
drive->waiting_for_dma++;
if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
printk(KERN_WARNING "ide%d, timeout waiting \
set_bit(IDE_DMA, drive->channel->active);
// if (drive->waiting_for_dma >= DMA_WAIT_TIMEOUT) {
// printk(KERN_WARNING "ide%d, timeout waiting \
for dbdma command stop\n", ix);
return 1;
}
......
......@@ -148,7 +148,7 @@ void ata_write(struct ata_device *drive, void *buffer, unsigned int wcount)
*/
int drive_is_ready(struct ata_device *drive)
{
if (drive->waiting_for_dma)
if (test_bit(IDE_DMA, drive->channel->active))
return udma_irq_status(drive);
/*
......@@ -242,9 +242,8 @@ int ide_do_drive_cmd(struct ata_device *drive, struct request *rq, ide_action_t
/*
* Invoked on completion of a special REQ_SPECIAL command.
*/
static ide_startstop_t special_intr(struct ata_device *drive,
struct request *rq)
{
ide_startstop_t ata_special_intr(struct ata_device *drive, struct
request *rq) {
struct ata_taskfile *ar = rq->special;
ide_startstop_t ret = ide_stopped;
......@@ -293,18 +292,16 @@ static ide_startstop_t special_intr(struct ata_device *drive,
return ret;
}
int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar,
char *buffer)
int ide_raw_taskfile(struct ata_device *drive, struct ata_taskfile *ar)
{
struct request req;
ar->command_type = IDE_DRIVE_TASK_NO_DATA;
ar->XXX_handler = special_intr;
ar->XXX_handler = ata_special_intr;
memset(&req, 0, sizeof(req));
req.flags = REQ_SPECIAL;
req.special = ar;
req.buffer = buffer;
return ide_do_drive_cmd(drive, &req, ide_wait);
}
......@@ -313,4 +310,5 @@ EXPORT_SYMBOL(drive_is_ready);
EXPORT_SYMBOL(ide_do_drive_cmd);
EXPORT_SYMBOL(ata_read);
EXPORT_SYMBOL(ata_write);
EXPORT_SYMBOL(ata_special_intr);
EXPORT_SYMBOL(ide_raw_taskfile);
......@@ -262,14 +262,14 @@ static ide_startstop_t do_reset1(struct ata_device *, int); /* needed below */
* Poll the interface for completion every 50ms during an ATAPI drive reset
* operation. If the drive has not yet responded, and we have not yet hit our
* maximum waiting time, then the timer is restarted for another 50ms.
*
* Channel lock should be held.
*/
static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct request *__rq)
{
unsigned long flags;
struct ata_channel *ch = drive->channel;
int ret = ide_stopped;
spin_lock_irqsave(ch->lock, flags);
ata_select(drive, 10);
if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) {
......@@ -287,7 +287,6 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req
ret = ide_stopped;
}
spin_unlock_irqrestore(ch->lock, flags);
return ret;
}
......@@ -296,14 +295,14 @@ static ide_startstop_t atapi_reset_pollfunc(struct ata_device *drive, struct req
* Poll the interface for completion every 50ms during an ata reset operation.
* If the drives have not yet responded, and we have not yet hit our maximum
* waiting time, then the timer is restarted for another 50ms.
*
* Channel lock should be held.
*/
static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *__rq)
{
unsigned long flags;
struct ata_channel *ch = drive->channel;
int ret;
spin_lock_irqsave(ch->lock, flags);
if (!ata_status(drive, 0, BUSY_STAT)) {
if (time_before(jiffies, ch->poll_timeout)) {
ata_set_handler(drive, reset_pollfunc, HZ/20, NULL);
......@@ -347,7 +346,6 @@ static ide_startstop_t reset_pollfunc(struct ata_device *drive, struct request *
ret = ide_stopped;
}
ch->poll_timeout = 0; /* done polling */
spin_unlock_irqrestore(ch->lock, flags);
return ide_stopped;
}
......@@ -443,12 +441,17 @@ static struct ata_bit_messages ata_error_msgs[] = {
static void dump_bits(struct ata_bit_messages *msgs, int nr, byte bits)
{
int i;
int first = 1;
printk(" [ ");
for (i = 0; i < nr; i++, msgs++)
if ((bits & msgs->mask) == msgs->match)
printk("%s ", msgs->msg);
if ((bits & msgs->mask) == msgs->match) {
if (!first)
printk(",");
printk("%s", msgs->msg);
first = 0;
}
printk("] ");
}
......@@ -560,7 +563,7 @@ static int do_recalibrate(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.sector_count = drive->sect;
args.cmd = WIN_RESTORE;
ide_raw_taskfile(drive, &args, NULL);
ide_raw_taskfile(drive, &args);
printk(KERN_INFO "%s: done!\n", drive->name);
}
......@@ -1030,12 +1033,12 @@ void ide_timer_expiry(unsigned long data)
if (ch->poll_timeout) {
ret = handler(drive, drive->rq);
} else if (drive_is_ready(drive)) {
if (drive->waiting_for_dma)
if (test_bit(IDE_DMA, ch->active))
udma_irq_lost(drive);
(void) ide_ack_intr(ch);
printk("%s: lost interrupt\n", drive->name);
ret = handler(drive, drive->rq);
} else if (drive->waiting_for_dma) {
} else if (test_bit(IDE_DMA, ch->active)) {
struct request *rq = drive->rq;
/*
......
......@@ -47,6 +47,7 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg)
u8 *argbuf = vals;
int argsize = 4;
struct ata_taskfile args;
struct request req;
/* Second phase.
*/
......@@ -77,7 +78,17 @@ static int do_cmd_ioctl(struct ata_device *drive, unsigned long arg)
memset(argbuf + 4, 0, argsize - 4);
}
err = ide_raw_taskfile(drive, &args, argbuf + 4);
/* Issue ATA command and wait for completion.
*/
args.command_type = IDE_DRIVE_TASK_NO_DATA;
args.XXX_handler = ata_special_intr;
memset(&req, 0, sizeof(req));
req.flags = REQ_SPECIAL;
req.special = &args;
req.buffer = argbuf + 4;
err = ide_do_drive_cmd(drive, &req, ide_wait);
argbuf[0] = drive->status;
argbuf[1] = args.taskfile.feature;
......
......@@ -91,7 +91,6 @@ static int ns87415_udma_stop(struct ata_device *drive)
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
drive->waiting_for_dma = 0;
dma_stat = inb(ch->dma_base+2);
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
outb(inb(dma_base)|6, dma_base); /* from ERRATA: clear the INTR & ERROR bits */
......
......@@ -167,7 +167,6 @@ int ata_start_dma(struct ata_device *drive, struct request *rq)
outl(ch->dmatable_dma, dma_base + 4); /* PRD table */
outb(reading, dma_base); /* specify r/w */
outb(inb(dma_base+2)|6, dma_base+2); /* clear INTR & ERROR flags */
drive->waiting_for_dma = 1;
return 0;
}
......@@ -436,7 +435,6 @@ int udma_pci_stop(struct ata_device *drive)
unsigned long dma_base = ch->dma_base;
u8 dma_stat;
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......
......@@ -571,7 +571,7 @@ static void pdc202xx_udma_start(struct ata_device *drive, struct request *rq)
outb(inb(ch->dma_base) | 1, ch->dma_base); /* start DMA */
}
int pdc202xx_udma_stop(struct ata_device *drive)
static int pdc202xx_udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
u32 high_16 = pci_resource_start(ch->pci_dev, 4);
......@@ -585,7 +585,6 @@ int pdc202xx_udma_stop(struct ata_device *drive)
OUT_BYTE(clock & ~(ch->unit ? 0x08:0x02), high_16 + PDC_CLK);
}
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......@@ -604,7 +603,7 @@ static void pdc202xx_bug(struct ata_device *drive)
#endif
void pdc202xx_new_reset(struct ata_device *drive)
static void pdc202xx_new_reset(struct ata_device *drive)
{
ata_reset(drive->channel);
mdelay(1000);
......
......@@ -331,7 +331,6 @@ static int svwks_udma_stop(struct ata_device *drive)
#endif
}
drive->waiting_for_dma = 0;
outb(inb(dma_base)&~1, dma_base); /* stop DMA */
dma_stat = inb(dma_base+2); /* get DMA status */
outb(dma_stat|6, dma_base+2); /* clear the INTR & ERROR bits */
......
......@@ -441,7 +441,7 @@ static int check_autopoll(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.feature = 0x01;
args.cmd = WIN_NOP;
ide_raw_taskfile(drive, &args, NULL);
ide_raw_taskfile(drive, &args);
if (args.taskfile.feature & ABRT_ERR)
return 1;
......@@ -469,7 +469,7 @@ static int configure_tcq(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_EN_WCACHE;
args.cmd = WIN_SETFEATURES;
if (ide_raw_taskfile(drive, &args, NULL)) {
if (ide_raw_taskfile(drive, &args)) {
printk("%s: failed to enable write cache\n", drive->name);
return 1;
}
......@@ -481,7 +481,7 @@ static int configure_tcq(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_DIS_RI;
args.cmd = WIN_SETFEATURES;
if (ide_raw_taskfile(drive, &args, NULL)) {
if (ide_raw_taskfile(drive, &args)) {
printk("%s: disabling release interrupt fail\n", drive->name);
return 1;
}
......@@ -493,7 +493,7 @@ static int configure_tcq(struct ata_device *drive)
memset(&args, 0, sizeof(args));
args.taskfile.feature = SETFEATURES_EN_SI;
args.cmd = WIN_SETFEATURES;
if (ide_raw_taskfile(drive, &args, NULL)) {
if (ide_raw_taskfile(drive, &args)) {
printk("%s: enabling service interrupt fail\n", drive->name);
return 1;
}
......
......@@ -185,8 +185,8 @@ static int trm290_udma_stop(struct ata_device *drive)
{
struct ata_channel *ch = drive->channel;
drive->waiting_for_dma = 0;
udma_destroy_table(ch); /* purge DMA mappings */
return (inw(ch->dma_base + 2) != 0x00ff);
}
......@@ -224,7 +224,6 @@ static int trm290_udma_init(struct ata_device *drive, struct request *rq)
trm290_prepare_drive(drive, 1); /* select DMA xfer */
outl(ch->dmatable_dma|reading|writing, ch->dma_base);
drive->waiting_for_dma = 1;
outw((count * 2) - 1, ch->dma_base+2); /* start DMA */
if (drive->type == ATA_DISK) {
......
......@@ -298,7 +298,6 @@ struct ata_device {
unsigned using_tcq : 1; /* disk is using queueing */
unsigned dsc_overlap : 1; /* flag: DSC overlap */
unsigned waiting_for_dma: 1; /* dma currently in progress */
unsigned busy : 1; /* currently doing revalidate_disk() */
unsigned blocked : 1; /* 1=powermanagment told us not to do anything, so sleep nicely */
......@@ -681,7 +680,8 @@ static inline void ide_unmap_rq(struct request *rq, char *to,
bio_kunmap_irq(to, flags);
}
extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *, char *);
extern ide_startstop_t ata_special_intr(struct ata_device *, struct request *);
extern int ide_raw_taskfile(struct ata_device *, struct ata_taskfile *);
extern void ide_fix_driveid(struct hd_driveid *id);
extern int ide_config_drive_speed(struct ata_device *, byte);
......@@ -756,6 +756,8 @@ static inline void udma_start(struct ata_device *drive, struct request *rq)
static inline int udma_stop(struct ata_device *drive)
{
clear_bit(IDE_DMA, drive->channel->active);
return drive->channel->udma_stop(drive);
}
......@@ -764,7 +766,11 @@ static inline int udma_stop(struct ata_device *drive)
*/
static inline ide_startstop_t udma_init(struct ata_device *drive, struct request *rq)
{
return drive->channel->udma_init(drive, rq);
int ret = drive->channel->udma_init(drive, rq);
if (ret == ide_started)
set_bit(IDE_DMA, drive->channel->active);
return ret;
}
static inline int udma_irq_status(struct ata_device *drive)
......
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