From: Tomas Henzl <thenzl@redhat.com> Date: Fri, 17 Apr 2009 14:53:29 +0300 Subject: [scsi] make fusion MPT driver legacy I/O port free Message-id: 49E86DB9.6060408@redhat.com O-Subject: [RHEL5.4 PATCH2/3] Make fusion MPT driver legacy I/O port free Bugzilla: 475451 RH-Acked-by: David Milburn <dmilburn@redhat.com> Resolves bz475451 This patch modifies the I/O resource allocation behavior of FUSION driver. The current version of driver allocates the I/O resources even if they are not required and this creates trouble in low resource environments. This driver now uses pci_enable_device_mem/pci_enable_device functions to differentiate the resource allocations. Backport from upstream. diff --git a/drivers/message/fusion/mptbase.c b/drivers/message/fusion/mptbase.c index a8ddb7c..229e2a5 100644 --- a/drivers/message/fusion/mptbase.c +++ b/drivers/message/fusion/mptbase.c @@ -1671,13 +1671,19 @@ mpt_mapresources(MPT_ADAPTER *ioc) struct pci_dev *pdev; pdev = ioc->pcidev; - - if (pci_enable_device(pdev)) { - printk(MYIOC_s_WARN_FMT "pci_enable_device: failed\n", - ioc->name); + ioc->bars = pci_select_bars(pdev, IORESOURCE_MEM); + if (pci_enable_device_mem(pdev)) { + printk(MYIOC_s_ERR_FMT "pci_enable_device_mem() " + "failed\n", ioc->name); + return r; + } + if (pci_request_selected_regions(pdev, ioc->bars, "mpt")) { + printk(MYIOC_s_ERR_FMT "pci_request_selected_regions() with " + "MEM failed\n", ioc->name); return r; } + pci_read_config_byte(pdev, PCI_CLASS_REVISION, &revision); if (sizeof(dma_addr_t) > 4) { @@ -1699,6 +1705,7 @@ mpt_mapresources(MPT_ADAPTER *ioc) } else { printk(MYIOC_s_WARN_FMT "no suitable DMA mask for %s\n", ioc->name, pci_name(pdev)); + pci_release_selected_regions(pdev, ioc->bars); return r; } } else { @@ -1741,6 +1748,7 @@ mpt_mapresources(MPT_ADAPTER *ioc) if (mem == NULL) { printk(MYIOC_s_ERR_FMT ": ERROR - Unable to map adapter" " memory!\n", ioc->name); + pci_release_selected_regions(pdev, ioc->bars); return -EINVAL; } ioc->memmap = mem; @@ -1878,6 +1886,7 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) if (!ioc->reset_work_q) { printk(MYIOC_s_ERR_FMT "Insufficient memory to add adapter!\n", ioc->name); + pci_release_selected_regions(pdev, ioc->bars); kfree(ioc); return -ENOMEM; } @@ -2000,6 +2009,9 @@ mpt_attach(struct pci_dev *pdev, const struct pci_device_id *id) if (ioc->alt_ioc) ioc->alt_ioc->alt_ioc = NULL; iounmap(ioc->memmap); + if (r != -5) + pci_release_selected_regions(pdev, ioc->bars); + destroy_workqueue(ioc->reset_work_q); ioc->reset_work_q = NULL; @@ -2139,6 +2151,7 @@ mpt_suspend(struct pci_dev *pdev, pm_message_t state) ioc->pci_irq = -1; pci_save_state(pdev); pci_disable_device(pdev); + pci_release_selected_regions(pdev, ioc->bars); pci_set_power_state(pdev, device_state); return 0; } @@ -2254,7 +2267,8 @@ mpt_signal_reset(u8 index, MPT_ADAPTER *ioc, int reset_phase) * -2 if READY but IOCFacts Failed * -3 if READY but PrimeIOCFifos Failed * -4 if READY but IOCInit Failed - * -5 if failed to upload firmware + * -5 if failed to enable_device and/or request_selected_regions + * -6 if failed to upload firmware */ static int mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) @@ -2353,6 +2367,18 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } } + if ((ret == 0) && (reason == MPT_HOSTEVENT_IOC_BRINGUP) && + (ioc->facts.Flags & MPI_IOCFACTS_FLAGS_FW_DOWNLOAD_BOOT)) { + pci_release_selected_regions(ioc->pcidev, ioc->bars); + ioc->bars = pci_select_bars(ioc->pcidev, IORESOURCE_MEM | + IORESOURCE_IO); + if (pci_enable_device(ioc->pcidev)) + return -5; + if (pci_request_selected_regions(ioc->pcidev, ioc->bars, + "mpt")) + return -5; + } + /* * Device is reset now. It must have de-asserted the interrupt line * (if it was asserted) and it should be safe to register for the @@ -2439,7 +2465,7 @@ mpt_do_ioc_recovery(MPT_ADAPTER *ioc, u32 reason, int sleepFlag) } else { printk(MYIOC_s_WARN_FMT "firmware upload failure!\n", ioc->name); - ret = -5; + ret = -6; } } } @@ -2768,6 +2794,7 @@ mpt_adapter_dispose(MPT_ADAPTER *ioc) } pci_disable_device(ioc->pcidev); + pci_release_selected_regions(ioc->pcidev, ioc->bars); #if defined(CONFIG_MTRR) && 0 if (ioc->mtrr_reg > 0) { diff --git a/drivers/message/fusion/mptbase.h b/drivers/message/fusion/mptbase.h index f0b6d2f..0c77460 100644 --- a/drivers/message/fusion/mptbase.h +++ b/drivers/message/fusion/mptbase.h @@ -641,6 +641,7 @@ typedef struct _MPT_ADAPTER dma_addr_t HostPageBuffer_dma; int mtrr_reg; struct pci_dev *pcidev; /* struct pci_dev pointer */ + int bars; /* bitmask of BAR's that must be configured */ int msi_enable; u8 __iomem *memmap; /* mmap address */ struct Scsi_Host *sh; /* Scsi Host pointer */