diff options
Diffstat (limited to 'drivers/scsi/lpfc/lpfc_init.c')
-rw-r--r-- | drivers/scsi/lpfc/lpfc_init.c | 97 |
1 files changed, 78 insertions, 19 deletions
diff --git a/drivers/scsi/lpfc/lpfc_init.c b/drivers/scsi/lpfc/lpfc_init.c index 99141545c25e..a087524acf41 100644 --- a/drivers/scsi/lpfc/lpfc_init.c +++ b/drivers/scsi/lpfc/lpfc_init.c | |||
@@ -1924,6 +1924,42 @@ void lpfc_host_attrib_init(struct Scsi_Host *shost) | |||
1924 | spin_unlock_irq(shost->host_lock); | 1924 | spin_unlock_irq(shost->host_lock); |
1925 | } | 1925 | } |
1926 | 1926 | ||
1927 | static int | ||
1928 | lpfc_enable_msix(struct lpfc_hba *phba) | ||
1929 | { | ||
1930 | int error; | ||
1931 | |||
1932 | phba->msix_entries[0].entry = 0; | ||
1933 | phba->msix_entries[0].vector = 0; | ||
1934 | |||
1935 | error = pci_enable_msix(phba->pcidev, phba->msix_entries, | ||
1936 | ARRAY_SIZE(phba->msix_entries)); | ||
1937 | if (error) { | ||
1938 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | ||
1939 | "0420 Enable MSI-X failed (%d), continuing " | ||
1940 | "with MSI\n", error); | ||
1941 | pci_disable_msix(phba->pcidev); | ||
1942 | return error; | ||
1943 | } | ||
1944 | |||
1945 | error = request_irq(phba->msix_entries[0].vector, lpfc_intr_handler, 0, | ||
1946 | LPFC_DRIVER_NAME, phba); | ||
1947 | if (error) { | ||
1948 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | ||
1949 | "0421 MSI-X request_irq failed (%d), " | ||
1950 | "continuing with MSI\n", error); | ||
1951 | pci_disable_msix(phba->pcidev); | ||
1952 | } | ||
1953 | return error; | ||
1954 | } | ||
1955 | |||
1956 | static void | ||
1957 | lpfc_disable_msix(struct lpfc_hba *phba) | ||
1958 | { | ||
1959 | free_irq(phba->msix_entries[0].vector, phba); | ||
1960 | pci_disable_msix(phba->pcidev); | ||
1961 | } | ||
1962 | |||
1927 | static int __devinit | 1963 | static int __devinit |
1928 | lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | 1964 | lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) |
1929 | { | 1965 | { |
@@ -2125,24 +2161,36 @@ lpfc_pci_probe_one(struct pci_dev *pdev, const struct pci_device_id *pid) | |||
2125 | lpfc_debugfs_initialize(vport); | 2161 | lpfc_debugfs_initialize(vport); |
2126 | 2162 | ||
2127 | pci_set_drvdata(pdev, shost); | 2163 | pci_set_drvdata(pdev, shost); |
2164 | phba->intr_type = NONE; | ||
2128 | 2165 | ||
2129 | if (phba->cfg_use_msi) { | 2166 | if (phba->cfg_use_msi == 2) { |
2167 | error = lpfc_enable_msix(phba); | ||
2168 | if (!error) | ||
2169 | phba->intr_type = MSIX; | ||
2170 | } | ||
2171 | |||
2172 | /* Fallback to MSI if MSI-X initialization failed */ | ||
2173 | if (phba->cfg_use_msi >= 1 && phba->intr_type == NONE) { | ||
2130 | retval = pci_enable_msi(phba->pcidev); | 2174 | retval = pci_enable_msi(phba->pcidev); |
2131 | if (!retval) | 2175 | if (!retval) |
2132 | phba->using_msi = 1; | 2176 | phba->intr_type = MSI; |
2133 | else | 2177 | else |
2134 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, | 2178 | lpfc_printf_log(phba, KERN_INFO, LOG_INIT, |
2135 | "0452 Enable MSI failed, continuing " | 2179 | "0452 Enable MSI failed, continuing " |
2136 | "with IRQ\n"); | 2180 | "with IRQ\n"); |
2137 | } | 2181 | } |
2138 | 2182 | ||
2139 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, IRQF_SHARED, | 2183 | /* MSI-X is the only case the doesn't need to call request_irq */ |
2140 | LPFC_DRIVER_NAME, phba); | 2184 | if (phba->intr_type != MSIX) { |
2141 | if (retval) { | 2185 | retval = request_irq(phba->pcidev->irq, lpfc_intr_handler, |
2142 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, | 2186 | IRQF_SHARED, LPFC_DRIVER_NAME, phba); |
2143 | "0451 Enable interrupt handler failed\n"); | 2187 | if (retval) { |
2144 | error = retval; | 2188 | lpfc_printf_log(phba, KERN_ERR, LOG_INIT, "0451 Enable " |
2145 | goto out_disable_msi; | 2189 | "interrupt handler failed\n"); |
2190 | error = retval; | ||
2191 | goto out_disable_msi; | ||
2192 | } else if (phba->intr_type != MSI) | ||
2193 | phba->intr_type = INTx; | ||
2146 | } | 2194 | } |
2147 | 2195 | ||
2148 | phba->MBslimaddr = phba->slim_memmap_p; | 2196 | phba->MBslimaddr = phba->slim_memmap_p; |
@@ -2187,9 +2235,14 @@ out_remove_device: | |||
2187 | out_free_irq: | 2235 | out_free_irq: |
2188 | lpfc_stop_phba_timers(phba); | 2236 | lpfc_stop_phba_timers(phba); |
2189 | phba->pport->work_port_events = 0; | 2237 | phba->pport->work_port_events = 0; |
2190 | free_irq(phba->pcidev->irq, phba); | 2238 | |
2239 | if (phba->intr_type == MSIX) | ||
2240 | lpfc_disable_msix(phba); | ||
2241 | else | ||
2242 | free_irq(phba->pcidev->irq, phba); | ||
2243 | |||
2191 | out_disable_msi: | 2244 | out_disable_msi: |
2192 | if (phba->using_msi) | 2245 | if (phba->intr_type == MSI) |
2193 | pci_disable_msi(phba->pcidev); | 2246 | pci_disable_msi(phba->pcidev); |
2194 | destroy_port(vport); | 2247 | destroy_port(vport); |
2195 | out_kthread_stop: | 2248 | out_kthread_stop: |
@@ -2262,10 +2315,13 @@ lpfc_pci_remove_one(struct pci_dev *pdev) | |||
2262 | 2315 | ||
2263 | lpfc_debugfs_terminate(vport); | 2316 | lpfc_debugfs_terminate(vport); |
2264 | 2317 | ||
2265 | /* Release the irq reservation */ | 2318 | if (phba->intr_type == MSIX) |
2266 | free_irq(phba->pcidev->irq, phba); | 2319 | lpfc_disable_msix(phba); |
2267 | if (phba->using_msi) | 2320 | else { |
2268 | pci_disable_msi(phba->pcidev); | 2321 | free_irq(phba->pcidev->irq, phba); |
2322 | if (phba->intr_type == MSI) | ||
2323 | pci_disable_msi(phba->pcidev); | ||
2324 | } | ||
2269 | 2325 | ||
2270 | pci_set_drvdata(pdev, NULL); | 2326 | pci_set_drvdata(pdev, NULL); |
2271 | scsi_host_put(shost); | 2327 | scsi_host_put(shost); |
@@ -2324,10 +2380,13 @@ static pci_ers_result_t lpfc_io_error_detected(struct pci_dev *pdev, | |||
2324 | pring = &psli->ring[psli->fcp_ring]; | 2380 | pring = &psli->ring[psli->fcp_ring]; |
2325 | lpfc_sli_abort_iocb_ring(phba, pring); | 2381 | lpfc_sli_abort_iocb_ring(phba, pring); |
2326 | 2382 | ||
2327 | /* Release the irq reservation */ | 2383 | if (phba->intr_type == MSIX) |
2328 | free_irq(phba->pcidev->irq, phba); | 2384 | lpfc_disable_msix(phba); |
2329 | if (phba->using_msi) | 2385 | else { |
2330 | pci_disable_msi(phba->pcidev); | 2386 | free_irq(phba->pcidev->irq, phba); |
2387 | if (phba->intr_type == MSI) | ||
2388 | pci_disable_msi(phba->pcidev); | ||
2389 | } | ||
2331 | 2390 | ||
2332 | /* Request a slot reset. */ | 2391 | /* Request a slot reset. */ |
2333 | return PCI_ERS_RESULT_NEED_RESET; | 2392 | return PCI_ERS_RESULT_NEED_RESET; |