11e66f787SSean Bruno /*-
2*7ea28254SJohn Hall * Copyright 2016-2023 Microchip Technology, Inc. and/or its subsidiaries.
31e66f787SSean Bruno *
41e66f787SSean Bruno * Redistribution and use in source and binary forms, with or without
51e66f787SSean Bruno * modification, are permitted provided that the following conditions
61e66f787SSean Bruno * are met:
71e66f787SSean Bruno * 1. Redistributions of source code must retain the above copyright
81e66f787SSean Bruno * notice, this list of conditions and the following disclaimer.
91e66f787SSean Bruno * 2. Redistributions in binary form must reproduce the above copyright
101e66f787SSean Bruno * notice, this list of conditions and the following disclaimer in the
111e66f787SSean Bruno * documentation and/or other materials provided with the distribution.
121e66f787SSean Bruno *
131e66f787SSean Bruno * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
141e66f787SSean Bruno * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
151e66f787SSean Bruno * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
161e66f787SSean Bruno * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
171e66f787SSean Bruno * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
181e66f787SSean Bruno * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
191e66f787SSean Bruno * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
201e66f787SSean Bruno * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
211e66f787SSean Bruno * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
221e66f787SSean Bruno * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
231e66f787SSean Bruno * SUCH DAMAGE.
241e66f787SSean Bruno */
251e66f787SSean Bruno
261e66f787SSean Bruno
271e66f787SSean Bruno #include "smartpqi_includes.h"
281e66f787SSean Bruno
29*7ea28254SJohn Hall
301e66f787SSean Bruno /*
311e66f787SSean Bruno * Function to get processor count
321e66f787SSean Bruno */
339fac68fcSPAPANI SRIKANTH int
os_get_processor_config(pqisrc_softstate_t * softs)349fac68fcSPAPANI SRIKANTH os_get_processor_config(pqisrc_softstate_t *softs)
351e66f787SSean Bruno {
361e66f787SSean Bruno DBG_FUNC("IN\n");
371e66f787SSean Bruno softs->num_cpus_online = mp_ncpus;
38*7ea28254SJohn Hall bsd_set_hint_adapter_cpu_config(softs);
391e66f787SSean Bruno DBG_FUNC("OUT\n");
401e66f787SSean Bruno
411e66f787SSean Bruno return PQI_STATUS_SUCCESS;
421e66f787SSean Bruno }
431e66f787SSean Bruno
441e66f787SSean Bruno /*
451e66f787SSean Bruno * Function to get interrupt count and type supported
461e66f787SSean Bruno */
479fac68fcSPAPANI SRIKANTH int
os_get_intr_config(pqisrc_softstate_t * softs)489fac68fcSPAPANI SRIKANTH os_get_intr_config(pqisrc_softstate_t *softs)
491e66f787SSean Bruno {
509fac68fcSPAPANI SRIKANTH device_t dev = softs->os_specific.pqi_dev;
519fac68fcSPAPANI SRIKANTH int msi_count = pci_msix_count(dev);
529fac68fcSPAPANI SRIKANTH int error = BSD_SUCCESS;
531e66f787SSean Bruno
541e66f787SSean Bruno DBG_FUNC("IN\n");
551e66f787SSean Bruno
561e66f787SSean Bruno if (msi_count > softs->num_cpus_online)
571e66f787SSean Bruno msi_count = softs->num_cpus_online;
581e66f787SSean Bruno if (msi_count > PQI_MAX_MSIX)
591e66f787SSean Bruno msi_count = PQI_MAX_MSIX;
601e66f787SSean Bruno if (msi_count == 0 || (error = pci_alloc_msix(dev, &msi_count)) != 0) {
611e66f787SSean Bruno device_printf(dev, "alloc msix failed - msi_count=%d, err=%d; "
621e66f787SSean Bruno "will try MSI\n", msi_count, error);
631e66f787SSean Bruno pci_release_msi(dev);
641e66f787SSean Bruno } else {
651e66f787SSean Bruno softs->intr_count = msi_count;
661e66f787SSean Bruno softs->intr_type = INTR_TYPE_MSIX;
671e66f787SSean Bruno softs->os_specific.msi_enabled = TRUE;
681e66f787SSean Bruno device_printf(dev, "using MSI-X interrupts (%d vectors)\n",
691e66f787SSean Bruno msi_count);
701e66f787SSean Bruno }
711e66f787SSean Bruno if (!softs->intr_type) {
721e66f787SSean Bruno msi_count = 1;
731e66f787SSean Bruno if ((error = pci_alloc_msi(dev, &msi_count)) != 0) {
741e66f787SSean Bruno device_printf(dev, "alloc msi failed - err=%d; "
751e66f787SSean Bruno "will use INTx\n", error);
761e66f787SSean Bruno pci_release_msi(dev);
771e66f787SSean Bruno } else {
781e66f787SSean Bruno softs->os_specific.msi_enabled = TRUE;
791e66f787SSean Bruno softs->intr_count = msi_count;
801e66f787SSean Bruno softs->intr_type = INTR_TYPE_MSI;
811e66f787SSean Bruno device_printf(dev, "using MSI interrupts\n");
821e66f787SSean Bruno }
831e66f787SSean Bruno }
841e66f787SSean Bruno
851e66f787SSean Bruno if (!softs->intr_type) {
861e66f787SSean Bruno device_printf(dev, "using legacy interrupts\n");
871e66f787SSean Bruno softs->intr_type = INTR_TYPE_FIXED;
881e66f787SSean Bruno softs->intr_count = 1;
891e66f787SSean Bruno }
901e66f787SSean Bruno
919fac68fcSPAPANI SRIKANTH error = bsd_status_to_pqi_status(BSD_SUCCESS);
929fac68fcSPAPANI SRIKANTH
93*7ea28254SJohn Hall DBG_FUNC("OUT\n");
94*7ea28254SJohn Hall
959fac68fcSPAPANI SRIKANTH return error;
961e66f787SSean Bruno }
971e66f787SSean Bruno
989fac68fcSPAPANI SRIKANTH void
os_eventtaskqueue_enqueue(pqisrc_softstate_t * sc)999fac68fcSPAPANI SRIKANTH os_eventtaskqueue_enqueue(pqisrc_softstate_t *sc)
1001e66f787SSean Bruno {
1011e66f787SSean Bruno taskqueue_enqueue(taskqueue_swi, &sc->os_specific.event_task);
1021e66f787SSean Bruno }
1031e66f787SSean Bruno
1049fac68fcSPAPANI SRIKANTH void
pqisrc_event_worker(void * arg1,int arg2)1059fac68fcSPAPANI SRIKANTH pqisrc_event_worker(void *arg1, int arg2)
1061e66f787SSean Bruno {
1071e66f787SSean Bruno pqisrc_ack_all_events(arg1);
1081e66f787SSean Bruno }
1091e66f787SSean Bruno
1101e66f787SSean Bruno /*
1111e66f787SSean Bruno * ithread routine to handle uniprocessor systems
1121e66f787SSean Bruno */
1139fac68fcSPAPANI SRIKANTH static void
shared_ithread_routine(void * arg)1149fac68fcSPAPANI SRIKANTH shared_ithread_routine(void *arg)
1151e66f787SSean Bruno {
1161e66f787SSean Bruno pqi_intr_ctx_t *intr_ctx = (pqi_intr_ctx_t *)arg;
1171e66f787SSean Bruno pqisrc_softstate_t *softs = device_get_softc(intr_ctx->pqi_dev);
1181e66f787SSean Bruno int oq_id = intr_ctx->oq_id;
1191e66f787SSean Bruno
1201e66f787SSean Bruno DBG_FUNC("IN\n");
1211e66f787SSean Bruno
122*7ea28254SJohn Hall if (!softs)
1239fac68fcSPAPANI SRIKANTH return;
1249fac68fcSPAPANI SRIKANTH
1251e66f787SSean Bruno pqisrc_process_response_queue(softs, oq_id);
1261e66f787SSean Bruno pqisrc_process_event_intr_src(softs, oq_id - 1);
1271e66f787SSean Bruno
1281e66f787SSean Bruno DBG_FUNC("OUT\n");
1291e66f787SSean Bruno }
1301e66f787SSean Bruno
1311e66f787SSean Bruno /*
1321e66f787SSean Bruno * ithread routine to process non event response
1331e66f787SSean Bruno */
1349fac68fcSPAPANI SRIKANTH static void
common_ithread_routine(void * arg)1359fac68fcSPAPANI SRIKANTH common_ithread_routine(void *arg)
1361e66f787SSean Bruno {
1371e66f787SSean Bruno pqi_intr_ctx_t *intr_ctx = (pqi_intr_ctx_t *)arg;
1381e66f787SSean Bruno pqisrc_softstate_t *softs = device_get_softc(intr_ctx->pqi_dev);
1391e66f787SSean Bruno int oq_id = intr_ctx->oq_id;
1401e66f787SSean Bruno
1411e66f787SSean Bruno DBG_FUNC("IN\n");
1421e66f787SSean Bruno
143*7ea28254SJohn Hall if (!softs)
1449fac68fcSPAPANI SRIKANTH return;
1459fac68fcSPAPANI SRIKANTH
1461e66f787SSean Bruno pqisrc_process_response_queue(softs, oq_id);
1471e66f787SSean Bruno
1481e66f787SSean Bruno DBG_FUNC("OUT\n");
1491e66f787SSean Bruno }
1501e66f787SSean Bruno
1519fac68fcSPAPANI SRIKANTH static void
event_ithread_routine(void * arg)1529fac68fcSPAPANI SRIKANTH event_ithread_routine(void *arg)
1531e66f787SSean Bruno {
1541e66f787SSean Bruno pqi_intr_ctx_t *intr_ctx = (pqi_intr_ctx_t *)arg;
1551e66f787SSean Bruno pqisrc_softstate_t *softs = device_get_softc(intr_ctx->pqi_dev);
1561e66f787SSean Bruno int oq_id = intr_ctx->oq_id;
1571e66f787SSean Bruno
1581e66f787SSean Bruno DBG_FUNC("IN\n");
1591e66f787SSean Bruno
160*7ea28254SJohn Hall if (!softs)
1619fac68fcSPAPANI SRIKANTH return;
1629fac68fcSPAPANI SRIKANTH
1631e66f787SSean Bruno pqisrc_process_event_intr_src(softs, oq_id);
1641e66f787SSean Bruno
1651e66f787SSean Bruno DBG_FUNC("OUT\n");
1661e66f787SSean Bruno }
1671e66f787SSean Bruno
1681e66f787SSean Bruno /*
1691e66f787SSean Bruno * Registration of legacy interrupt in case MSI is unsupported
1701e66f787SSean Bruno */
1719fac68fcSPAPANI SRIKANTH int
register_legacy_intr(pqisrc_softstate_t * softs)1729fac68fcSPAPANI SRIKANTH register_legacy_intr(pqisrc_softstate_t *softs)
1731e66f787SSean Bruno {
1749fac68fcSPAPANI SRIKANTH int error = BSD_SUCCESS;
175*7ea28254SJohn Hall device_t dev;
1761e66f787SSean Bruno
1771e66f787SSean Bruno DBG_FUNC("IN\n");
1781e66f787SSean Bruno
179*7ea28254SJohn Hall dev = softs->os_specific.pqi_dev;
180*7ea28254SJohn Hall
1811e66f787SSean Bruno softs->os_specific.pqi_irq_rid[0] = 0;
1821e66f787SSean Bruno softs->os_specific.pqi_irq[0] = bus_alloc_resource_any(dev, \
1831e66f787SSean Bruno SYS_RES_IRQ, &softs->os_specific.pqi_irq_rid[0],
1841e66f787SSean Bruno RF_ACTIVE | RF_SHAREABLE);
1851e66f787SSean Bruno if (NULL == softs->os_specific.pqi_irq[0]) {
1861e66f787SSean Bruno DBG_ERR("Failed to allocate resource for interrupt\n");
1879fac68fcSPAPANI SRIKANTH return ENXIO;
1881e66f787SSean Bruno }
1891e66f787SSean Bruno if ((softs->os_specific.msi_ctx = os_mem_alloc(softs,sizeof(pqi_intr_ctx_t))) == NULL) {
1901e66f787SSean Bruno DBG_ERR("Failed to allocate memory for msi_ctx\n");
1919fac68fcSPAPANI SRIKANTH return ENXIO;
1921e66f787SSean Bruno }
1931e66f787SSean Bruno softs->os_specific.msi_ctx[0].pqi_dev = dev;
1949fac68fcSPAPANI SRIKANTH /* For Legacy support oq_id should be one */
195b17f4335SSean Bruno softs->os_specific.msi_ctx[0].oq_id = 1;
1961e66f787SSean Bruno
1971e66f787SSean Bruno error = bus_setup_intr(dev, softs->os_specific.pqi_irq[0],
1981e66f787SSean Bruno INTR_TYPE_CAM | INTR_MPSAFE, \
1991e66f787SSean Bruno NULL, shared_ithread_routine,
2001e66f787SSean Bruno &softs->os_specific.msi_ctx[0],
2011e66f787SSean Bruno &softs->os_specific.intrcookie[0]);
2021e66f787SSean Bruno if (error) {
2031e66f787SSean Bruno DBG_ERR("Failed to setup legacy interrupt err = %d\n", error);
2041e66f787SSean Bruno return error;
2051e66f787SSean Bruno }
2061e66f787SSean Bruno softs->os_specific.intr_registered[0] = TRUE;
2071e66f787SSean Bruno
2081e66f787SSean Bruno DBG_FUNC("OUT error = %d\n", error);
2091e66f787SSean Bruno
2101e66f787SSean Bruno return error;
2111e66f787SSean Bruno }
2121e66f787SSean Bruno
2131e66f787SSean Bruno /*
2141e66f787SSean Bruno * Registration of MSIx
2151e66f787SSean Bruno */
2169fac68fcSPAPANI SRIKANTH int
register_msix_intr(pqisrc_softstate_t * softs)2179fac68fcSPAPANI SRIKANTH register_msix_intr(pqisrc_softstate_t *softs)
2181e66f787SSean Bruno {
2199fac68fcSPAPANI SRIKANTH int error = BSD_SUCCESS;
2201e66f787SSean Bruno int i = 0;
2219fac68fcSPAPANI SRIKANTH device_t dev = softs->os_specific.pqi_dev;
2221e66f787SSean Bruno int msix_count = softs->intr_count;
223*7ea28254SJohn Hall size_t msix_size = sizeof(pqi_intr_ctx_t) * msix_count;
2241e66f787SSean Bruno
2251e66f787SSean Bruno DBG_FUNC("IN\n");
2261e66f787SSean Bruno
227*7ea28254SJohn Hall softs->os_specific.msi_ctx = os_mem_alloc(softs, msix_size);
2289fac68fcSPAPANI SRIKANTH if (!softs->os_specific.msi_ctx) {
229*7ea28254SJohn Hall DBG_ERR("Memory allocation failed, Requested memory:%lu bytes\n", (unsigned long)msix_size);
2309fac68fcSPAPANI SRIKANTH return ENXIO;
2319fac68fcSPAPANI SRIKANTH }
2329fac68fcSPAPANI SRIKANTH
2331e66f787SSean Bruno /*Add shared handler */
2341e66f787SSean Bruno if (softs->share_opq_and_eventq) {
2351e66f787SSean Bruno softs->os_specific.pqi_irq_rid[i] = i+1;
2361e66f787SSean Bruno softs->os_specific.pqi_irq[i] = bus_alloc_resource_any(dev, \
2371e66f787SSean Bruno SYS_RES_IRQ,
2381e66f787SSean Bruno &softs->os_specific.pqi_irq_rid[i],
2391e66f787SSean Bruno RF_SHAREABLE | RF_ACTIVE);
2401e66f787SSean Bruno if (NULL == softs->os_specific.pqi_irq[i]) {
2411e66f787SSean Bruno DBG_ERR("Failed to allocate \
2421e66f787SSean Bruno event interrupt resource\n");
2439fac68fcSPAPANI SRIKANTH return ENXIO;
2441e66f787SSean Bruno }
2451e66f787SSean Bruno
2461e66f787SSean Bruno softs->os_specific.msi_ctx[i].pqi_dev = dev;
247b17f4335SSean Bruno softs->os_specific.msi_ctx[i].oq_id = i+1;
2481e66f787SSean Bruno
2491e66f787SSean Bruno error = bus_setup_intr(dev,softs->os_specific.pqi_irq[i],
2501e66f787SSean Bruno INTR_TYPE_CAM | INTR_MPSAFE,\
2511e66f787SSean Bruno NULL,
2521e66f787SSean Bruno shared_ithread_routine,
2531e66f787SSean Bruno &softs->os_specific.msi_ctx[i],
2541e66f787SSean Bruno &softs->os_specific.intrcookie[i]);
2551e66f787SSean Bruno
2561e66f787SSean Bruno if (error) {
2571e66f787SSean Bruno DBG_ERR("Failed to setup interrupt for events r=%d\n",
2581e66f787SSean Bruno error);
2591e66f787SSean Bruno return error;
2601e66f787SSean Bruno }
2611e66f787SSean Bruno softs->os_specific.intr_registered[i] = TRUE;
2621e66f787SSean Bruno }
2631e66f787SSean Bruno else {
2641e66f787SSean Bruno /* Add event handler */
2651e66f787SSean Bruno softs->os_specific.pqi_irq_rid[i] = i+1;
2661e66f787SSean Bruno softs->os_specific.pqi_irq[i] = bus_alloc_resource_any(dev, \
2671e66f787SSean Bruno SYS_RES_IRQ,
2681e66f787SSean Bruno &softs->os_specific.pqi_irq_rid[i],
2691e66f787SSean Bruno RF_SHAREABLE | RF_ACTIVE);
2701e66f787SSean Bruno if (NULL == softs->os_specific.pqi_irq[i]) {
2719fac68fcSPAPANI SRIKANTH DBG_ERR("Failed to allocate event interrupt resource\n");
2729fac68fcSPAPANI SRIKANTH return ENXIO;
2731e66f787SSean Bruno }
2741e66f787SSean Bruno
2751e66f787SSean Bruno softs->os_specific.msi_ctx[i].pqi_dev = dev;
2761e66f787SSean Bruno softs->os_specific.msi_ctx[i].oq_id = i;
2771e66f787SSean Bruno
2781e66f787SSean Bruno error = bus_setup_intr(dev,softs->os_specific.pqi_irq[i],
2791e66f787SSean Bruno INTR_TYPE_CAM | INTR_MPSAFE,\
2801e66f787SSean Bruno NULL,
2811e66f787SSean Bruno event_ithread_routine,
2821e66f787SSean Bruno &softs->os_specific.msi_ctx[i],
2831e66f787SSean Bruno &softs->os_specific.intrcookie[i]);
2841e66f787SSean Bruno if (error) {
2851e66f787SSean Bruno DBG_ERR("Failed to setup interrupt for events err=%d\n",
2861e66f787SSean Bruno error);
2871e66f787SSean Bruno return error;
2881e66f787SSean Bruno }
2891e66f787SSean Bruno softs->os_specific.intr_registered[i] = TRUE;
2901e66f787SSean Bruno /* Add interrupt handlers*/
2911e66f787SSean Bruno for (i = 1; i < msix_count; ++i) {
2921e66f787SSean Bruno softs->os_specific.pqi_irq_rid[i] = i+1;
2931e66f787SSean Bruno softs->os_specific.pqi_irq[i] = \
2941e66f787SSean Bruno bus_alloc_resource_any(dev,
2951e66f787SSean Bruno SYS_RES_IRQ,
2961e66f787SSean Bruno &softs->os_specific.pqi_irq_rid[i],
2971e66f787SSean Bruno RF_SHAREABLE | RF_ACTIVE);
2981e66f787SSean Bruno if (NULL == softs->os_specific.pqi_irq[i]) {
2991e66f787SSean Bruno DBG_ERR("Failed to allocate \
3001e66f787SSean Bruno msi/x interrupt resource\n");
3019fac68fcSPAPANI SRIKANTH return ENXIO;
3021e66f787SSean Bruno }
3031e66f787SSean Bruno softs->os_specific.msi_ctx[i].pqi_dev = dev;
3041e66f787SSean Bruno softs->os_specific.msi_ctx[i].oq_id = i;
3051e66f787SSean Bruno error = bus_setup_intr(dev,
3061e66f787SSean Bruno softs->os_specific.pqi_irq[i],
3071e66f787SSean Bruno INTR_TYPE_CAM | INTR_MPSAFE,\
3081e66f787SSean Bruno NULL,
3091e66f787SSean Bruno common_ithread_routine,
3101e66f787SSean Bruno &softs->os_specific.msi_ctx[i],
3111e66f787SSean Bruno &softs->os_specific.intrcookie[i]);
3121e66f787SSean Bruno if (error) {
3131e66f787SSean Bruno DBG_ERR("Failed to setup \
3141e66f787SSean Bruno msi/x interrupt error = %d\n", error);
3151e66f787SSean Bruno return error;
3161e66f787SSean Bruno }
3171e66f787SSean Bruno softs->os_specific.intr_registered[i] = TRUE;
3181e66f787SSean Bruno }
3191e66f787SSean Bruno }
3201e66f787SSean Bruno
3211e66f787SSean Bruno DBG_FUNC("OUT error = %d\n", error);
3221e66f787SSean Bruno
3231e66f787SSean Bruno return error;
3241e66f787SSean Bruno }
3251e66f787SSean Bruno
3261e66f787SSean Bruno /*
3271e66f787SSean Bruno * Setup interrupt depending on the configuration
3281e66f787SSean Bruno */
3299fac68fcSPAPANI SRIKANTH int
os_setup_intr(pqisrc_softstate_t * softs)3309fac68fcSPAPANI SRIKANTH os_setup_intr(pqisrc_softstate_t *softs)
3311e66f787SSean Bruno {
3329fac68fcSPAPANI SRIKANTH int bsd_status, pqi_status;
3331e66f787SSean Bruno
3341e66f787SSean Bruno DBG_FUNC("IN\n");
3351e66f787SSean Bruno
3361e66f787SSean Bruno if (softs->intr_type == INTR_TYPE_FIXED) {
3379fac68fcSPAPANI SRIKANTH bsd_status = register_legacy_intr(softs);
3381e66f787SSean Bruno }
3391e66f787SSean Bruno else {
3409fac68fcSPAPANI SRIKANTH bsd_status = register_msix_intr(softs);
3411e66f787SSean Bruno }
3421e66f787SSean Bruno
3439fac68fcSPAPANI SRIKANTH if (bsd_status)
3449fac68fcSPAPANI SRIKANTH DBG_WARN("interrupt registration is failed, error = %d\n", bsd_status);
3451e66f787SSean Bruno
3469fac68fcSPAPANI SRIKANTH pqi_status = bsd_status_to_pqi_status(bsd_status);
3479fac68fcSPAPANI SRIKANTH
3489fac68fcSPAPANI SRIKANTH DBG_FUNC("OUT\n");
3499fac68fcSPAPANI SRIKANTH
3509fac68fcSPAPANI SRIKANTH return pqi_status;
3511e66f787SSean Bruno }
3521e66f787SSean Bruno
3531e66f787SSean Bruno /*
3541e66f787SSean Bruno * Deregistration of legacy interrupt
3551e66f787SSean Bruno */
3569fac68fcSPAPANI SRIKANTH void
deregister_pqi_intx(pqisrc_softstate_t * softs)3579fac68fcSPAPANI SRIKANTH deregister_pqi_intx(pqisrc_softstate_t *softs)
3581e66f787SSean Bruno {
3599fac68fcSPAPANI SRIKANTH device_t dev = softs->os_specific.pqi_dev;
3601e66f787SSean Bruno
3611e66f787SSean Bruno DBG_FUNC("IN\n");
3621e66f787SSean Bruno
3631e66f787SSean Bruno if (softs->os_specific.pqi_irq[0] != NULL) {
3641e66f787SSean Bruno if (softs->os_specific.intr_registered[0]) {
3651e66f787SSean Bruno bus_teardown_intr(dev, softs->os_specific.pqi_irq[0],
3661e66f787SSean Bruno softs->os_specific.intrcookie[0]);
3671e66f787SSean Bruno softs->os_specific.intr_registered[0] = FALSE;
3681e66f787SSean Bruno }
3691e66f787SSean Bruno bus_release_resource(dev, SYS_RES_IRQ,
3701e66f787SSean Bruno softs->os_specific.pqi_irq_rid[0],
3711e66f787SSean Bruno softs->os_specific.pqi_irq[0]);
3721e66f787SSean Bruno softs->os_specific.pqi_irq[0] = NULL;
3731e66f787SSean Bruno os_mem_free(softs, (char*)softs->os_specific.msi_ctx, sizeof(pqi_intr_ctx_t));
3741e66f787SSean Bruno }
3751e66f787SSean Bruno
3761e66f787SSean Bruno DBG_FUNC("OUT\n");
3771e66f787SSean Bruno }
3781e66f787SSean Bruno
3791e66f787SSean Bruno /*
3801e66f787SSean Bruno * Deregistration of MSIx interrupt
3811e66f787SSean Bruno */
3829fac68fcSPAPANI SRIKANTH void
deregister_pqi_msix(pqisrc_softstate_t * softs)3839fac68fcSPAPANI SRIKANTH deregister_pqi_msix(pqisrc_softstate_t *softs)
3841e66f787SSean Bruno {
3859fac68fcSPAPANI SRIKANTH device_t dev = softs->os_specific.pqi_dev;
3861e66f787SSean Bruno int msix_count = softs->intr_count;
3871e66f787SSean Bruno int i = 0;
3881e66f787SSean Bruno
3891e66f787SSean Bruno DBG_FUNC("IN\n");
3901e66f787SSean Bruno
3911e66f787SSean Bruno os_mem_free(softs, (char*)softs->os_specific.msi_ctx, sizeof(pqi_intr_ctx_t) * msix_count);
3921e66f787SSean Bruno softs->os_specific.msi_ctx = NULL;
3931e66f787SSean Bruno
3941e66f787SSean Bruno for (; i < msix_count; ++i) {
3951e66f787SSean Bruno if (softs->os_specific.pqi_irq[i] != NULL) {
3961e66f787SSean Bruno if (softs->os_specific.intr_registered[i]) {
3971e66f787SSean Bruno bus_teardown_intr(dev,
3981e66f787SSean Bruno softs->os_specific.pqi_irq[i],
3991e66f787SSean Bruno softs->os_specific.intrcookie[i]);
4001e66f787SSean Bruno softs->os_specific.intr_registered[i] = FALSE;
4011e66f787SSean Bruno }
4021e66f787SSean Bruno bus_release_resource(dev, SYS_RES_IRQ,
4031e66f787SSean Bruno softs->os_specific.pqi_irq_rid[i],
4041e66f787SSean Bruno softs->os_specific.pqi_irq[i]);
4051e66f787SSean Bruno softs->os_specific.pqi_irq[i] = NULL;
4061e66f787SSean Bruno }
4071e66f787SSean Bruno }
4081e66f787SSean Bruno
4091e66f787SSean Bruno DBG_FUNC("OUT\n");
4101e66f787SSean Bruno }
4111e66f787SSean Bruno
4121e66f787SSean Bruno /*
4131e66f787SSean Bruno * Function to destroy interrupts registered
4141e66f787SSean Bruno */
4159fac68fcSPAPANI SRIKANTH int
os_destroy_intr(pqisrc_softstate_t * softs)4169fac68fcSPAPANI SRIKANTH os_destroy_intr(pqisrc_softstate_t *softs)
4171e66f787SSean Bruno {
4189fac68fcSPAPANI SRIKANTH device_t dev = softs->os_specific.pqi_dev;
4191e66f787SSean Bruno
4201e66f787SSean Bruno DBG_FUNC("IN\n");
4211e66f787SSean Bruno
4221e66f787SSean Bruno if (softs->intr_type == INTR_TYPE_FIXED) {
4231e66f787SSean Bruno deregister_pqi_intx(softs);
4241e66f787SSean Bruno } else if (softs->intr_type == INTR_TYPE_MSIX) {
4251e66f787SSean Bruno deregister_pqi_msix(softs);
4261e66f787SSean Bruno }
4271e66f787SSean Bruno if (softs->os_specific.msi_enabled) {
4281e66f787SSean Bruno pci_release_msi(dev);
4291e66f787SSean Bruno softs->os_specific.msi_enabled = FALSE;
4301e66f787SSean Bruno }
4311e66f787SSean Bruno
4321e66f787SSean Bruno DBG_FUNC("OUT\n");
4331e66f787SSean Bruno
4341e66f787SSean Bruno return PQI_STATUS_SUCCESS;
4351e66f787SSean Bruno }
4361e66f787SSean Bruno
4371e66f787SSean Bruno /*
4381e66f787SSean Bruno * Free interrupt related resources for the adapter
4391e66f787SSean Bruno */
4409fac68fcSPAPANI SRIKANTH void
os_free_intr_config(pqisrc_softstate_t * softs)4419fac68fcSPAPANI SRIKANTH os_free_intr_config(pqisrc_softstate_t *softs)
4421e66f787SSean Bruno {
4439fac68fcSPAPANI SRIKANTH device_t dev = softs->os_specific.pqi_dev;
4441e66f787SSean Bruno
4451e66f787SSean Bruno DBG_FUNC("IN\n");
4461e66f787SSean Bruno
4471e66f787SSean Bruno if (softs->os_specific.msi_enabled) {
4481e66f787SSean Bruno pci_release_msi(dev);
4491e66f787SSean Bruno softs->os_specific.msi_enabled = FALSE;
4501e66f787SSean Bruno }
4511e66f787SSean Bruno
4521e66f787SSean Bruno DBG_FUNC("OUT\n");
4531e66f787SSean Bruno }
454