Skip to content

Commit

Permalink
[PATCH] sgiioc4: fixup use of mmio ops
Browse files Browse the repository at this point in the history
Fix some bugs in the patch that converted the IOC4 driver from port IO ops to
memio ops.

http://marc.theaimsgroup.com/?l=linux-ide&m=114895892231438&w=2

  Problems fixed are:
   - Call to default_hwif_mmiops() was not being done until _after_
     first IO operation, resulting in the first IO operation being
     done as a port IO op, instead of memio.
   - request_region() calls needed to be request_mem_region()
   - Incomplete error case handling.
   - Non-usage of ioremap() and __iomem.

Signed-off-by: John Keller <jpk@sgi.com>
Signed-off-by: Jeremy Higdon <jeremy@sgi.com>
Cc: Alan Cox <alan@lxorguk.ukuu.org.uk>
Cc: Bartlomiej Zolnierkiewicz <B.Zolnierkiewicz@elka.pw.edu.pl>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
  • Loading branch information
John Keller authored and Linus Torvalds committed Sep 1, 2006
1 parent 7931e2a commit 1678df3
Showing 1 changed file with 42 additions and 18 deletions.
60 changes: 42 additions & 18 deletions drivers/ide/pci/sgiioc4.c
Original file line number Diff line number Diff line change
Expand Up @@ -367,12 +367,13 @@ sgiioc4_INB(unsigned long port)
static void __devinit
ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
{
void __iomem *virt_dma_base;
int num_ports = sizeof (ioc4_dma_regs_t);

printk(KERN_INFO "%s: BM-DMA at 0x%04lx-0x%04lx\n", hwif->name,
dma_base, dma_base + num_ports - 1);

if (!request_region(dma_base, num_ports, hwif->name)) {
if (!request_mem_region(dma_base, num_ports, hwif->name)) {
printk(KERN_ERR
"%s(%s) -- ERROR, Addresses 0x%p to 0x%p "
"ALREADY in use\n",
Expand All @@ -381,13 +382,21 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
goto dma_alloc_failure;
}

hwif->dma_base = dma_base;
virt_dma_base = ioremap(dma_base, num_ports);
if (virt_dma_base == NULL) {
printk(KERN_ERR
"%s(%s) -- ERROR, Unable to map addresses 0x%lx to 0x%lx\n",
__FUNCTION__, hwif->name, dma_base, dma_base + num_ports - 1);
goto dma_remap_failure;
}
hwif->dma_base = (unsigned long) virt_dma_base;

hwif->dmatable_cpu = pci_alloc_consistent(hwif->pci_dev,
IOC4_PRD_ENTRIES * IOC4_PRD_BYTES,
&hwif->dmatable_dma);

if (!hwif->dmatable_cpu)
goto dma_alloc_failure;
goto dma_pci_alloc_failure;

hwif->sg_max_nents = IOC4_PRD_ENTRIES;

Expand All @@ -411,6 +420,12 @@ ide_dma_sgiioc4(ide_hwif_t * hwif, unsigned long dma_base)
printk(KERN_INFO
"Changing from DMA to PIO mode for Drive %s\n", hwif->name);

dma_pci_alloc_failure:
iounmap(virt_dma_base);

dma_remap_failure:
release_mem_region(dma_base, num_ports);

dma_alloc_failure:
/* Disable DMA because we couldnot allocate any DMA maps */
hwif->autodma = 0;
Expand Down Expand Up @@ -607,18 +622,15 @@ ide_init_sgiioc4(ide_hwif_t * hwif)
hwif->ide_dma_lostirq = &sgiioc4_ide_dma_lostirq;
hwif->ide_dma_timeout = &__ide_dma_timeout;

/*
* The IOC4 uses MMIO rather than Port IO.
* It also needs special workarounds for INB.
*/
default_hwif_mmiops(hwif);
hwif->INB = &sgiioc4_INB;
}

static int __devinit
sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
{
unsigned long base, ctl, dma_base, irqport;
unsigned long cmd_base, dma_base, irqport;
unsigned long bar0, cmd_phys_base, ctl;
void __iomem *virt_base;
ide_hwif_t *hwif;
int h;

Expand All @@ -636,23 +648,32 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
}

/* Get the CmdBlk and CtrlBlk Base Registers */
base = pci_resource_start(dev, 0) + IOC4_CMD_OFFSET;
ctl = pci_resource_start(dev, 0) + IOC4_CTRL_OFFSET;
irqport = pci_resource_start(dev, 0) + IOC4_INTR_OFFSET;
bar0 = pci_resource_start(dev, 0);
virt_base = ioremap(bar0, pci_resource_len(dev, 0));
if (virt_base == NULL) {
printk(KERN_ERR "%s: Unable to remap BAR 0 address: 0x%lx\n",
d->name, bar0);
return -ENOMEM;
}
cmd_base = (unsigned long) virt_base + IOC4_CMD_OFFSET;
ctl = (unsigned long) virt_base + IOC4_CTRL_OFFSET;
irqport = (unsigned long) virt_base + IOC4_INTR_OFFSET;
dma_base = pci_resource_start(dev, 0) + IOC4_DMA_OFFSET;

if (!request_region(base, IOC4_CMD_CTL_BLK_SIZE, hwif->name)) {
cmd_phys_base = bar0 + IOC4_CMD_OFFSET;
if (!request_mem_region(cmd_phys_base, IOC4_CMD_CTL_BLK_SIZE,
hwif->name)) {
printk(KERN_ERR
"%s : %s -- ERROR, Port Addresses "
"%s : %s -- ERROR, Addresses "
"0x%p to 0x%p ALREADY in use\n",
__FUNCTION__, hwif->name, (void *) base,
(void *) base + IOC4_CMD_CTL_BLK_SIZE);
__FUNCTION__, hwif->name, (void *) cmd_phys_base,
(void *) cmd_phys_base + IOC4_CMD_CTL_BLK_SIZE);
return -ENOMEM;
}

if (hwif->io_ports[IDE_DATA_OFFSET] != base) {
if (hwif->io_ports[IDE_DATA_OFFSET] != cmd_base) {
/* Initialize the IO registers */
sgiioc4_init_hwif_ports(&hwif->hw, base, ctl, irqport);
sgiioc4_init_hwif_ports(&hwif->hw, cmd_base, ctl, irqport);
memcpy(hwif->io_ports, hwif->hw.io_ports,
sizeof (hwif->io_ports));
hwif->noprobe = !hwif->io_ports[IDE_DATA_OFFSET];
Expand All @@ -665,6 +686,9 @@ sgiioc4_ide_setup_pci_device(struct pci_dev *dev, ide_pci_device_t * d)
hwif->cds = (struct ide_pci_device_s *) d;
hwif->gendev.parent = &dev->dev;/* setup proper ancestral information */

/* The IOC4 uses MMIO rather than Port IO. */
default_hwif_mmiops(hwif);

/* Initializing chipset IRQ Registers */
hwif->OUTL(0x03, irqport + IOC4_INTR_SET * 4);

Expand Down

0 comments on commit 1678df3

Please sign in to comment.