diff options
| author | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-04-26 16:25:22 -0400 |
|---|---|---|
| committer | Bartlomiej Zolnierkiewicz <bzolnier@gmail.com> | 2008-04-26 16:25:22 -0400 |
| commit | b123f56e04c7c112f754f948198d1ea5a80e649d (patch) | |
| tree | c58e83e954159d7755aa7f04d433e4c7e25dc330 | |
| parent | f629b38beddf2ff8bc3fda1754bbd6cc7d3acc03 (diff) | |
ide: do complete DMA setup in ->init_dma method (take 2)
* Make ide_hwif_setup_dma() return an error value.
* Pass 'const struct ide_port_info *d' instead of 'unsigned long dmabase'
to ->init_dma method and make it return an error value.
* Rename ide_get_or_set_dma_base() to ide_pci_dma_base(),
change ordering of its arguments and then export it.
* Export ide_pci_set_master().
* Do complete DMA setup inside ->init_dma method and update ->init_dma
users accordingly.
* Sanitize code for DMA setup in ide_init_port().
v2:
* Fix for CONFIG_BLK_DEV_IDEDMA_PCI=n configs
(from Jiri Slaby <jirislaby@gmail.com>):
Fix following compiler warning by returning EINVAL:
In file included from ANYTHING-INCLUDING-IDE.H:45:
include/linux/ide.h: In function ‘ide_hwif_setup_dma’:
include/linux/ide.h:1022: warning: no return statement in function returning non-void
Cc: Jiri Slaby <jirislaby@gmail.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Sergei Shtylyov <sshtylyov@ru.mvista.com>
Signed-off-by: Bartlomiej Zolnierkiewicz <bzolnier@gmail.com>
| -rw-r--r-- | drivers/ide/ide-probe.c | 21 | ||||
| -rw-r--r-- | drivers/ide/pci/alim15x3.c | 27 | ||||
| -rw-r--r-- | drivers/ide/pci/hpt366.c | 27 | ||||
| -rw-r--r-- | drivers/ide/setup-pci.c | 31 | ||||
| -rw-r--r-- | include/linux/ide.h | 14 |
5 files changed, 81 insertions, 39 deletions
diff --git a/drivers/ide/ide-probe.c b/drivers/ide/ide-probe.c index d2faef17e548..e0316869eb6f 100644 --- a/drivers/ide/ide-probe.c +++ b/drivers/ide/ide-probe.c | |||
| @@ -1356,9 +1356,6 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
| 1356 | if (d->init_iops) | 1356 | if (d->init_iops) |
| 1357 | d->init_iops(hwif); | 1357 | d->init_iops(hwif); |
| 1358 | 1358 | ||
| 1359 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) | ||
| 1360 | ide_hwif_setup_dma(hwif, d); | ||
| 1361 | |||
| 1362 | if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || | 1359 | if ((!hwif->irq && (d->host_flags & IDE_HFLAG_LEGACY_IRQS)) || |
| 1363 | (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) | 1360 | (d->host_flags & IDE_HFLAG_FORCE_LEGACY_IRQS)) |
| 1364 | hwif->irq = port ? 15 : 14; | 1361 | hwif->irq = port ? 15 : 14; |
| @@ -1377,9 +1374,21 @@ static void ide_init_port(ide_hwif_t *hwif, unsigned int port, | |||
| 1377 | hwif->mwdma_mask = d->mwdma_mask; | 1374 | hwif->mwdma_mask = d->mwdma_mask; |
| 1378 | hwif->ultra_mask = d->udma_mask; | 1375 | hwif->ultra_mask = d->udma_mask; |
| 1379 | 1376 | ||
| 1380 | /* reset DMA masks only for SFF-style DMA controllers */ | 1377 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0) { |
| 1381 | if ((d->host_flags & IDE_HFLAG_NO_DMA) == 0 && hwif->dma_base == 0) | 1378 | int rc; |
| 1382 | hwif->swdma_mask = hwif->mwdma_mask = hwif->ultra_mask = 0; | 1379 | |
| 1380 | if (d->init_dma) | ||
| 1381 | rc = d->init_dma(hwif, d); | ||
| 1382 | else | ||
| 1383 | rc = ide_hwif_setup_dma(hwif, d); | ||
| 1384 | |||
| 1385 | if (rc < 0) { | ||
| 1386 | printk(KERN_INFO "%s: DMA disabled\n", hwif->name); | ||
| 1387 | hwif->swdma_mask = 0; | ||
| 1388 | hwif->mwdma_mask = 0; | ||
| 1389 | hwif->ultra_mask = 0; | ||
| 1390 | } | ||
| 1391 | } | ||
| 1383 | 1392 | ||
| 1384 | if (d->host_flags & IDE_HFLAG_RQSIZE_256) | 1393 | if (d->host_flags & IDE_HFLAG_RQSIZE_256) |
| 1385 | hwif->rqsize = 256; | 1394 | hwif->rqsize = 256; |
diff --git a/drivers/ide/pci/alim15x3.c b/drivers/ide/pci/alim15x3.c index fbb55fa2d067..5261f308d946 100644 --- a/drivers/ide/pci/alim15x3.c +++ b/drivers/ide/pci/alim15x3.c | |||
| @@ -723,17 +723,32 @@ static void __devinit init_hwif_ali15x3 (ide_hwif_t *hwif) | |||
| 723 | /** | 723 | /** |
| 724 | * init_dma_ali15x3 - set up DMA on ALi15x3 | 724 | * init_dma_ali15x3 - set up DMA on ALi15x3 |
| 725 | * @hwif: IDE interface | 725 | * @hwif: IDE interface |
| 726 | * @dmabase: DMA interface base PCI address | 726 | * @d: IDE port info |
| 727 | * | 727 | * |
| 728 | * Set up the DMA functionality on the ALi 15x3. For the ALi | 728 | * Set up the DMA functionality on the ALi 15x3. |
| 729 | * controllers this is generic so we can let the generic code do | ||
| 730 | * the actual work. | ||
| 731 | */ | 729 | */ |
| 732 | 730 | ||
| 733 | static void __devinit init_dma_ali15x3 (ide_hwif_t *hwif, unsigned long dmabase) | 731 | static int __devinit init_dma_ali15x3(ide_hwif_t *hwif, |
| 732 | const struct ide_port_info *d) | ||
| 734 | { | 733 | { |
| 734 | struct pci_dev *dev = to_pci_dev(hwif->dev); | ||
| 735 | unsigned long base = ide_pci_dma_base(hwif, d); | ||
| 736 | |||
| 737 | if (base == 0 || ide_pci_set_master(dev, d->name) < 0) | ||
| 738 | return -1; | ||
| 739 | |||
| 735 | if (!hwif->channel) | 740 | if (!hwif->channel) |
| 736 | outb(inb(dmabase + 2) & 0x60, dmabase + 2); | 741 | outb(inb(base + 2) & 0x60, base + 2); |
| 742 | |||
| 743 | printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", | ||
| 744 | hwif->name, base, base + 7); | ||
| 745 | |||
| 746 | if (ide_allocate_dma_engine(hwif)) | ||
| 747 | return -1; | ||
| 748 | |||
| 749 | ide_setup_dma(hwif, base); | ||
| 750 | |||
| 751 | return 0; | ||
| 737 | } | 752 | } |
| 738 | 753 | ||
| 739 | static const struct ide_port_ops ali_port_ops = { | 754 | static const struct ide_port_ops ali_port_ops = { |
diff --git a/drivers/ide/pci/hpt366.c b/drivers/ide/pci/hpt366.c index df45098157f6..e5e64436ffd9 100644 --- a/drivers/ide/pci/hpt366.c +++ b/drivers/ide/pci/hpt366.c | |||
| @@ -1327,14 +1327,17 @@ static void __devinit init_hwif_hpt366(ide_hwif_t *hwif) | |||
| 1327 | hwif->dma_lost_irq = &hpt366_dma_lost_irq; | 1327 | hwif->dma_lost_irq = &hpt366_dma_lost_irq; |
| 1328 | } | 1328 | } |
| 1329 | 1329 | ||
| 1330 | static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) | 1330 | static int __devinit init_dma_hpt366(ide_hwif_t *hwif, |
| 1331 | const struct ide_port_info *d) | ||
| 1331 | { | 1332 | { |
| 1332 | struct pci_dev *dev = to_pci_dev(hwif->dev); | 1333 | struct pci_dev *dev = to_pci_dev(hwif->dev); |
| 1333 | u8 masterdma = 0, slavedma = 0; | 1334 | unsigned long flags, base = ide_pci_dma_base(hwif, d); |
| 1334 | u8 dma_new = 0, dma_old = 0; | 1335 | u8 dma_old, dma_new, masterdma = 0, slavedma = 0; |
| 1335 | unsigned long flags; | ||
| 1336 | 1336 | ||
| 1337 | dma_old = inb(dmabase + 2); | 1337 | if (base == 0 || ide_pci_set_master(dev, d->name) < 0) |
| 1338 | return -1; | ||
| 1339 | |||
| 1340 | dma_old = inb(base + 2); | ||
| 1338 | 1341 | ||
| 1339 | local_irq_save(flags); | 1342 | local_irq_save(flags); |
| 1340 | 1343 | ||
| @@ -1345,9 +1348,21 @@ static void __devinit init_dma_hpt366(ide_hwif_t *hwif, unsigned long dmabase) | |||
| 1345 | if (masterdma & 0x30) dma_new |= 0x20; | 1348 | if (masterdma & 0x30) dma_new |= 0x20; |
| 1346 | if ( slavedma & 0x30) dma_new |= 0x40; | 1349 | if ( slavedma & 0x30) dma_new |= 0x40; |
| 1347 | if (dma_new != dma_old) | 1350 | if (dma_new != dma_old) |
| 1348 | outb(dma_new, dmabase + 2); | 1351 | outb(dma_new, base + 2); |
| 1349 | 1352 | ||
| 1350 | local_irq_restore(flags); | 1353 | local_irq_restore(flags); |
| 1354 | |||
| 1355 | printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx\n", | ||
| 1356 | hwif->name, base, base + 7); | ||
| 1357 | |||
| 1358 | hwif->extra_base = base + (hwif->channel ? 8 : 16); | ||
| 1359 | |||
| 1360 | if (ide_allocate_dma_engine(hwif)) | ||
| 1361 | return -1; | ||
| 1362 | |||
| 1363 | ide_setup_dma(hwif, base); | ||
| 1364 | |||
| 1365 | return 0; | ||
| 1351 | } | 1366 | } |
| 1352 | 1367 | ||
| 1353 | static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2) | 1368 | static void __devinit hpt374_init(struct pci_dev *dev, struct pci_dev *dev2) |
diff --git a/drivers/ide/setup-pci.c b/drivers/ide/setup-pci.c index 5006ea98733b..5171601fb255 100644 --- a/drivers/ide/setup-pci.c +++ b/drivers/ide/setup-pci.c | |||
| @@ -72,16 +72,16 @@ static void ide_pci_clear_simplex(unsigned long dma_base, const char *name) | |||
| 72 | } | 72 | } |
| 73 | 73 | ||
| 74 | /** | 74 | /** |
| 75 | * ide_get_or_set_dma_base - setup BMIBA | 75 | * ide_pci_dma_base - setup BMIBA |
| 76 | * @d: IDE port info | ||
| 77 | * @hwif: IDE interface | 76 | * @hwif: IDE interface |
| 77 | * @d: IDE port info | ||
| 78 | * | 78 | * |
| 79 | * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. | 79 | * Fetch the DMA Bus-Master-I/O-Base-Address (BMIBA) from PCI space. |
| 80 | * Where a device has a partner that is already in DMA mode we check | 80 | * Where a device has a partner that is already in DMA mode we check |
| 81 | * and enforce IDE simplex rules. | 81 | * and enforce IDE simplex rules. |
| 82 | */ | 82 | */ |
| 83 | 83 | ||
| 84 | static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_hwif_t *hwif) | 84 | unsigned long ide_pci_dma_base(ide_hwif_t *hwif, const struct ide_port_info *d) |
| 85 | { | 85 | { |
| 86 | struct pci_dev *dev = to_pci_dev(hwif->dev); | 86 | struct pci_dev *dev = to_pci_dev(hwif->dev); |
| 87 | unsigned long dma_base = 0; | 87 | unsigned long dma_base = 0; |
| @@ -132,11 +132,12 @@ static unsigned long ide_get_or_set_dma_base(const struct ide_port_info *d, ide_ | |||
| 132 | out: | 132 | out: |
| 133 | return dma_base; | 133 | return dma_base; |
| 134 | } | 134 | } |
| 135 | EXPORT_SYMBOL_GPL(ide_pci_dma_base); | ||
| 135 | 136 | ||
| 136 | /* | 137 | /* |
| 137 | * Set up BM-DMA capability (PnP BIOS should have done this) | 138 | * Set up BM-DMA capability (PnP BIOS should have done this) |
| 138 | */ | 139 | */ |
| 139 | static int ide_pci_set_master(struct pci_dev *dev, const char *name) | 140 | int ide_pci_set_master(struct pci_dev *dev, const char *name) |
| 140 | { | 141 | { |
| 141 | u16 pcicmd; | 142 | u16 pcicmd; |
| 142 | 143 | ||
| @@ -155,6 +156,7 @@ static int ide_pci_set_master(struct pci_dev *dev, const char *name) | |||
| 155 | 156 | ||
| 156 | return 0; | 157 | return 0; |
| 157 | } | 158 | } |
| 159 | EXPORT_SYMBOL_GPL(ide_pci_set_master); | ||
| 158 | #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ | 160 | #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ |
| 159 | 161 | ||
| 160 | void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d) | 162 | void ide_setup_pci_noise(struct pci_dev *dev, const struct ide_port_info *d) |
| @@ -360,20 +362,17 @@ static ide_hwif_t *ide_hwif_configure(struct pci_dev *dev, | |||
| 360 | * state | 362 | * state |
| 361 | */ | 363 | */ |
| 362 | 364 | ||
| 363 | void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) | 365 | int ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) |
| 364 | { | 366 | { |
| 365 | struct pci_dev *dev = to_pci_dev(hwif->dev); | 367 | struct pci_dev *dev = to_pci_dev(hwif->dev); |
| 366 | 368 | ||
| 367 | if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 || | 369 | if ((d->host_flags & IDE_HFLAG_NO_AUTODMA) == 0 || |
| 368 | ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && | 370 | ((dev->class >> 8) == PCI_CLASS_STORAGE_IDE && |
| 369 | (dev->class & 0x80))) { | 371 | (dev->class & 0x80))) { |
| 370 | unsigned long base = ide_get_or_set_dma_base(d, hwif); | 372 | unsigned long base = ide_pci_dma_base(hwif, d); |
| 371 | 373 | ||
| 372 | if (base == 0 || ide_pci_set_master(dev, d->name) < 0) | 374 | if (base == 0 || ide_pci_set_master(dev, d->name) < 0) |
| 373 | goto out_disabled; | 375 | return -1; |
| 374 | |||
| 375 | if (d->init_dma) | ||
| 376 | d->init_dma(hwif, base); | ||
| 377 | 376 | ||
| 378 | if (hwif->mmio) | 377 | if (hwif->mmio) |
| 379 | printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); | 378 | printk(KERN_INFO " %s: MMIO-DMA\n", hwif->name); |
| @@ -383,15 +382,13 @@ void ide_hwif_setup_dma(ide_hwif_t *hwif, const struct ide_port_info *d) | |||
| 383 | 382 | ||
| 384 | hwif->extra_base = base + (hwif->channel ? 8 : 16); | 383 | hwif->extra_base = base + (hwif->channel ? 8 : 16); |
| 385 | 384 | ||
| 386 | if (ide_allocate_dma_engine(hwif) == 0) | 385 | if (ide_allocate_dma_engine(hwif)) |
| 387 | ide_setup_dma(hwif, base); | 386 | return -1; |
| 388 | } | ||
| 389 | 387 | ||
| 390 | return; | 388 | ide_setup_dma(hwif, base); |
| 389 | } | ||
| 391 | 390 | ||
| 392 | out_disabled: | 391 | return 0; |
| 393 | printk(KERN_INFO "%s: Bus-Master DMA disabled (BIOS) on %s\n", | ||
| 394 | d->name, pci_name(dev)); | ||
| 395 | } | 392 | } |
| 396 | #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ | 393 | #endif /* CONFIG_BLK_DEV_IDEDMA_PCI */ |
| 397 | 394 | ||
diff --git a/include/linux/ide.h b/include/linux/ide.h index b8a9d3b4d633..2da46af64604 100644 --- a/include/linux/ide.h +++ b/include/linux/ide.h | |||
| @@ -1007,10 +1007,15 @@ void ide_pci_setup_ports(struct pci_dev *, const struct ide_port_info *, int, u8 | |||
| 1007 | void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); | 1007 | void ide_setup_pci_noise(struct pci_dev *, const struct ide_port_info *); |
| 1008 | 1008 | ||
| 1009 | #ifdef CONFIG_BLK_DEV_IDEDMA_PCI | 1009 | #ifdef CONFIG_BLK_DEV_IDEDMA_PCI |
| 1010 | void ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *); | 1010 | int ide_pci_set_master(struct pci_dev *, const char *); |
| 1011 | unsigned long ide_pci_dma_base(ide_hwif_t *, const struct ide_port_info *); | ||
| 1012 | int ide_hwif_setup_dma(ide_hwif_t *, const struct ide_port_info *); | ||
| 1011 | #else | 1013 | #else |
| 1012 | static inline void ide_hwif_setup_dma(ide_hwif_t *hwif, | 1014 | static inline int ide_hwif_setup_dma(ide_hwif_t *hwif, |
| 1013 | const struct ide_port_info *d) { } | 1015 | const struct ide_port_info *d) |
| 1016 | { | ||
| 1017 | return -EINVAL; | ||
| 1018 | } | ||
| 1014 | #endif | 1019 | #endif |
| 1015 | 1020 | ||
| 1016 | extern void default_hwif_iops(ide_hwif_t *); | 1021 | extern void default_hwif_iops(ide_hwif_t *); |
| @@ -1103,7 +1108,8 @@ struct ide_port_info { | |||
| 1103 | unsigned int (*init_chipset)(struct pci_dev *, const char *); | 1108 | unsigned int (*init_chipset)(struct pci_dev *, const char *); |
| 1104 | void (*init_iops)(ide_hwif_t *); | 1109 | void (*init_iops)(ide_hwif_t *); |
| 1105 | void (*init_hwif)(ide_hwif_t *); | 1110 | void (*init_hwif)(ide_hwif_t *); |
| 1106 | void (*init_dma)(ide_hwif_t *, unsigned long); | 1111 | int (*init_dma)(ide_hwif_t *, |
| 1112 | const struct ide_port_info *); | ||
| 1107 | 1113 | ||
| 1108 | const struct ide_port_ops *port_ops; | 1114 | const struct ide_port_ops *port_ops; |
| 1109 | 1115 | ||
