1fcf3ce44SJohn Forte /*
2fcf3ce44SJohn Forte * CDDL HEADER START
3fcf3ce44SJohn Forte *
4fcf3ce44SJohn Forte * The contents of this file are subject to the terms of the
5fcf3ce44SJohn Forte * Common Development and Distribution License (the "License").
6fcf3ce44SJohn Forte * You may not use this file except in compliance with the License.
7fcf3ce44SJohn Forte *
88f23e9faSHans Rosenfeld * You can obtain a copy of the license at
98f23e9faSHans Rosenfeld * http://www.opensource.org/licenses/cddl1.txt.
10fcf3ce44SJohn Forte * See the License for the specific language governing permissions
11fcf3ce44SJohn Forte * and limitations under the License.
12fcf3ce44SJohn Forte *
13fcf3ce44SJohn Forte * When distributing Covered Code, include this CDDL HEADER in each
14fcf3ce44SJohn Forte * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15fcf3ce44SJohn Forte * If applicable, add the following below this CDDL HEADER, with the
16fcf3ce44SJohn Forte * fields enclosed by brackets "[]" replaced with your own identifying
17fcf3ce44SJohn Forte * information: Portions Copyright [yyyy] [name of copyright owner]
18fcf3ce44SJohn Forte *
19fcf3ce44SJohn Forte * CDDL HEADER END
20fcf3ce44SJohn Forte */
21fcf3ce44SJohn Forte
22fcf3ce44SJohn Forte /*
238f23e9faSHans Rosenfeld * Copyright (c) 2004-2012 Emulex. All rights reserved.
2482527734SSukumar Swaminathan * Use is subject to license terms.
25*a3170057SPaul Winder * Copyright 2018 OmniOS Community Edition (OmniOSce) Association.
26*a3170057SPaul Winder * Copyright 2020 RackTop Systems, Inc.
27fcf3ce44SJohn Forte */
28fcf3ce44SJohn Forte
2982527734SSukumar Swaminathan #define EMLXS_FW_TABLE_DEF
3082527734SSukumar Swaminathan #define EMLXS_MODEL_DEF
31fcf3ce44SJohn Forte
3282527734SSukumar Swaminathan #include <emlxs.h>
33fcf3ce44SJohn Forte
3482527734SSukumar Swaminathan /* Required for EMLXS_CONTEXT in EMLXS_MSGF calls */
3582527734SSukumar Swaminathan EMLXS_MSG_DEF(EMLXS_HBA_C);
36fcf3ce44SJohn Forte
37a9800bebSGarrett D'Amore
3882527734SSukumar Swaminathan static void emlxs_handle_async_event(emlxs_hba_t *hba, CHANNEL *cp,
3982527734SSukumar Swaminathan IOCBQ *iocbq);
40291a2b48SSukumar Swaminathan
41a9800bebSGarrett D'Amore static void emlxs_pci_cap_offsets(emlxs_hba_t *hba);
42a9800bebSGarrett D'Amore
43fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
4482527734SSukumar Swaminathan uint32_t emlxs_msi_map[EMLXS_MSI_MODES][EMLXS_MSI_MAX_INTRS] =
4582527734SSukumar Swaminathan {EMLXS_MSI_MAP1, EMLXS_MSI_MAP2, EMLXS_MSI_MAP4, EMLXS_MSI_MAP8};
4682527734SSukumar Swaminathan uint32_t emlxs_msi_mask[EMLXS_MSI_MODES] =
4782527734SSukumar Swaminathan {EMLXS_MSI0_MASK1, EMLXS_MSI0_MASK2, EMLXS_MSI0_MASK4,
4882527734SSukumar Swaminathan EMLXS_MSI0_MASK8};
49291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
50fcf3ce44SJohn Forte
5182527734SSukumar Swaminathan emlxs_firmware_t emlxs_fw_table[] = EMLXS_FW_TABLE;
5282527734SSukumar Swaminathan int emlxs_fw_count = sizeof (emlxs_fw_table) / sizeof (emlxs_firmware_t);
53291a2b48SSukumar Swaminathan
54a9800bebSGarrett D'Amore emlxs_table_t emlxs_pci_cap[] = {
55a9800bebSGarrett D'Amore {PCI_CAP_ID_PM, "PCI_CAP_ID_PM"},
56a9800bebSGarrett D'Amore {PCI_CAP_ID_AGP, "PCI_CAP_ID_AGP"},
57a9800bebSGarrett D'Amore {PCI_CAP_ID_VPD, "PCI_CAP_ID_VPD"},
58a9800bebSGarrett D'Amore {PCI_CAP_ID_SLOT_ID, "PCI_CAP_ID_SLOT_ID"},
59a9800bebSGarrett D'Amore {PCI_CAP_ID_MSI, "PCI_CAP_ID_MSI"},
60a9800bebSGarrett D'Amore {PCI_CAP_ID_cPCI_HS, "PCI_CAP_ID_cPCI_HS"},
61a9800bebSGarrett D'Amore {PCI_CAP_ID_PCIX, "PCI_CAP_ID_PCIX"},
62a9800bebSGarrett D'Amore {PCI_CAP_ID_HT, "PCI_CAP_ID_HT"},
63a9800bebSGarrett D'Amore {PCI_CAP_ID_VS, "PCI_CAP_ID_VS"},
64a9800bebSGarrett D'Amore {PCI_CAP_ID_DEBUG_PORT, "PCI_CAP_ID_DEBUG_PORT"},
65a9800bebSGarrett D'Amore {PCI_CAP_ID_cPCI_CRC, "PCI_CAP_ID_cPCI_CRC"},
66a9800bebSGarrett D'Amore {PCI_CAP_ID_PCI_HOTPLUG, "PCI_CAP_ID_PCI_HOTPLUG"},
67a9800bebSGarrett D'Amore {PCI_CAP_ID_P2P_SUBSYS, "PCI_CAP_ID_P2P_SUBSYS"},
68a9800bebSGarrett D'Amore {PCI_CAP_ID_AGP_8X, "PCI_CAP_ID_AGP_8X"},
69a9800bebSGarrett D'Amore {PCI_CAP_ID_SECURE_DEV, "PCI_CAP_ID_SECURE_DEV"},
70a9800bebSGarrett D'Amore {PCI_CAP_ID_PCI_E, "PCI_CAP_ID_PCI_E"},
71a9800bebSGarrett D'Amore {PCI_CAP_ID_MSI_X, "PCI_CAP_ID_MSI_X"},
72a9800bebSGarrett D'Amore {PCI_CAP_ID_SATA, "PCI_CAP_ID_SATA"},
73a9800bebSGarrett D'Amore {PCI_CAP_ID_FLR, "PCI_CAP_ID_FLR"}
74a9800bebSGarrett D'Amore
75a9800bebSGarrett D'Amore }; /* emlxs_pci_cap */
76a9800bebSGarrett D'Amore
778f23e9faSHans Rosenfeld emlxs_table_t emlxs_pci_ecap[] = {
788f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_AER, "PCIE_EXT_CAP_ID_AER"},
798f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VC, "PCIE_EXT_CAP_ID_VC"},
808f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_SER, "PCIE_EXT_CAP_ID_SER"},
818f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_PWR_BUDGET, "PCIE_EXT_CAP_ID_PWR_BUDGET"},
828f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_LINK_DECL, "PCIE_EXT_CAP_ID_RC_LINK_DECL"},
838f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_INT_LINKCTRL, "PCIE_EXT_CAP_ID_RC_INT_LINKCTRL"},
848f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RC_EVNT_CEA, "PCIE_EXT_CAP_ID_RC_EVNT_CEA"},
858f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_MFVC, "PCIE_EXT_CAP_ID_MFVC"},
868f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VC_WITH_MFVC, "PCIE_EXT_CAP_ID_VC_WITH_MFVC"},
878f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_RCRB, "PCIE_EXT_CAP_ID_RCRB"},
888f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_VS, "PCIE_EXT_CAP_ID_VS"},
898f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_CAC, "PCIE_EXT_CAP_ID_CAC"},
908f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ACS, "PCIE_EXT_CAP_ID_ACS"},
918f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ARI, "PCIE_EXT_CAP_ID_ARI"},
928f23e9faSHans Rosenfeld {PCIE_EXT_CAP_ID_ATS, "PCIE_EXT_CAP_ID_ATS"},
938f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_SRIOV, "PCI_EXT_CAP_ID_SRIOV"},
948f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_TPH, "PCI_EXT_CAP_ID_TPH"},
958f23e9faSHans Rosenfeld {PCI_EXT_CAP_ID_SEC_PCI, "PCI_EXT_CAP_ID_SEC_PCI"}
968f23e9faSHans Rosenfeld
978f23e9faSHans Rosenfeld }; /* emlxs_pci_ecap */
988f23e9faSHans Rosenfeld
998f23e9faSHans Rosenfeld
10082527734SSukumar Swaminathan emlxs_table_t emlxs_ring_table[] = {
10182527734SSukumar Swaminathan {FC_FCP_RING, "FCP Ring"},
10282527734SSukumar Swaminathan {FC_IP_RING, "IP Ring"},
10382527734SSukumar Swaminathan {FC_ELS_RING, "ELS Ring"},
10482527734SSukumar Swaminathan {FC_CT_RING, "CT Ring"}
105291a2b48SSukumar Swaminathan
10682527734SSukumar Swaminathan }; /* emlxs_ring_table */
107fcf3ce44SJohn Forte
10882527734SSukumar Swaminathan emlxs_table_t emlxs_ffstate_table[] = {
10982527734SSukumar Swaminathan {0, "NULL"},
11082527734SSukumar Swaminathan {FC_ERROR, "ERROR"},
11182527734SSukumar Swaminathan {FC_KILLED, "KILLED"},
11282527734SSukumar Swaminathan {FC_WARM_START, "WARM_START"},
11382527734SSukumar Swaminathan {FC_INIT_START, "INIT_START"},
11482527734SSukumar Swaminathan {FC_INIT_NVPARAMS, "INIT_NVPARAMS"},
11582527734SSukumar Swaminathan {FC_INIT_REV, "INIT_REV"},
11682527734SSukumar Swaminathan {FC_INIT_CFGPORT, "INIT_CFGPORT"},
11782527734SSukumar Swaminathan {FC_INIT_CFGRING, "INIT_CFGRING"},
11882527734SSukumar Swaminathan {FC_INIT_INITLINK, "INIT_INITLINK"},
11982527734SSukumar Swaminathan {FC_LINK_DOWN, "LINK_DOWN"},
12082527734SSukumar Swaminathan {FC_LINK_UP, "LINK_UP"},
12182527734SSukumar Swaminathan {FC_CLEAR_LA, "CLEAR_LA"},
12282527734SSukumar Swaminathan {FC_READY, "READY"}
123fcf3ce44SJohn Forte
12482527734SSukumar Swaminathan }; /* emlxs_ffstate_table */
125fcf3ce44SJohn Forte
126fcf3ce44SJohn Forte
127fcf3ce44SJohn Forte #ifdef MSI_SUPPORT
128fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
129fcf3ce44SJohn Forte int32_t
emlxs_msi_init(emlxs_hba_t * hba,uint32_t max)130fcf3ce44SJohn Forte emlxs_msi_init(emlxs_hba_t *hba, uint32_t max)
131fcf3ce44SJohn Forte {
132fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
133fcf3ce44SJohn Forte int32_t pass = 0;
134fcf3ce44SJohn Forte int32_t type = 0;
135fcf3ce44SJohn Forte char s_type[16];
136fcf3ce44SJohn Forte int32_t types;
137fcf3ce44SJohn Forte int32_t count;
138fcf3ce44SJohn Forte int32_t nintrs;
139fcf3ce44SJohn Forte int32_t mode;
140fcf3ce44SJohn Forte int32_t actual;
141fcf3ce44SJohn Forte int32_t new_actual;
142fcf3ce44SJohn Forte int32_t i;
143fcf3ce44SJohn Forte int32_t ret;
144fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL;
145fcf3ce44SJohn Forte ddi_intr_handle_t *new_htable = NULL;
146fcf3ce44SJohn Forte uint32_t *intr_pri = NULL;
147fcf3ce44SJohn Forte int32_t *intr_cap = NULL;
148fcf3ce44SJohn Forte int32_t hilevel_pri;
149fcf3ce44SJohn Forte emlxs_config_t *cfg = &CFG;
150fcf3ce44SJohn Forte
151fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
152fcf3ce44SJohn Forte return (emlxs_intx_init(hba, max));
153fcf3ce44SJohn Forte }
154291a2b48SSukumar Swaminathan
155fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_INITED) {
156fcf3ce44SJohn Forte return (DDI_SUCCESS);
157fcf3ce44SJohn Forte }
158291a2b48SSukumar Swaminathan
159fcf3ce44SJohn Forte /* Set max interrupt count if not specified */
160fcf3ce44SJohn Forte if (max == 0) {
161fcf3ce44SJohn Forte if ((cfg[CFG_MSI_MODE].current == 2) ||
162fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 3)) {
163fcf3ce44SJohn Forte max = EMLXS_MSI_MAX_INTRS;
164fcf3ce44SJohn Forte } else {
165fcf3ce44SJohn Forte max = 1;
166fcf3ce44SJohn Forte }
167fcf3ce44SJohn Forte }
168291a2b48SSukumar Swaminathan
169fcf3ce44SJohn Forte /* Filter max interrupt count with adapter model specification */
170fcf3ce44SJohn Forte if (hba->model_info.intr_limit && (max > hba->model_info.intr_limit)) {
171fcf3ce44SJohn Forte max = hba->model_info.intr_limit;
172fcf3ce44SJohn Forte }
173291a2b48SSukumar Swaminathan
174fcf3ce44SJohn Forte /* Get the available interrupt types from the kernel */
175fcf3ce44SJohn Forte types = 0;
176fcf3ce44SJohn Forte ret = ddi_intr_get_supported_types(hba->dip, &types);
177fcf3ce44SJohn Forte
178fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS)) {
179fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
180fcf3ce44SJohn Forte "MSI: ddi_intr_get_supported_types failed. ret=%d", ret);
181fcf3ce44SJohn Forte
182fcf3ce44SJohn Forte /* Default to fixed type */
183fcf3ce44SJohn Forte types = DDI_INTR_TYPE_FIXED;
184fcf3ce44SJohn Forte }
185291a2b48SSukumar Swaminathan
186fcf3ce44SJohn Forte /* Check if fixed interrupts are being forced */
187fcf3ce44SJohn Forte if (cfg[CFG_MSI_MODE].current == 0) {
188fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED;
189fcf3ce44SJohn Forte }
190291a2b48SSukumar Swaminathan
191fcf3ce44SJohn Forte /* Check if MSI interrupts are being forced */
192fcf3ce44SJohn Forte else if ((cfg[CFG_MSI_MODE].current == 1) ||
193fcf3ce44SJohn Forte (cfg[CFG_MSI_MODE].current == 2)) {
194fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
195fcf3ce44SJohn Forte }
196291a2b48SSukumar Swaminathan
197fcf3ce44SJohn Forte begin:
198fcf3ce44SJohn Forte
199fcf3ce44SJohn Forte /* Set interrupt type and interrupt count */
200fcf3ce44SJohn Forte type = 0;
201fcf3ce44SJohn Forte
202fcf3ce44SJohn Forte /* Check if MSIX is fully supported */
203fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSIX) &&
204fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSIX_SUPPORTED)) {
205fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */
206fcf3ce44SJohn Forte nintrs = 0;
207fcf3ce44SJohn Forte ret =
208291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSIX,
209291a2b48SSukumar Swaminathan &nintrs);
210fcf3ce44SJohn Forte
211fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) {
212fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSIX;
2138f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_MSIX", sizeof (s_type));
214fcf3ce44SJohn Forte goto initialize;
215fcf3ce44SJohn Forte }
216fcf3ce44SJohn Forte }
217291a2b48SSukumar Swaminathan
218fcf3ce44SJohn Forte /* Check if MSI is fully supported */
219fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_MSI) &&
220fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_MSI_SUPPORTED)) {
221fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */
222fcf3ce44SJohn Forte nintrs = 0;
223291a2b48SSukumar Swaminathan ret =
224291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_MSI, &nintrs);
225fcf3ce44SJohn Forte
226fcf3ce44SJohn Forte if (ret == DDI_SUCCESS && nintrs) {
227fcf3ce44SJohn Forte type = DDI_INTR_TYPE_MSI;
2288f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_MSI", sizeof (s_type));
229fcf3ce44SJohn Forte goto initialize;
230fcf3ce44SJohn Forte }
231fcf3ce44SJohn Forte }
232291a2b48SSukumar Swaminathan
233fcf3ce44SJohn Forte /* Check if fixed interrupts are fully supported */
234fcf3ce44SJohn Forte if ((types & DDI_INTR_TYPE_FIXED) &&
235fcf3ce44SJohn Forte (hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
236fcf3ce44SJohn Forte /* Get the max interrupt count from the adapter */
237fcf3ce44SJohn Forte nintrs = 0;
238fcf3ce44SJohn Forte ret =
239291a2b48SSukumar Swaminathan ddi_intr_get_nintrs(hba->dip, DDI_INTR_TYPE_FIXED,
240291a2b48SSukumar Swaminathan &nintrs);
241fcf3ce44SJohn Forte
242fcf3ce44SJohn Forte if (ret == DDI_SUCCESS) {
243fcf3ce44SJohn Forte type = DDI_INTR_TYPE_FIXED;
2448f23e9faSHans Rosenfeld (void) strlcpy(s_type, "TYPE_FIXED", sizeof (s_type));
245fcf3ce44SJohn Forte goto initialize;
246fcf3ce44SJohn Forte }
247fcf3ce44SJohn Forte }
248291a2b48SSukumar Swaminathan
249fcf3ce44SJohn Forte goto init_failed;
250fcf3ce44SJohn Forte
251fcf3ce44SJohn Forte
252fcf3ce44SJohn Forte initialize:
253fcf3ce44SJohn Forte
254fcf3ce44SJohn Forte pass++;
255fcf3ce44SJohn Forte mode = 0;
256fcf3ce44SJohn Forte actual = 0;
257fcf3ce44SJohn Forte htable = NULL;
258fcf3ce44SJohn Forte intr_pri = NULL;
259fcf3ce44SJohn Forte intr_cap = NULL;
260fcf3ce44SJohn Forte hilevel_pri = 0;
261fcf3ce44SJohn Forte
262fcf3ce44SJohn Forte if (pass == 1) {
263fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
264291a2b48SSukumar Swaminathan "MSI: %s: mode=%d types=0x%x nintrs=%d", s_type,
265291a2b48SSukumar Swaminathan cfg[CFG_MSI_MODE].current, types, nintrs);
266fcf3ce44SJohn Forte }
267291a2b48SSukumar Swaminathan
268fcf3ce44SJohn Forte /* Validate interrupt count */
269fcf3ce44SJohn Forte count = min(nintrs, max);
270fcf3ce44SJohn Forte
271fcf3ce44SJohn Forte if (count >= 8) {
272fcf3ce44SJohn Forte count = 8;
273fcf3ce44SJohn Forte } else if (count >= 4) {
274fcf3ce44SJohn Forte count = 4;
275fcf3ce44SJohn Forte } else if (count >= 2) {
276fcf3ce44SJohn Forte count = 2;
277fcf3ce44SJohn Forte } else {
278fcf3ce44SJohn Forte count = 1;
279fcf3ce44SJohn Forte }
280fcf3ce44SJohn Forte
281fcf3ce44SJohn Forte /* Allocate an array of interrupt handles */
282fcf3ce44SJohn Forte htable =
283291a2b48SSukumar Swaminathan kmem_alloc((size_t)(count * sizeof (ddi_intr_handle_t)),
284291a2b48SSukumar Swaminathan KM_SLEEP);
285fcf3ce44SJohn Forte
286fcf3ce44SJohn Forte /* Allocate 'count' interrupts */
287291a2b48SSukumar Swaminathan ret =
288291a2b48SSukumar Swaminathan ddi_intr_alloc(hba->dip, htable, type, EMLXS_MSI_INUMBER, count,
289fcf3ce44SJohn Forte &actual, DDI_INTR_ALLOC_NORMAL);
290fcf3ce44SJohn Forte
291fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
29282527734SSukumar Swaminathan "MSI: %s: count=%d actual=%d ret=%d", s_type, count, actual, ret);
293fcf3ce44SJohn Forte
294fcf3ce44SJohn Forte if ((ret != DDI_SUCCESS) || (actual == 0)) {
295fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
296fcf3ce44SJohn Forte "MSI: Unable to allocate interrupts. error=%d", ret);
297fcf3ce44SJohn Forte
298a9800bebSGarrett D'Amore actual = 0;
299fcf3ce44SJohn Forte goto init_failed;
300fcf3ce44SJohn Forte }
301291a2b48SSukumar Swaminathan
302fcf3ce44SJohn Forte if (actual != count) {
303fcf3ce44SJohn Forte /* Validate actual count */
304fcf3ce44SJohn Forte if (actual >= 8) {
305fcf3ce44SJohn Forte new_actual = 8;
306fcf3ce44SJohn Forte } else if (actual >= 4) {
307fcf3ce44SJohn Forte new_actual = 4;
308fcf3ce44SJohn Forte } else if (actual >= 2) {
309fcf3ce44SJohn Forte new_actual = 2;
310fcf3ce44SJohn Forte } else {
311fcf3ce44SJohn Forte new_actual = 1;
312fcf3ce44SJohn Forte }
313fcf3ce44SJohn Forte
314fcf3ce44SJohn Forte if (new_actual < actual) {
315fcf3ce44SJohn Forte /* Free extra handles */
316fcf3ce44SJohn Forte for (i = new_actual; i < actual; i++) {
317fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]);
318fcf3ce44SJohn Forte }
319fcf3ce44SJohn Forte
320fcf3ce44SJohn Forte actual = new_actual;
321fcf3ce44SJohn Forte }
322291a2b48SSukumar Swaminathan
323fcf3ce44SJohn Forte /* Allocate a new array of interrupt handles */
324fcf3ce44SJohn Forte new_htable =
325fcf3ce44SJohn Forte kmem_alloc((size_t)(actual * sizeof (ddi_intr_handle_t)),
326fcf3ce44SJohn Forte KM_SLEEP);
327fcf3ce44SJohn Forte
328fcf3ce44SJohn Forte /* Copy old array to new array */
329fcf3ce44SJohn Forte bcopy((uint8_t *)htable, (uint8_t *)new_htable,
330fcf3ce44SJohn Forte (actual * sizeof (ddi_intr_handle_t)));
331fcf3ce44SJohn Forte
332fcf3ce44SJohn Forte /* Free the old array */
333fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
334fcf3ce44SJohn Forte
335fcf3ce44SJohn Forte htable = new_htable;
336fcf3ce44SJohn Forte count = actual;
337fcf3ce44SJohn Forte }
338291a2b48SSukumar Swaminathan
339fcf3ce44SJohn Forte /* Allocate interrupt priority table */
340fcf3ce44SJohn Forte intr_pri =
341fcf3ce44SJohn Forte (uint32_t *)kmem_alloc((size_t)(count * sizeof (uint32_t)),
342fcf3ce44SJohn Forte KM_SLEEP);
343fcf3ce44SJohn Forte
344fcf3ce44SJohn Forte /* Allocate interrupt capability table */
345fcf3ce44SJohn Forte intr_cap = kmem_alloc((size_t)(count * sizeof (uint32_t)), KM_SLEEP);
346fcf3ce44SJohn Forte
347fcf3ce44SJohn Forte /* Get minimum hilevel priority */
348fcf3ce44SJohn Forte hilevel_pri = ddi_intr_get_hilevel_pri();
349fcf3ce44SJohn Forte
350fcf3ce44SJohn Forte /* Fill the priority and capability tables */
351fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
352fcf3ce44SJohn Forte ret = ddi_intr_get_pri(htable[i], &intr_pri[i]);
353fcf3ce44SJohn Forte
354fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
355fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
356fcf3ce44SJohn Forte "MSI: ddi_intr_get_pri(%d) failed. "
357291a2b48SSukumar Swaminathan "handle=%p ret=%d",
358291a2b48SSukumar Swaminathan i, &htable[i], ret);
359fcf3ce44SJohn Forte
360fcf3ce44SJohn Forte /* Clean up the interrupts */
361fcf3ce44SJohn Forte goto init_failed;
362fcf3ce44SJohn Forte }
363291a2b48SSukumar Swaminathan
364fcf3ce44SJohn Forte if (intr_pri[i] >= hilevel_pri) {
365fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
366fcf3ce44SJohn Forte "MSI: Interrupt(%d) level too high. "
367fcf3ce44SJohn Forte "pri=0x%x hilevel=0x%x",
368fcf3ce44SJohn Forte i, intr_pri[i], hilevel_pri);
369fcf3ce44SJohn Forte
370fcf3ce44SJohn Forte /* Clean up the interrupts */
371fcf3ce44SJohn Forte goto init_failed;
372fcf3ce44SJohn Forte }
373291a2b48SSukumar Swaminathan
374fcf3ce44SJohn Forte ret = ddi_intr_get_cap(htable[i], &intr_cap[i]);
375fcf3ce44SJohn Forte
376fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
377fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
378291a2b48SSukumar Swaminathan "MSI: ddi_intr_get_cap(%d) failed. "
379291a2b48SSukumar Swaminathan "handle=%p ret=%d",
380291a2b48SSukumar Swaminathan i, &htable[i], ret);
381fcf3ce44SJohn Forte
382fcf3ce44SJohn Forte /* Clean up the interrupts */
383fcf3ce44SJohn Forte goto init_failed;
384fcf3ce44SJohn Forte }
385291a2b48SSukumar Swaminathan
386fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
387291a2b48SSukumar Swaminathan "MSI: %s: %d: cap=0x%x pri=0x%x hilevel=0x%x", s_type, i,
388291a2b48SSukumar Swaminathan intr_cap[i], intr_pri[i], hilevel_pri);
389fcf3ce44SJohn Forte
390fcf3ce44SJohn Forte }
391fcf3ce44SJohn Forte
392fcf3ce44SJohn Forte /* Set mode */
393fcf3ce44SJohn Forte switch (count) {
394fcf3ce44SJohn Forte case 8:
395fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE8;
396fcf3ce44SJohn Forte break;
397fcf3ce44SJohn Forte
398fcf3ce44SJohn Forte case 4:
399fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE4;
400fcf3ce44SJohn Forte break;
401fcf3ce44SJohn Forte
402fcf3ce44SJohn Forte case 2:
403fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE2;
404fcf3ce44SJohn Forte break;
405fcf3ce44SJohn Forte
406fcf3ce44SJohn Forte default:
407fcf3ce44SJohn Forte mode = EMLXS_MSI_MODE1;
408fcf3ce44SJohn Forte }
409fcf3ce44SJohn Forte
410fcf3ce44SJohn Forte /* Save the info */
411fcf3ce44SJohn Forte hba->intr_htable = htable;
412fcf3ce44SJohn Forte hba->intr_count = count;
413fcf3ce44SJohn Forte hba->intr_pri = intr_pri;
414fcf3ce44SJohn Forte hba->intr_cap = intr_cap;
415fcf3ce44SJohn Forte hba->intr_type = type;
416291a2b48SSukumar Swaminathan hba->intr_arg = (void *)((unsigned long)intr_pri[0]);
417fcf3ce44SJohn Forte hba->intr_mask = emlxs_msi_mask[mode];
418fcf3ce44SJohn Forte
419fcf3ce44SJohn Forte hba->intr_cond = 0;
42082527734SSukumar Swaminathan
42182527734SSukumar Swaminathan /* Adjust number of channels based on intr_count */
42282527734SSukumar Swaminathan if (hba->sli_mode == EMLXS_HBA_SLI4_MODE) {
42382527734SSukumar Swaminathan hba->chan_count = hba->intr_count * cfg[CFG_NUM_WQ].current;
42482527734SSukumar Swaminathan }
42582527734SSukumar Swaminathan
426fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
427fcf3ce44SJohn Forte hba->intr_map[i] = emlxs_msi_map[mode][i];
428fcf3ce44SJohn Forte hba->intr_cond |= emlxs_msi_map[mode][i];
429fcf3ce44SJohn Forte
4308f23e9faSHans Rosenfeld mutex_init(&hba->intr_lock[i], NULL, MUTEX_DRIVER,
431a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg));
432fcf3ce44SJohn Forte }
433fcf3ce44SJohn Forte
434fcf3ce44SJohn Forte /* Set flag to indicate support */
435fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_INITED;
436fcf3ce44SJohn Forte
437fcf3ce44SJohn Forte /* Create the interrupt threads */
43882527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) {
4398f23e9faSHans Rosenfeld mutex_init(&hba->chan[i].rsp_lock, NULL, MUTEX_DRIVER,
440a9800bebSGarrett D'Amore DDI_INTR_PRI(hba->intr_arg));
441fcf3ce44SJohn Forte
44282527734SSukumar Swaminathan emlxs_thread_create(hba, &hba->chan[i].intr_thread);
443fcf3ce44SJohn Forte }
444fcf3ce44SJohn Forte
445fcf3ce44SJohn Forte return (DDI_SUCCESS);
446fcf3ce44SJohn Forte
447fcf3ce44SJohn Forte init_failed:
448fcf3ce44SJohn Forte
449fcf3ce44SJohn Forte if (intr_cap) {
450fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t)));
451fcf3ce44SJohn Forte }
452291a2b48SSukumar Swaminathan
453fcf3ce44SJohn Forte if (intr_pri) {
454fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t)));
455fcf3ce44SJohn Forte }
456291a2b48SSukumar Swaminathan
457fcf3ce44SJohn Forte if (htable) {
458fcf3ce44SJohn Forte /* Process the interrupt handlers */
459fcf3ce44SJohn Forte for (i = 0; i < actual; i++) {
460fcf3ce44SJohn Forte /* Free the handle[i] */
461fcf3ce44SJohn Forte (void) ddi_intr_free(htable[i]);
462fcf3ce44SJohn Forte }
463fcf3ce44SJohn Forte
464fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
465fcf3ce44SJohn Forte }
466291a2b48SSukumar Swaminathan
467fcf3ce44SJohn Forte /* Initialize */
468fcf3ce44SJohn Forte hba->intr_htable = NULL;
469fcf3ce44SJohn Forte hba->intr_count = 0;
470fcf3ce44SJohn Forte hba->intr_pri = NULL;
471fcf3ce44SJohn Forte hba->intr_cap = NULL;
472fcf3ce44SJohn Forte hba->intr_type = 0;
473fcf3ce44SJohn Forte hba->intr_arg = NULL;
474fcf3ce44SJohn Forte hba->intr_cond = 0;
475fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map));
476fcf3ce44SJohn Forte bzero(hba->intr_lock, sizeof (hba->intr_lock));
477fcf3ce44SJohn Forte
478fcf3ce44SJohn Forte if (type == DDI_INTR_TYPE_MSIX) {
479fcf3ce44SJohn Forte types &= (DDI_INTR_TYPE_MSI | DDI_INTR_TYPE_FIXED);
480fcf3ce44SJohn Forte goto begin;
481fcf3ce44SJohn Forte } else if (type == DDI_INTR_TYPE_MSI) {
482fcf3ce44SJohn Forte types &= DDI_INTR_TYPE_FIXED;
483fcf3ce44SJohn Forte goto begin;
484fcf3ce44SJohn Forte }
485291a2b48SSukumar Swaminathan
486fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
487fcf3ce44SJohn Forte "MSI: Unable to initialize interrupts");
488fcf3ce44SJohn Forte
489fcf3ce44SJohn Forte return (DDI_FAILURE);
490fcf3ce44SJohn Forte
491fcf3ce44SJohn Forte
49282527734SSukumar Swaminathan } /* emlxs_msi_init() */
493fcf3ce44SJohn Forte
494fcf3ce44SJohn Forte
495fcf3ce44SJohn Forte /* EMLXS_INTR_UNINIT */
496fcf3ce44SJohn Forte int32_t
emlxs_msi_uninit(emlxs_hba_t * hba)497fcf3ce44SJohn Forte emlxs_msi_uninit(emlxs_hba_t *hba)
498fcf3ce44SJohn Forte {
499fcf3ce44SJohn Forte uint32_t count;
500fcf3ce44SJohn Forte int32_t i;
501fcf3ce44SJohn Forte ddi_intr_handle_t *htable;
502fcf3ce44SJohn Forte uint32_t *intr_pri;
503fcf3ce44SJohn Forte int32_t *intr_cap;
504fcf3ce44SJohn Forte int32_t ret;
505fcf3ce44SJohn Forte
506fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
507fcf3ce44SJohn Forte return (emlxs_intx_uninit(hba));
508fcf3ce44SJohn Forte }
509291a2b48SSukumar Swaminathan
510fcf3ce44SJohn Forte /*
511291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5128f23e9faSHans Rosenfeld * "MSI: msi_uninit called. flags=%x",
513291a2b48SSukumar Swaminathan * hba->intr_flags);
514fcf3ce44SJohn Forte */
515fcf3ce44SJohn Forte
516fcf3ce44SJohn Forte /* Make sure interrupts have been removed first */
517fcf3ce44SJohn Forte if ((hba->intr_flags & EMLXS_MSI_ADDED)) {
518fcf3ce44SJohn Forte ret = emlxs_msi_remove(hba);
519fcf3ce44SJohn Forte
520fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
521fcf3ce44SJohn Forte return (ret);
522fcf3ce44SJohn Forte }
523fcf3ce44SJohn Forte }
524291a2b48SSukumar Swaminathan
525fcf3ce44SJohn Forte /* Check if the interrupts are still initialized */
526fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
527fcf3ce44SJohn Forte return (DDI_SUCCESS);
528fcf3ce44SJohn Forte }
529fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_INITED;
530fcf3ce44SJohn Forte
531fcf3ce44SJohn Forte /* Get handle table parameters */
532fcf3ce44SJohn Forte htable = hba->intr_htable;
533fcf3ce44SJohn Forte count = hba->intr_count;
534fcf3ce44SJohn Forte intr_pri = hba->intr_pri;
535fcf3ce44SJohn Forte intr_cap = hba->intr_cap;
536fcf3ce44SJohn Forte
537fcf3ce44SJohn Forte /* Clean up */
538fcf3ce44SJohn Forte hba->intr_count = 0;
539fcf3ce44SJohn Forte hba->intr_htable = NULL;
540fcf3ce44SJohn Forte hba->intr_pri = NULL;
541fcf3ce44SJohn Forte hba->intr_cap = NULL;
542fcf3ce44SJohn Forte hba->intr_type = 0;
543fcf3ce44SJohn Forte hba->intr_arg = NULL;
544fcf3ce44SJohn Forte hba->intr_cond = 0;
545fcf3ce44SJohn Forte bzero(hba->intr_map, sizeof (hba->intr_map));
546fcf3ce44SJohn Forte
547fcf3ce44SJohn Forte if (intr_cap) {
548fcf3ce44SJohn Forte kmem_free(intr_cap, (count * sizeof (int32_t)));
549fcf3ce44SJohn Forte }
550291a2b48SSukumar Swaminathan
551fcf3ce44SJohn Forte if (intr_pri) {
552fcf3ce44SJohn Forte kmem_free(intr_pri, (count * sizeof (int32_t)));
553fcf3ce44SJohn Forte }
554291a2b48SSukumar Swaminathan
555fcf3ce44SJohn Forte if (htable) {
556fcf3ce44SJohn Forte /* Process the interrupt handlers */
557fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
558fcf3ce44SJohn Forte /* Free the handle[i] */
559291a2b48SSukumar Swaminathan ret = ddi_intr_free(htable[i]);
560fcf3ce44SJohn Forte }
561fcf3ce44SJohn Forte
562fcf3ce44SJohn Forte kmem_free(htable, (count * sizeof (ddi_intr_handle_t)));
563fcf3ce44SJohn Forte }
564291a2b48SSukumar Swaminathan
565fcf3ce44SJohn Forte /* Destroy the intr locks */
566fcf3ce44SJohn Forte for (i = 0; i < EMLXS_MSI_MAX_INTRS; i++) {
567fcf3ce44SJohn Forte mutex_destroy(&hba->intr_lock[i]);
568fcf3ce44SJohn Forte }
569fcf3ce44SJohn Forte
570fcf3ce44SJohn Forte /* Destroy the interrupt threads */
57182527734SSukumar Swaminathan for (i = 0; i < hba->chan_count; i++) {
57282527734SSukumar Swaminathan emlxs_thread_destroy(&hba->chan[i].intr_thread);
57382527734SSukumar Swaminathan mutex_destroy(&hba->chan[i].rsp_lock);
574fcf3ce44SJohn Forte }
575fcf3ce44SJohn Forte
576fcf3ce44SJohn Forte /*
577291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
5788f23e9faSHans Rosenfeld * "MSI: msi_uninit done. flags=%x",
579291a2b48SSukumar Swaminathan * hba->intr_flags);
580fcf3ce44SJohn Forte */
581fcf3ce44SJohn Forte
582fcf3ce44SJohn Forte return (DDI_SUCCESS);
583fcf3ce44SJohn Forte
58482527734SSukumar Swaminathan } /* emlxs_msi_uninit() */
585fcf3ce44SJohn Forte
586fcf3ce44SJohn Forte
587fcf3ce44SJohn Forte /* EMLXS_INTR_ADD */
588fcf3ce44SJohn Forte int32_t
emlxs_msi_add(emlxs_hba_t * hba)589fcf3ce44SJohn Forte emlxs_msi_add(emlxs_hba_t *hba)
590fcf3ce44SJohn Forte {
591fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
592fcf3ce44SJohn Forte int32_t count;
593fcf3ce44SJohn Forte int32_t i;
594fcf3ce44SJohn Forte int32_t ret;
595fcf3ce44SJohn Forte ddi_intr_handle_t *htable = NULL;
596fcf3ce44SJohn Forte int32_t *intr_cap = NULL;
597fcf3ce44SJohn Forte
598fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
599fcf3ce44SJohn Forte return (emlxs_intx_add(hba));
600fcf3ce44SJohn Forte }
601291a2b48SSukumar Swaminathan
602fcf3ce44SJohn Forte /* Check if interrupts have already been added */
603fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_MSI_ADDED) {
604fcf3ce44SJohn Forte return (DDI_SUCCESS);
605fcf3ce44SJohn Forte }
606291a2b48SSukumar Swaminathan
607fcf3ce44SJohn Forte /* Check if interrupts have been initialized */
608fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_INITED)) {
609fcf3ce44SJohn Forte ret = emlxs_msi_init(hba, 0);
610fcf3ce44SJohn Forte
611fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
612fcf3ce44SJohn Forte return (ret);
613fcf3ce44SJohn Forte }
614fcf3ce44SJohn Forte }
615291a2b48SSukumar Swaminathan
616fcf3ce44SJohn Forte /* Get handle table parameters */
617fcf3ce44SJohn Forte htable = hba->intr_htable;
618fcf3ce44SJohn Forte count = hba->intr_count;
619fcf3ce44SJohn Forte intr_cap = hba->intr_cap;
620fcf3ce44SJohn Forte
621fcf3ce44SJohn Forte /* Add the interrupt handlers */
622fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
623fcf3ce44SJohn Forte /* add handler for handle[i] */
624291a2b48SSukumar Swaminathan ret =
62582527734SSukumar Swaminathan ddi_intr_add_handler(htable[i], EMLXS_SLI_MSI_INTR,
626291a2b48SSukumar Swaminathan (char *)hba, (char *)((unsigned long)i));
627fcf3ce44SJohn Forte
628fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
629fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
630291a2b48SSukumar Swaminathan "MSI: ddi_intr_add_handler(%d) failed. "
631291a2b48SSukumar Swaminathan "handle=%p ret=%d",
632291a2b48SSukumar Swaminathan i, &htable[i], ret);
633fcf3ce44SJohn Forte
634fcf3ce44SJohn Forte /* Process the remaining interrupt handlers */
635fcf3ce44SJohn Forte while (i) {
636fcf3ce44SJohn Forte /* Decrement i */
637fcf3ce44SJohn Forte i--;
638fcf3ce44SJohn Forte
639fcf3ce44SJohn Forte /* Remove the handler */
640fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]);
641fcf3ce44SJohn Forte
642fcf3ce44SJohn Forte }
643fcf3ce44SJohn Forte
644fcf3ce44SJohn Forte return (DDI_FAILURE);
645fcf3ce44SJohn Forte }
646fcf3ce44SJohn Forte }
647fcf3ce44SJohn Forte
648fcf3ce44SJohn Forte /* Enable the interrupts */
649fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
650fcf3ce44SJohn Forte ret = ddi_intr_block_enable(htable, count);
651fcf3ce44SJohn Forte
652fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
653fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
654fcf3ce44SJohn Forte "MSI: ddi_intr_block_enable(%d) failed. ret=%d",
655fcf3ce44SJohn Forte count, ret);
656fcf3ce44SJohn Forte
657fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
658fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]);
659fcf3ce44SJohn Forte
660fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
661fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
662fcf3ce44SJohn Forte &emlxs_init_debug_msg,
663fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. "
664291a2b48SSukumar Swaminathan "ret=%d",
665291a2b48SSukumar Swaminathan i, ret);
666fcf3ce44SJohn Forte }
667fcf3ce44SJohn Forte }
668fcf3ce44SJohn Forte }
669fcf3ce44SJohn Forte } else {
670fcf3ce44SJohn Forte for (i = 0; i < count; ++i) {
671fcf3ce44SJohn Forte ret = ddi_intr_enable(htable[i]);
672fcf3ce44SJohn Forte
673fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
674291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT,
675291a2b48SSukumar Swaminathan &emlxs_init_debug_msg,
676fcf3ce44SJohn Forte "MSI: ddi_intr_enable(%d) failed. ret=%d",
677fcf3ce44SJohn Forte i, ret);
678fcf3ce44SJohn Forte }
679fcf3ce44SJohn Forte }
680fcf3ce44SJohn Forte }
681fcf3ce44SJohn Forte
682fcf3ce44SJohn Forte
683fcf3ce44SJohn Forte /* Set flag to indicate support */
684fcf3ce44SJohn Forte hba->intr_flags |= EMLXS_MSI_ADDED;
685fcf3ce44SJohn Forte
686fcf3ce44SJohn Forte return (DDI_SUCCESS);
687fcf3ce44SJohn Forte
68882527734SSukumar Swaminathan } /* emlxs_msi_add() */
689fcf3ce44SJohn Forte
690fcf3ce44SJohn Forte
691fcf3ce44SJohn Forte
692fcf3ce44SJohn Forte /* EMLXS_INTR_REMOVE */
693fcf3ce44SJohn Forte int32_t
emlxs_msi_remove(emlxs_hba_t * hba)694fcf3ce44SJohn Forte emlxs_msi_remove(emlxs_hba_t *hba)
695fcf3ce44SJohn Forte {
696fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
697fcf3ce44SJohn Forte uint32_t count;
698fcf3ce44SJohn Forte int32_t i;
699fcf3ce44SJohn Forte ddi_intr_handle_t *htable;
700fcf3ce44SJohn Forte int32_t *intr_cap;
701fcf3ce44SJohn Forte int32_t ret;
702fcf3ce44SJohn Forte
703fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ENABLED)) {
704fcf3ce44SJohn Forte return (emlxs_intx_remove(hba));
705fcf3ce44SJohn Forte }
706291a2b48SSukumar Swaminathan
707fcf3ce44SJohn Forte /*
708291a2b48SSukumar Swaminathan * EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
7098f23e9faSHans Rosenfeld * "MSI: msi_remove called. flags=%x",
710291a2b48SSukumar Swaminathan * hba->intr_flags);
711fcf3ce44SJohn Forte */
712fcf3ce44SJohn Forte
713fcf3ce44SJohn Forte /* Check if interrupts have already been removed */
714fcf3ce44SJohn Forte if (!(hba->intr_flags & EMLXS_MSI_ADDED)) {
715fcf3ce44SJohn Forte return (DDI_SUCCESS);
716fcf3ce44SJohn Forte }
717fcf3ce44SJohn Forte hba->intr_flags &= ~EMLXS_MSI_ADDED;
718fcf3ce44SJohn Forte
719fcf3ce44SJohn Forte /* Disable all adapter interrupts */
72082527734SSukumar Swaminathan EMLXS_SLI_DISABLE_INTR(hba, 0);
721fcf3ce44SJohn Forte
722fcf3ce44SJohn Forte /* Get handle table parameters */
723fcf3ce44SJohn Forte htable = hba->intr_htable;
724fcf3ce44SJohn Forte count = hba->intr_count;
725fcf3ce44SJohn Forte intr_cap = hba->intr_cap;
726fcf3ce44SJohn Forte
727fcf3ce44SJohn Forte /* Disable the interrupts */
728fcf3ce44SJohn Forte if (intr_cap[0] & DDI_INTR_FLAG_BLOCK) {
729fcf3ce44SJohn Forte ret = ddi_intr_block_disable(htable, count);
730fcf3ce44SJohn Forte
731fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
732fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_debug_msg,
733fcf3ce44SJohn Forte "MSI: ddi_intr_block_disable(%d) failed. ret=%d",
734fcf3ce44SJohn Forte count, ret);
735fcf3ce44SJohn Forte
736fcf3ce44SJohn Forte for (i = 0; i < count; i++) {
737fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]);
738fcf3ce44SJohn Forte
739fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
740fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT,
741fcf3ce44SJohn Forte &emlxs_init_debug_msg,
742fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. "
743291a2b48SSukumar Swaminathan "ret=%d",
744291a2b48SSukumar Swaminathan i, ret);
745fcf3ce44SJohn Forte }
746fcf3ce44SJohn Forte }
747fcf3ce44SJohn Forte }
748fcf3ce44SJohn Forte } else {
749fcf3ce44SJohn Forte for (i = 0; i < count; i++) {
750fcf3ce44SJohn Forte ret = ddi_intr_disable(htable[i]);
751fcf3ce44SJohn Forte
752fcf3ce44SJohn Forte if (ret != DDI_SUCCESS) {
753291a2b48SSukumar Swaminathan EMLXS_MSGF(EMLXS_CONTEXT,
754291a2b48SSukumar Swaminathan &emlxs_init_debug_msg,
755fcf3ce44SJohn Forte "MSI: ddi_intr_disable(%d) failed. ret=%d",
756fcf3ce44SJohn Forte i, ret);
757fcf3ce44SJohn Forte }
758fcf3ce44SJohn Forte }
759fcf3ce44SJohn Forte }
760fcf3ce44SJohn Forte
761fcf3ce44SJohn Forte /* Process the interrupt handlers */
762fcf3ce44SJohn Forte for (i = 0; i < count; i++) {
763fcf3ce44SJohn Forte /* Remove the handler */
764fcf3ce44SJohn Forte ret = ddi_intr_remove_handler(htable[i]);
765fcf3ce44SJohn Forte
766fcf3ce44SJohn Forte
767fcf3ce44SJohn Forte }
768fcf3ce44SJohn Forte
769fcf3ce44SJohn Forte return (DDI_SUCCESS);
770fcf3ce44SJohn Forte
77182527734SSukumar Swaminathan } /* emlxs_msi_remove() */
772fcf3ce44SJohn Forte
773291a2b48SSukumar Swaminathan #endif /* MSI_SUPPORT */
774fcf3ce44SJohn Forte
775fcf3ce44SJohn Forte
776fcf3ce44SJohn Forte /* EMLXS_INTR_INIT */
777fcf3ce44SJohn Forte /* ARGSUSED */
778fcf3ce44SJohn Forte int32_t
emlxs_intx_init(emlxs_hba_t * hba,uint32_t max)779fcf3ce44SJohn Forte emlxs_intx_init(emlxs_hba_t *hba, uint32_t max)
780fcf3ce44SJohn Forte {
781fcf3ce44SJohn Forte emlxs_port_t *port = &PPORT;
78282527734SSukumar Swaminathan emlxs_config_t *cfg = &CFG;
783fcf3ce44SJohn Forte int32_t ret;
784fcf3ce44SJohn Forte uint32_t i;
785fcf3ce44SJohn Forte
786fcf3ce44SJohn Forte /* Check if interrupts have already been initialized */
787fcf3ce44SJohn Forte if (hba->intr_flags & EMLXS_INTX_INITED) {
788fcf3ce44SJohn Forte return (DDI_SUCCESS);
789fcf3ce44SJohn Forte }
790291a2b48SSukumar Swaminathan
791fcf3ce44SJohn Forte /* Check if adapter is flagged for INTX support */
792fcf3ce44SJohn Forte if (!(hba->model_info.flags & EMLXS_INTX_SUPPORTED)) {
793fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
794fcf3ce44SJohn Forte "INTX: %s does not support INTX. flags=0x%x",
795fcf3ce44SJohn Forte hba->model_info.model, hba->model_info.flags);
796fcf3ce44SJohn Forte
797fcf3ce44SJohn Forte return (DDI_FAILURE);
798fcf3ce44SJohn Forte }
799291a2b48SSukumar Swaminathan
800fcf3ce44SJohn Forte /*
801291a2b48SSukumar Swaminathan * Interrupt number '0' is a high-level interrupt. This driver
802291a2b48SSukumar Swaminathan * does not support having its interrupts mapped above scheduler
803291a2b48SSukumar Swaminathan * priority; i.e., we always expect to be able to call general
804291a2b48SSukumar Swaminathan * kernel routines that may invoke the scheduler.
805fcf3ce44SJohn Forte */
806fcf3ce44SJohn Forte if (ddi_intr_hilevel(hba->dip, EMLXS_INUMBER) != 0) {
807fcf3ce44SJohn Forte EMLXS_MSGF(EMLXS_CONTEXT, &emlxs_init_failed_msg,
808fcf3ce44SJohn Forte "INTX: High-level interrupt not supported.");
809fcf3ce44SJohn Forte
810