Hello.
Sergei Shtylylov wrote:
Resolve several IDE DMA resource management issues:
- release DMA engine for memory mapped DMA as well
- release the same number of DMA I/O ports that was requested by a driver
- release the channel's secondary DMA I/O ports for real
- claim extra DMA I/O ports regardless of what IDE channels are
present/enabled
- merge the duplicate code into ide_dma_iobase()
Added missing request_resource() result check noticed by Alan.
Removed useless code in ide_allocate_dma_engine().
WBR, Sergei
Signed-off-by: Sergei Shtylyov <sshtylyov@xxxxxxxxxxxxx>
diff --git a/drivers/ide/ide-dma.c b/drivers/ide/ide-dma.c
index 0523da7..ce49912 100644
--- a/drivers/ide/ide-dma.c
+++ b/drivers/ide/ide-dma.c
@@ -800,26 +800,25 @@ static int ide_release_dma_engine(ide_hw
static int ide_release_iomio_dma(ide_hwif_t *hwif)
{
- if ((hwif->dma_extra) && (hwif->channel == 0))
- release_region((hwif->dma_base + 16), hwif->dma_extra);
- release_region(hwif->dma_base, 8);
+ release_region(hwif->dma_base, hwif->dma_ports);
+ if (hwif->extra_base)
+ release_region(hwif->extra_base, hwif->extra_ports);
if (hwif->dma_base2)
- release_region(hwif->dma_base, 8);
+ release_region(hwif->dma_base2, hwif->dma_ports);
return 1;
}
/*
* Needed for allowing full modular support of ide-driver
*/
-int ide_release_dma (ide_hwif_t *hwif)
+int ide_release_dma(ide_hwif_t *hwif)
{
+ ide_release_dma_engine(hwif);
+
if (hwif->mmio == 2)
return 1;
- if (hwif->chipset == ide_etrax100)
- return 1;
-
- ide_release_dma_engine(hwif);
- return ide_release_iomio_dma(hwif);
+ else
+ return ide_release_iomio_dma(hwif);
}
static int ide_allocate_dma_engine(ide_hwif_t *hwif)
@@ -831,25 +830,15 @@ static int ide_allocate_dma_engine(ide_h
if (hwif->dmatable_cpu)
return 0;
- printk(KERN_ERR "%s: -- Error, unable to allocate%s DMA table(s).\n",
- hwif->cds->name, !hwif->dmatable_cpu ? " CPU" : "");
+ printk(KERN_ERR "%s: -- Error, unable to allocate CPU DMA table(s).\n",
+ hwif->cds->name);
- ide_release_dma_engine(hwif);
return 1;
}
static int ide_mapped_mmio_dma(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
{
- printk(KERN_INFO " %s: MMIO-DMA ", hwif->name);
-
- hwif->dma_base = base;
- if (hwif->cds->extra && hwif->channel == 0)
- hwif->dma_extra = hwif->cds->extra;
-
- if(hwif->mate)
- hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
- else
- hwif->dma_master = base;
+ printk(KERN_INFO " %s: MMIO-DMA at 0x%08lx", hwif->name, base);
return 0;
}
@@ -857,43 +846,54 @@ static int ide_iomio_dma(ide_hwif_t *hwi
{
printk(KERN_INFO " %s: BM-DMA at 0x%04lx-0x%04lx",
hwif->name, base, base + ports - 1);
+
if (!request_region(base, ports, hwif->name)) {
printk(" -- Error, ports in use.\n");
return 1;
}
- hwif->dma_base = base;
- if ((hwif->cds->extra) && (hwif->channel == 0)) {
- request_region(base+16, hwif->cds->extra, hwif->cds->name);
- hwif->dma_extra = hwif->cds->extra;
- }
-
- if(hwif->mate)
- hwif->dma_master = (hwif->channel) ? hwif->mate->dma_base : base;
- else
- hwif->dma_master = base;
- if (hwif->dma_base2) {
- if (!request_region(hwif->dma_base2, ports, hwif->name))
- {
- printk(" -- Error, secondary ports in use.\n");
- release_region(base, ports);
- return 1;
- }
+
+ if (hwif->dma_base2 &&
+ !request_region(hwif->dma_base2, ports, hwif->name)) {
+ release_region(base, ports);
+ printk(" -- Error, secondary ports in use.\n");
+ return 1;
+ }
+
+ if (hwif->extra_base &&
+ !request_region(hwif->extra_base, hwif->extra_ports, hwif->cds->name)) {
+ release_region(base, ports);
+ if (hwif->dma_base2)
+ release_region(hwif->dma_base2, ports);
+ printk(" -- Error, extra ports in use.\n");
+ return 1;
}
return 0;
}
static int ide_dma_iobase(ide_hwif_t *hwif, unsigned long base, unsigned int ports)
{
- if (hwif->mmio == 2)
- return ide_mapped_mmio_dma(hwif, base,ports);
BUG_ON(hwif->mmio == 1);
- return ide_iomio_dma(hwif, base, ports);
+
+ hwif->dma_base = base;
+ hwif->dma_ports = ports;
+
+ if (hwif->cds->extra && !(hwif->mate && hwif->mate->extra_base)) {
+ hwif->extra_base = base + (hwif->channel ? 8 : 16);
+ hwif->extra_ports = hwif->cds->extra;
+ }
+
+ hwif->dma_master = (hwif->channel && hwif->mate) ? hwif->mate->dma_base : base;
+
+ if (hwif->mmio == 2)
+ return ide_mapped_mmio_dma(hwif, base, ports);
+ else
+ return ide_iomio_dma(hwif, base, ports);
}
/*
* This can be called for a dynamically installed interface. Don't __init it
*/
-void ide_setup_dma (ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
+void ide_setup_dma(ide_hwif_t *hwif, unsigned long dma_base, unsigned int num_ports)
{
if (ide_dma_iobase(hwif, dma_base, num_ports))
return;
@@ -903,16 +903,16 @@ void ide_setup_dma (ide_hwif_t *hwif, un
return;
}
- if (!(hwif->dma_command))
+ if (!hwif->dma_command)
hwif->dma_command = hwif->dma_base;
- if (!(hwif->dma_vendor1))
- hwif->dma_vendor1 = (hwif->dma_base + 1);
- if (!(hwif->dma_status))
- hwif->dma_status = (hwif->dma_base + 2);
- if (!(hwif->dma_vendor3))
- hwif->dma_vendor3 = (hwif->dma_base + 3);
- if (!(hwif->dma_prdtable))
- hwif->dma_prdtable = (hwif->dma_base + 4);
+ if (!hwif->dma_vendor1)
+ hwif->dma_vendor1 = hwif->dma_base + 1;
+ if (!hwif->dma_status)
+ hwif->dma_status = hwif->dma_base + 2;
+ if (!hwif->dma_vendor3)
+ hwif->dma_vendor3 = hwif->dma_base + 3;
+ if (!hwif->dma_prdtable)
+ hwif->dma_prdtable = hwif->dma_base + 4;
if (!hwif->ide_dma_off_quietly)
hwif->ide_dma_off_quietly = &__ide_dma_off_quietly;
@@ -947,7 +947,7 @@ void ide_setup_dma (ide_hwif_t *hwif, un
}
printk("\n");
- if (!(hwif->dma_master))
+ if (!hwif->dma_master)
BUG();
}
diff --git a/drivers/ide/ide.c b/drivers/ide/ide.c
index b2cc437..5c31f2a 100644
--- a/drivers/ide/ide.c
+++ b/drivers/ide/ide.c
@@ -452,7 +452,7 @@ void ide_hwif_release_regions(ide_hwif_t
* @hwif: hwif to update
* @tmp_hwif: template
*
- * Restore hwif to a previous state by copying most settngs
+ * Restore hwif to a previous state by copying most settings
* from the template.
*/
@@ -540,8 +540,11 @@ static void ide_hwif_restore(ide_hwif_t
hwif->dma_status = tmp_hwif->dma_status;
hwif->dma_vendor3 = tmp_hwif->dma_vendor3;
hwif->dma_prdtable = tmp_hwif->dma_prdtable;
+ hwif->dma_base2 = tmp_hwif->dma_base2;
+ hwif->extra_base = tmp_hwif->extra_base;
- hwif->dma_extra = tmp_hwif->dma_extra;
+ hwif->dma_ports = tmp_hwif->dma_ports;
+ hwif->extra_ports = tmp_hwif->extra_ports;
hwif->config_data = tmp_hwif->config_data;
hwif->select_data = tmp_hwif->select_data;
hwif->autodma = tmp_hwif->autodma;
@@ -552,7 +555,7 @@ static void ide_hwif_restore(ide_hwif_t
}
/**
- * ide_unregister - free an ide interface
+ * ide_unregister - free an IDE interface
* @index: index of interface (will change soon to a pointer)
*
* Perform the final unregister of an IDE interface. At the moment
@@ -565,8 +568,8 @@ static void ide_hwif_restore(ide_hwif_t
* deadlocking the IDE layer. The shutdown callback is called
* before we take the lock and free resources. It is up to the
* caller to be sure there is no pending I/O here, and that
- * the interfce will not be reopened (present/vanishing locking
- * isnt yet done btw). After we commit to the final kill we
+ * the interface will not be reopened (present/vanishing locking
+ * isn't yet done BTW). After we commit to the final kill we
* call the cleanup callback with the ide locks held.
*
* Unregister restores the hwif structures to the default state.
diff --git a/include/linux/ide.h b/include/linux/ide.h
index a7fc4cc..122cb54 100644
--- a/include/linux/ide.h
+++ b/include/linux/ide.h
@@ -774,8 +774,10 @@ typedef struct hwif_s {
unsigned long dma_vendor3; /* dma vendor 3 register */
unsigned long dma_prdtable; /* actual prd table address */
unsigned long dma_base2; /* extended base addr for dma ports */
+ unsigned long extra_base; /* extra addr for dma ports */
- unsigned dma_extra; /* extra addr for dma ports */
+ unsigned dma_ports; /* number of dma ports */
+ unsigned extra_ports; /* number of extra dma ports */
unsigned long config_data; /* for use by chipset-specific code */
unsigned long select_data; /* for use by chipset-specific code */