From c5e240b44f4fb18fa09f3ef2eae65fd6dba4bea1 Mon Sep 17 00:00:00 2001 From: Stanislaw Gruszka Date: Tue, 12 Feb 2008 11:08:06 +0000 Subject: [PATCH] Synchronize with Feral CVS repository: - Add a missing MSI disable and provide for pre-2.6.8 kernels. - Fix bugs- forgot to actually compile (shame on me). git-svn-id: http://svn.code.sf.net/p/scst/svn/trunk@283 d57e44dd-8a1f-0410-8b47-8ef2f437770f --- qla_isp/linux/isp_pci.c | 114 +++++++++++++++++++++++++++++----------- 1 file changed, 84 insertions(+), 30 deletions(-) diff --git a/qla_isp/linux/isp_pci.c b/qla_isp/linux/isp_pci.c index fe26c77eb..a31dc5486 100644 --- a/qla_isp/linux/isp_pci.c +++ b/qla_isp/linux/isp_pci.c @@ -1,4 +1,4 @@ -/* $Id: isp_pci.c,v 1.155 2008/01/25 22:23:15 mjacob Exp $ */ +/* $Id: isp_pci.c,v 1.158 2008/01/26 00:14:12 mjacob Exp $ */ /* * Copyright (c) 1997-2007 by Matthew Jacob * All rights reserved. @@ -349,8 +349,17 @@ struct isp_pcisoftc { void * vaddr; /* Mapped Memory Address */ vm_offset_t voff; vm_offset_t poff[_NREG_BLKS]; - int msi_enable; + u32 msix_vector : 16, + : 13, + msix_enabled : 2, + msi_enabled : 1; }; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,6,8) +#define pci_enable_msi(x) -ENXIO +#define pci_enable_msix(x) -ENXIO +#define pci_disable_msi(x) do { ; } while(0) +#define pci_disable_msix(x) do { ; } while(0) +#endif /* * Gratefully borrowed from Gerard Roudier's sym53c8xx driver @@ -409,20 +418,33 @@ void isplinux_pci_release(struct Scsi_Host *host) { ispsoftc_t *isp = ISP_HOST2ISP(host); - struct isp_pcisoftc *pcs = (struct isp_pcisoftc *) isp; + struct isp_pcisoftc *isp_pci = (struct isp_pcisoftc *) isp; int i; - pci_disable_device(pcs->pci_dev); - free_irq(host->irq, pcs); - if (pcs->vaddr != 0) { - unmap_pci_mem(pcs, 0xff); - pcs->vaddr = 0; - } else if (pcs->port) { - release_region(pcs->port, 0xff); - pcs->port = 0; + if (host->irq) { + free_irq(host->irq, isp_pci); + host->irq = 0; + } + if (isp_pci->msix_enabled) { + if (isp_pci->msix_enabled > 1) { + free_irq(isp_pci->msix_vector, isp_pci); + } + pci_disable_msix(isp_pci->pci_dev); + isp_pci->msix_enabled = 0; + } + if (isp_pci->msi_enabled) { + pci_disable_msi(isp_pci->pci_dev); + isp_pci->msi_enabled = 0; + } + if (isp_pci->vaddr != 0) { + unmap_pci_mem(isp_pci, 0xff); + isp_pci->vaddr = 0; + } else if (isp_pci->port) { + release_region(isp_pci->port, 0xff); + isp_pci->port = 0; } if (isp->isp_rquest) { - pci_free_consistent(pcs->pci_dev, RQUEST_QUEUE_LEN(isp) * QENTRY_LEN, isp->isp_rquest, isp->isp_rquest_dma); + pci_free_consistent(isp_pci->pci_dev, RQUEST_QUEUE_LEN(isp) * QENTRY_LEN, isp->isp_rquest, isp->isp_rquest_dma); isp->isp_rquest = NULL; } if (isp->isp_xflist) { @@ -436,23 +458,19 @@ isplinux_pci_release(struct Scsi_Host *host) } #endif if (isp->isp_result) { - pci_free_consistent(pcs->pci_dev, RESULT_QUEUE_LEN(isp) * QENTRY_LEN, isp->isp_result, isp->isp_result_dma); + pci_free_consistent(isp_pci->pci_dev, RESULT_QUEUE_LEN(isp) * QENTRY_LEN, isp->isp_result, isp->isp_result_dma); isp->isp_result = NULL; } if (IS_FC(isp)) { for (i = 0; i < isp->isp_nchan; i++) { fcparam *fcp = FCPARAM(isp, i); if (fcp->isp_scratch) { - pci_free_consistent(pcs->pci_dev, ISP_FC_SCRLEN, fcp->isp_scratch, fcp->isp_scdma); + pci_free_consistent(isp_pci->pci_dev, ISP_FC_SCRLEN, fcp->isp_scratch, fcp->isp_scdma); fcp->isp_scratch = NULL; } } } - pci_release_regions(pcs->pci_dev); - if (pcs->msi_enable) { - pcs->msi_enable = 0; - pci_disable_msi(pcs->pci_dev); - } + pci_release_regions(isp_pci->pci_dev); if (isp->isp_param) { isp_kfree(isp->isp_param, isp->isp_osinfo.param_amt); isp->isp_param = NULL; @@ -461,6 +479,7 @@ isplinux_pci_release(struct Scsi_Host *host) isp_kfree(isp->isp_osinfo.storep, isp->isp_osinfo.storep_amt); isp->isp_osinfo.storep = NULL; } + pci_disable_device(isp_pci->pci_dev); /* * Pull ourselves off the global list @@ -509,6 +528,7 @@ isplinux_pci_init_one(struct Scsi_Host *host) struct pci_dev *pdev; ispsoftc_t *isp; const char *fwname = NULL; + struct msix_entry isp_msix; isp_pci = (struct isp_pcisoftc *) ISP_HOST2ISP(host); pdev = isp_pci->pci_dev; @@ -593,15 +613,21 @@ isplinux_pci_init_one(struct Scsi_Host *host) pci_intx(pdev, 1); } + isp_msix.vector = 0; + isp_msix.entry = 0; + if (pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2422 || pdev->device == PCI_DEVICE_ID_QLOGIC_ISP2432) { int reg; /* enable PCI-INTX */ pci_intx(pdev, 1); - /* enable MSI */ - if (pci_enable_msi(pdev) == 0) { - isp_pci->msi_enable = 1; + /* enable MSI-X or MSI-X */ + if (pci_enable_msix(pdev, &isp_msix, 1) == 0) { + isp_pci->msix_enabled = 1; + isp_pci->msix_vector = isp_msix.vector; + } else if (pci_enable_msi(pdev) == 0) { + isp_pci->msi_enabled = 1; } /* @@ -773,12 +799,22 @@ isplinux_pci_init_one(struct Scsi_Host *host) fwname = "ql2400_fw.bin"; } #endif - - if (request_irq(pdev->irq, isplinux_intr, ISP_IRQ_FLAGS, isp->isp_name, isp_pci)) { - isp_prt(isp, ISP_LOGERR, "could not snag irq %u (0x%x)", pdev->irq, pdev->irq); - goto bad; + if (isp_pci->msix_enabled) { + if (request_irq(isp_pci->msix_vector, isplinux_intr, 0, isp->isp_name, isp_pci)) { + isp_prt(isp, ISP_LOGWARN, "unable to request MSI-X vector %u", isp_pci->msix_vector); + pci_disable_msix(pdev); + isp_pci->msix_enabled = 0; + } else { + isp_pci->msix_enabled++; + } + } + if (isp_pci->msix_enabled == 0) { + if (request_irq(pdev->irq, isplinux_intr, ISP_IRQ_FLAGS, isp->isp_name, isp_pci)) { + isp_prt(isp, ISP_LOGERR, "could not snag irq %u (0x%x)", pdev->irq, pdev->irq); + goto bad; + } + host->irq = pdev->irq; } - host->irq = pdev->irq; /* * Get parameter area set up @@ -878,11 +914,22 @@ bad: release_firmware(isp->isp_osinfo.fwp); isp->isp_osinfo.fwp = NULL; } + ISP_DISABLE_INTS(isp); if (host->irq) { - ISP_DISABLE_INTS(isp); free_irq(host->irq, isp_pci); host->irq = 0; } + if (isp_pci->msix_enabled) { + if (isp_pci->msix_enabled > 1) { + free_irq(isp_pci->msix_vector, isp_pci); + } + pci_disable_msix(isp_pci->pci_dev); + isp_pci->msix_enabled = 0; + } + if (isp_pci->msi_enabled) { + isp_pci->msi_enabled = 0; + pci_disable_msi(isp_pci->pci_dev); + } if (isp_pci->vaddr != 0) { unmap_pci_mem(isp_pci, 0xff); isp_pci->vaddr = 0; @@ -3306,8 +3353,15 @@ isplinux_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) ret = scsi_add_host(host, &pdev->dev); if (ret) { scsi_host_put(host); - if (pci_isp->msi_enable) { - pci_isp->msi_enable = 0; + if (pci_isp->msix_enabled) { + if (pci_isp->msix_enabled > 1) { + free_irq(pci_isp->msix_vector, pci_isp); + } + pci_disable_msix(pci_isp->pci_dev); + pci_isp->msix_enabled = 0; + } + if (pci_isp->msi_enabled) { + pci_isp->msi_enabled = 0; pci_disable_msi(pdev); } pci_disable_device(pdev);