lkml.org 
[lkml]   [2002]   [Sep]   [10]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
Patch in this message
/
Date
From
SubjectRe: Oops + Aiee when mounting CDROM via ide-scsi under 2.4.20-pre5-ac4
On Tue, Sep 10 2002, Jens Axboe wrote:
> On Tue, Sep 10 2002, Martin Knoblauch wrote:
> > Hi,
> >
> > I am getting a reproducable Oops+Aiee when trying to mount a ATAPI
> > CDROM via the ide-scsi interface under 2.4.20-pre5-ac4. Works OK
> > without ide-scsi.
>
> Ok, the problem is that ide-scsi builds a request which eventually ends
> up going through the ide code dma mapping. ide_build_sglist() does a
> rq_data_dir() on the request, which BUG()'s if the command isn't an fs
> read or write. This actually went undetected before, because the ide
> code did:
>
> if (rq->cmd == READ)
> direction is dma from device
> else
> direction is to device
>
> and rq->cmd is IDESCSI_PC_RQ in this case. So we always mapped for dma
> to the device, even if that wasn't the case.
>
> Hmm, maybe just adding a single direction bit to struct request is the
> easy way out for 2.4. Or... I'll cook something up.

ok try this patch, against 2.4.20-pre5-ac4 (well not a clean one, but I
think it should apply).

alan, this should probably go into ac5 provided that Martin tests it as
ok.

diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/arm/icside.c linux-2.4.20-pre5-ac4/drivers/ide/arm/icside.c
--- /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/arm/icside.c 2002-09-10 12:56:51.000000000 +0200
+++ linux-2.4.20-pre5-ac4/drivers/ide/arm/icside.c 2002-09-10 21:04:58.000000000 +0200
@@ -264,9 +264,9 @@
}

static int
-icside_build_dmatable(ide_drive_t *drive, int reading)
+icside_build_dmatable(ide_drive_t *drive, int ddir)
{
- return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq);
+ return HWIF(drive)->sg_nents = ide_build_sglist(HWIF(drive), HWGROUP(drive)->rq, ddir);
}

/* Teardown mappings after DMA has completed. */
@@ -556,7 +556,7 @@
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;

- count = icside_build_dmatable(drive, 1);
+ count = icside_build_dmatable(drive, PCI_DMA_FROMDEVICE);
if (!count)
return 1;
disable_dma(hwif->hw.dma);
@@ -610,7 +610,7 @@
u8 lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;

- count = icside_build_dmatable(drive, 0);
+ count = icside_build_dmatable(drive, PCI_DMA_TODEVICE);
if (!count)
return 1;
disable_dma(hwif->hw.dma);
diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/ide-dma.c linux-2.4.20-pre5-ac4/drivers/ide/ide-dma.c
--- /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/ide-dma.c 2002-09-10 12:56:51.000000000 +0200
+++ linux-2.4.20-pre5-ac4/drivers/ide/ide-dma.c 2002-09-10 21:03:11.000000000 +0200
@@ -215,7 +214,7 @@
return DRIVER(drive)->error(drive, "dma_intr", stat);
}

-static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq)
+static int ide_build_sglist (ide_hwif_t *hwif, struct request *rq, int ddir)
{
struct buffer_head *bh;
struct scatterlist *sg = hwif->sg_table;
@@ -223,11 +222,7 @@

if (hwif->sg_dma_active)
BUG();
-
- if (rq_data_dir(rq) == READ)
- hwif->sg_dma_direction = PCI_DMA_FROMDEVICE;
- else
- hwif->sg_dma_direction = PCI_DMA_TODEVICE;
+
bh = rq->bh;
do {
unsigned char *virt_addr = bh->b_data;
@@ -252,7 +247,8 @@
if(nents == 0)
BUG();

- return pci_map_sg(hwif->pci_dev, sg, nents, hwif->sg_dma_direction);
+ hwif->sg_dma_direction = ddir;
+ return pci_map_sg(hwif->pci_dev, sg, nents, ddir);
}

static int ide_raw_build_sglist (ide_hwif_t *hwif, struct request *rq)
@@ -302,7 +298,7 @@
* Returns 0 if all went okay, returns 1 otherwise.
* May also be invoked from trm290.c
*/
-int ide_build_dmatable (ide_drive_t *drive, struct request *rq)
+int ide_build_dmatable (ide_drive_t *drive, struct request *rq, int ddir)
{
ide_hwif_t *hwif = HWIF(drive);
unsigned int *table = hwif->dmatable_cpu;
@@ -314,7 +310,7 @@
if (rq->cmd == IDE_DRIVE_TASKFILE)
hwif->sg_nents = i = ide_raw_build_sglist(hwif, rq);
else
- hwif->sg_nents = i = ide_build_sglist(hwif, rq);
+ hwif->sg_nents = i = ide_build_sglist(hwif, rq, ddir);

if (!i)
return 0;
@@ -543,7 +539,7 @@
u8 dma_stat = 0, lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;

- if (!(count = ide_build_dmatable(drive, rq)))
+ if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE)))
/* try PIO instead of DMA */
return 1;
/* PRD table */
@@ -595,7 +591,7 @@
u8 dma_stat = 0, lba48 = (drive->addressing == 1) ? 1 : 0;
task_ioreg_t command = WIN_NOP;

