aic7xxx: fix MMIO for PPC 44x platforms
Subsystems (2)
PATCH 1/2 aic7xxx: fix MMIO for PPC 44x platforms
The driver stores the PCI resource address into 'u_long' variable before calling ioremap_nocache() on it. This warrants kernel oops when the registers are accessed on PPC 44x platforms which (being 32-bit) have PCI memory space mapped beyond 4 GB.
The arch/ppc/ kernel has a fixup in ioremap() that helps create an illusion that the PCI memory resources are mapped below 4 GB, but arch/powerpc/ code got rid of this trick, having instead CONFIG_RESOURCES_64BIT enabled.
---
Reworked to address James' comments.
This is the same issue as the one that has been recently addressed by commits 3c34ac36ac1084e571ef9b6fb1d6a5b10ccc1fd0 (e1000: Fix for 32 bits platforms with 64 bits resources) and c976816b6e901341ec3c4653147316c15549a1c4 (siimage: fix kernel oops on PPC 44x). The patch has only been compile tested though...
drivers/scsi/aic7xxx/aic7xxx_osm.h | 2 +- drivers/scsi/aic7xxx/aic7xxx_osm_pci.c | 18 +++++++++--------- 2 files changed, 10 insertions(+), 10 deletions(-)
drivers/scsi/aic7xxx/aic7xxx_osm.h +1 -1
@@ -365,7 +365,7 @@ struct ahc_platform_data {#define AHC_LINUX_NOIRQ ((uint32_t)~0)uint32_t irq;/* IRQ for this adapter */ uint32_t bios_address; -uint32_t mem_busaddr;/* Mem Base Addr */ +resource_size_t mem_busaddr;/* Mem Base Addr */ };/************************** OS Utility Wrappers *******************************/
drivers/scsi/aic7xxx/aic7xxx_osm_pci.c +9 -9
@@ -293,7 +293,7 @@ ahc_linux_pci_exit(void) }static int -ahc_linux_pci_reserve_io_region (struct ahc_softc *ahc,u_long *base) +ahc_linux_pci_reserve_io_region (struct ahc_softc *ahc,resource_size_t *base) {if (aic7xxx_allow_memio ==0 )return (ENOMEM );
@@ -308,10 +308,10 @@ ahc_linux_pci_reserve_io_region(struct astatic int ahc_linux_pci_reserve_mem_region (struct ahc_softc *ahc, -u_long *bus_addr, +resource_size_t *bus_addr,uint8_t __iomem **maddr) { -u_long start; +resource_size_t start;int error; error =0 ;
@@ -336,7 +336,7 @@ int ahc_pci_map_registers(struct ahc_softc *ahc) {uint32_t command; -u_long base; +resource_size_t base;uint8_t __iomem *maddr;int error;
@@ -374,12 +374,12 @@ ahc_pci_map_registers(struct ahc_softc * }else command |=PCIM_CMD_MEMEN ; }else { -printf ("aic7xxx: PCI%d:%d:%d MEM region 0x%lx " +printf ("aic7xxx: PCI%d:%d:%d MEM region 0x%llx " "unavailable. Cannot memory map device.\n" ,ahc_get_pci_bus (ahc->dev_softc),ahc_get_pci_slot (ahc->dev_softc),ahc_get_pci_function (ahc->dev_softc), - base); + (unsigned long long )base); }/*
@@ -390,15 +390,15 @@ ahc_pci_map_registers(struct ahc_softc * error =ahc_linux_pci_reserve_io_region (ahc, &base);if (error ==0 ) { ahc->tag =BUS_SPACE_PIO ; - ahc->bsh.ioport = base; + ahc->bsh.ioport = (u_long )base; command |=PCIM_CMD_PORTEN ; }else { -printf ("aic7xxx: PCI%d:%d:%d IO region 0x%lx[0..255] " +printf ("aic7xxx: PCI%d:%d:%d IO region 0x%llx[0..255] " "unavailable. Cannot map device.\n" ,ahc_get_pci_bus (ahc->dev_softc),ahc_get_pci_slot (ahc->dev_softc),ahc_get_pci_function (ahc->dev_softc), - base); + (unsigned long long )base); } }ahc_pci_write_config (ahc->dev_softc,PCIR_COMMAND , command,4 );