Re: [PATCH] Fix IDE DMA resource managment

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



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 */
 


[Index of Archives]     [Linux Filesystems]     [Linux SCSI]     [Linux RAID]     [Git]     [Kernel Newbies]     [Linux Newbie]     [Security]     [Netfilter]     [Bugtraq]     [Yosemite News]     [MIPS Linux]     [ARM Linux]     [Linux Security]     [Samba]     [Device Mapper]

  Powered by Linux