- if (!(count = ide_build_dmatable(drive, rq)))
+ if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_TODEVICE)))
/* try PIO instead of DMA */
return 1;
/* PRD table */
diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/pci/trm290.c linux-2.4.20-pre5-ac4/drivers/ide/pci/trm290.c
--- /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/pci/trm290.c 2002-09-10 12:56:52.000000000 +0200
+++ linux-2.4.20-pre5-ac4/drivers/ide/pci/trm290.c 2002-09-10 21:08:15.000000000 +0200
@@ -191,7 +191,7 @@
trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1;
#endif
- if (!(count = ide_build_dmatable(drive, rq))) {
+ if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_TODEVICE))) {
/* try PIO instead of DMA */
trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1;
@@ -235,7 +235,7 @@
task_ioreg_t command = WIN_NOP;
unsigned int count, reading = 2, writing = 0;

- if (!(count = ide_build_dmatable(drive, rq))) {
+ if (!(count = ide_build_dmatable(drive, rq, PCI_DMA_FROMDEVICE))) {
/* try PIO instead of DMA */
trm290_prepare_drive(drive, 0); /* select PIO xfer */
return 1;
diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/ppc/pmac.c linux-2.4.20-pre5-ac4/drivers/ide/ppc/pmac.c
--- /opt/kernel/linux-2.4.20-pre5-ac4/drivers/ide/ppc/pmac.c 2002-09-10 12:56:52.000000000 +0200
+++ linux-2.4.20-pre5-ac4/drivers/ide/ppc/pmac.c 2002-09-10 21:07:42.000000000 +0200
@@ -932,7 +932,7 @@
#ifdef CONFIG_BLK_DEV_IDEDMA_PMAC

static int
-pmac_ide_build_sglist(ide_hwif_t *hwif, struct request *rq)
+pmac_ide_build_sglist(ide_hwif_t *hwif, struct request *rq, int data_dir)
{
pmac_ide_hwif_t *pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
struct buffer_head *bh;
@@ -942,10 +942,6 @@
if (hwif->sg_dma_active)
BUG();

- if (rq->cmd == READ)
- pmif->sg_dma_direction = PCI_DMA_FROMDEVICE;
- else
- pmif->sg_dma_direction = PCI_DMA_TODEVICE;
bh = rq->bh;
do {
unsigned char *virt_addr = bh->b_data;
@@ -965,7 +961,8 @@
nents++;
} while (bh != NULL);

- return pci_map_sg(hwif->pci_dev, sg, nents, pmif->sg_dma_direction);
+ pmif->sg_dma_direction = data_dir;
+ return pci_map_sg(hwif->pci_dev, sg, nents, data_dir);
}

static int
@@ -1013,6 +1010,7 @@
pmac_ide_hwif_t* pmif = (pmac_ide_hwif_t *)hwif->hwif_data;
volatile struct dbdma_regs *dma = pmif->dma_regs;
struct scatterlist *sg;
+ int data_dir;

/* DMA table is already aligned */
table = (struct dbdma_cmd *) pmif->dma_table_cpu;
@@ -1022,11 +1020,16 @@
while (readl(&dma->status) & RUN)
udelay(1);

+ if (wr)
+ data_dir = PCI_DMA_TODEVICE;
+ else
+ data_dir = PCI_DMA_FROMDEVICE;
+
/* Build sglist */
if (rq->cmd == IDE_DRIVE_TASKFILE)
pmif->sg_nents = i = pmac_ide_raw_build_sglist(hwif, rq);
else
- pmif->sg_nents = i = pmac_ide_build_sglist(hwif, rq);
+ pmif->sg_nents = i = pmac_ide_build_sglist(hwif, rq, data_dir);
if (!i)
return 0;

diff -ur -X /home/axboe/cdrom/exclude /opt/kernel/linux-2.4.20-pre5-ac4/include/linux/ide.h linux-2.4.20-pre5-ac4/include/linux/ide.h
--- /opt/kernel/linux-2.4.20-pre5-ac4/include/linux/ide.h 2002-09-10 12:56:54.000000000 +0200
+++ linux-2.4.20-pre5-ac4/include/linux/ide.h 2002-09-10 21:04:00.000000000 +0200
@@ -1732,7 +1732,7 @@
#ifdef CONFIG_BLK_DEV_IDEDMA
#define BAD_DMA_DRIVE 0
#define GOOD_DMA_DRIVE 1
-extern int ide_build_dmatable(ide_drive_t *, struct request *);
+extern int ide_build_dmatable(ide_drive_t *, struct request *, int);
extern void ide_destroy_dmatable(ide_drive_t *);
extern ide_startstop_t ide_dma_intr(ide_drive_t *);
extern int ide_release_dma(ide_hwif_t *);
--
Jens Axboe

-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@vger.kernel.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/

\
 
 \ /
  Last update: 2005-03-22 13:28    [W:0.044 / U:0.140 seconds]
©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site