Commit eb728f67 authored by Bartlomiej Zolnierkiewicz's avatar Bartlomiej Zolnierkiewicz Committed by Jeff Garzik

[PATCH] ide: proper allocation of hwif->io_ports resources

parent cd492197
...@@ -634,64 +634,8 @@ static inline u8 probe_for_drive (ide_drive_t *drive) ...@@ -634,64 +634,8 @@ static inline u8 probe_for_drive (ide_drive_t *drive)
return drive->present; return drive->present;
} }
static int hwif_check_region(ide_hwif_t *hwif, unsigned long addr, int num)
{
int err;
if(hwif->mmio)
err = check_mem_region(addr, num);
else
err = check_region(addr, num);
if(err)
{
printk("%s: %s resource 0x%lX-0x%lX not free.\n",
hwif->name, hwif->mmio?"MMIO":"I/O", addr, addr+num-1);
}
return err;
}
/**
* hwif_check_regions - check resources for IDE
* @hwif: interface to use
*
* Checks if all the needed resources for an interface are free
* providing the interface is PIO. Right now core IDE code does
* this work which is deeply wrong. MMIO leaves it to the controller
* driver, PIO will migrate this way over time
*/
static int hwif_check_regions (ide_hwif_t *hwif)
{
u32 i = 0;
int addr_errs = 0;
if (hwif->mmio == 2)
return 0;
addr_errs = hwif_check_region(hwif, hwif->io_ports[IDE_DATA_OFFSET], 1);
for (i = IDE_ERROR_OFFSET; i <= IDE_STATUS_OFFSET; i++)
addr_errs += hwif_check_region(hwif, hwif->io_ports[i], 1);
if (hwif->io_ports[IDE_CONTROL_OFFSET])
addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_CONTROL_OFFSET], 1);
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
if (hwif->io_ports[IDE_IRQ_OFFSET])
addr_errs += hwif_check_region(hwif, hwif->io_ports[IDE_IRQ_OFFSET], 1);
#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
/* If any errors are return, we drop the hwif interface. */
hwif->straight8 = 0;
return(addr_errs);
}
//EXPORT_SYMBOL(hwif_check_regions);
#define hwif_request_region(addr, num, name) \
((hwif->mmio) ? request_mem_region((addr),(num),(name)) : request_region((addr),(num),(name)))
static void hwif_register (ide_hwif_t *hwif) static void hwif_register (ide_hwif_t *hwif)
{ {
u32 i = 0;
/* register with global device tree */ /* register with global device tree */
strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE); strlcpy(hwif->gendev.bus_id,hwif->name,BUS_ID_SIZE);
snprintf(hwif->gendev.name,DEVICE_NAME_SIZE,"IDE Controller"); snprintf(hwif->gendev.name,DEVICE_NAME_SIZE,"IDE Controller");
...@@ -701,24 +645,6 @@ static void hwif_register (ide_hwif_t *hwif) ...@@ -701,24 +645,6 @@ static void hwif_register (ide_hwif_t *hwif)
else else
hwif->gendev.parent = NULL; /* Would like to do = &device_legacy */ hwif->gendev.parent = NULL; /* Would like to do = &device_legacy */
device_register(&hwif->gendev); device_register(&hwif->gendev);
if (hwif->mmio == 2)
return;
if (hwif->io_ports[IDE_CONTROL_OFFSET])
hwif_request_region(hwif->io_ports[IDE_CONTROL_OFFSET], 1, hwif->name);
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
if (hwif->io_ports[IDE_IRQ_OFFSET])
hwif_request_region(hwif->io_ports[IDE_IRQ_OFFSET], 1, hwif->name);
#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
if (((unsigned long)hwif->io_ports[IDE_DATA_OFFSET] | 7) ==
((unsigned long)hwif->io_ports[IDE_STATUS_OFFSET])) {
hwif_request_region(hwif->io_ports[IDE_DATA_OFFSET], 8, hwif->name);
hwif->straight8 = 1;
return;
}
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++)
hwif_request_region(hwif->io_ports[i], 1, hwif->name);
} }
//EXPORT_SYMBOL(hwif_register); //EXPORT_SYMBOL(hwif_register);
...@@ -778,7 +704,7 @@ void probe_hwif (ide_hwif_t *hwif) ...@@ -778,7 +704,7 @@ void probe_hwif (ide_hwif_t *hwif)
#ifdef CONFIG_BLK_DEV_PDC4030 #ifdef CONFIG_BLK_DEV_PDC4030
(hwif->chipset != ide_pdc4030 || hwif->channel == 0) && (hwif->chipset != ide_pdc4030 || hwif->channel == 0) &&
#endif /* CONFIG_BLK_DEV_PDC4030 */ #endif /* CONFIG_BLK_DEV_PDC4030 */
(hwif_check_regions(hwif))) { (ide_hwif_request_regions(hwif))) {
u16 msgout = 0; u16 msgout = 0;
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit]; ide_drive_t *drive = &hwif->drives[unit];
...@@ -869,6 +795,11 @@ void probe_hwif (ide_hwif_t *hwif) ...@@ -869,6 +795,11 @@ void probe_hwif (ide_hwif_t *hwif)
if (irqd) if (irqd)
enable_irq(irqd); enable_irq(irqd);
if (!hwif->present) {
ide_hwif_release_regions(hwif);
return;
}
for (unit = 0; unit < MAX_DRIVES; ++unit) { for (unit = 0; unit < MAX_DRIVES; ++unit) {
ide_drive_t *drive = &hwif->drives[unit]; ide_drive_t *drive = &hwif->drives[unit];
int enable_dma = 1; int enable_dma = 1;
......
...@@ -508,12 +508,87 @@ ide_proc_entry_t generic_subdriver_entries[] = { ...@@ -508,12 +508,87 @@ ide_proc_entry_t generic_subdriver_entries[] = {
}; };
#endif #endif
static struct resource* hwif_request_region(ide_hwif_t *hwif,
unsigned long addr, int num)
{
struct resource *res;
if (hwif->mmio)
res = request_mem_region(addr, num, hwif->name);
else
res = request_region(addr, num, hwif->name);
if (!res)
printk(KERN_ERR "%s: %s resource 0x%lX-0x%lX not free.\n",
hwif->name, hwif->mmio ? "MMIO" : "I/O",
addr, addr+num-1);
return res;
}
#define hwif_release_region(addr, num) \ #define hwif_release_region(addr, num) \
((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num))) ((hwif->mmio) ? release_mem_region((addr),(num)) : release_region((addr),(num)))
/** /**
* hwif_unregister - free IDE resources * ide_hwif_request_regions - request resources for IDE
* @hwif: interface to use
*
* Requests all the needed resources for an interface.
* Right now core IDE code does this work which is deeply wrong.
* MMIO leaves it to the controller driver,
* PIO will migrate this way over time.
*/
int ide_hwif_request_regions(ide_hwif_t *hwif)
{
unsigned long addr;
unsigned int i;
if (hwif->mmio == 2)
return 0;
addr = hwif->io_ports[IDE_CONTROL_OFFSET];
if (addr && !hwif_request_region(hwif, addr, 1))
goto control_region_busy;
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
addr = hwif->io_ports[IDE_IRQ_OFFSET];
if (addr && !hwif_request_region(hwif, addr, 1))
goto irq_region_busy;
#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
hwif->straight8 = 0;
addr = hwif->io_ports[IDE_DATA_OFFSET];
if ((addr | 7) == hwif->io_ports[IDE_STATUS_OFFSET]) {
if (!hwif_request_region(hwif, addr, 8))
goto data_region_busy;
hwif->straight8 = 1;
return 0;
}
for (i = IDE_DATA_OFFSET; i <= IDE_STATUS_OFFSET; i++) {
addr = hwif->io_ports[i];
if (!hwif_request_region(hwif, addr, 1)) {
while (--i)
hwif_release_region(addr, 1);
goto data_region_busy;
}
}
return 0;
data_region_busy:
#if defined(CONFIG_AMIGA) || defined(CONFIG_MAC)
addr = hwif->io_ports[IDE_IRQ_OFFSET];
if (addr)
hwif_release_region(addr, 1);
irq_region_busy:
#endif /* (CONFIG_AMIGA) || (CONFIG_MAC) */
addr = hwif->io_ports[IDE_CONTROL_OFFSET];
if (addr)
hwif_release_region(addr, 1);
control_region_busy:
/* If any errors are return, we drop the hwif interface. */
return -EBUSY;
}
EXPORT_SYMBOL(ide_hwif_request_regions);
/**
* ide_hwif_release_regions - free IDE resources
* *
* Note that we only release the standard ports, * Note that we only release the standard ports,
* and do not even try to handle any extra ports * and do not even try to handle any extra ports
...@@ -523,8 +598,7 @@ ide_proc_entry_t generic_subdriver_entries[] = { ...@@ -523,8 +598,7 @@ ide_proc_entry_t generic_subdriver_entries[] = {
* importantly our caller should be doing this so we need to * importantly our caller should be doing this so we need to
* restructure this as a helper function for drivers. * restructure this as a helper function for drivers.
*/ */
void ide_hwif_release_regions(ide_hwif_t *hwif)
void hwif_unregister (ide_hwif_t *hwif)
{ {
u32 i = 0; u32 i = 0;
...@@ -548,7 +622,7 @@ void hwif_unregister (ide_hwif_t *hwif) ...@@ -548,7 +622,7 @@ void hwif_unregister (ide_hwif_t *hwif)
} }
} }
EXPORT_SYMBOL(hwif_unregister); EXPORT_SYMBOL(ide_hwif_release_regions);
extern void init_hwif_data(unsigned int index); extern void init_hwif_data(unsigned int index);
...@@ -635,7 +709,7 @@ void ide_unregister (unsigned int index) ...@@ -635,7 +709,7 @@ void ide_unregister (unsigned int index)
* and do not even try to handle any extra ports * and do not even try to handle any extra ports
* allocated for weird IDE interface chipsets. * allocated for weird IDE interface chipsets.
*/ */
hwif_unregister(hwif); ide_hwif_release_regions(hwif);
/* /*
* Remove us from the hwgroup, and free * Remove us from the hwgroup, and free
......
...@@ -1776,7 +1776,8 @@ static inline int __ide_dma_queued_off(ide_drive_t *drive) ...@@ -1776,7 +1776,8 @@ static inline int __ide_dma_queued_off(ide_drive_t *drive)
static inline void ide_release_dma(ide_hwif_t *drive) {;} static inline void ide_release_dma(ide_hwif_t *drive) {;}
#endif #endif
extern void hwif_unregister(ide_hwif_t *); extern int ide_hwif_request_regions(ide_hwif_t *hwif);
extern void ide_hwif_release_regions(ide_hwif_t* hwif);
extern void ide_unregister (unsigned int index); extern void ide_unregister (unsigned int index);
extern void export_ide_init_queue(ide_drive_t *); extern void export_ide_init_queue(ide_drive_t *);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment