Print this page
3235 pci: pci_common_intr_ops() leaks ddi_acc_handle_t
Reviewed by: Dan McDonald <danmcd@nexenta.com>
Reviewed by: Boris Protopopov <boris.protopopov@nexenta.com>

*** 19,28 **** --- 19,30 ---- * CDDL HEADER END */ /* * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. + * + * Copyright (c) 2012, Nexenta Systems, Inc. All rights reserved. */ /* * File that has code which is common between pci(7d) and npe(7d) * It shares the following:
*** 198,207 **** --- 200,212 ---- int pciepci = 0; int i, j, count; int rv; int behavior; int cap_ptr; + boolean_t did_pci_config_setup = B_FALSE; + boolean_t did_intr_vec_alloc = B_FALSE; + boolean_t did_msi_cap_set = B_FALSE; uint16_t msi_cap_base, msix_cap_base, cap_ctrl; char *prop; ddi_intrspec_t isp; struct intrspec *ispec; ddi_intr_handle_impl_t tmp_hdl;
*** 338,347 **** --- 343,353 ---- if (i_ddi_get_pci_config_handle(rdip) == NULL) { if (pci_config_setup(rdip, &handle) != DDI_SUCCESS) return (DDI_FAILURE); i_ddi_set_pci_config_handle(rdip, handle); + did_pci_config_setup = B_TRUE; } prop = NULL; cap_ptr = 0; if (hdlp->ih_type == DDI_INTR_TYPE_MSI)
*** 363,392 **** "cap property\n", (void *)rdip)); return (DDI_FAILURE); } } i_ddi_set_msi_msix_cap_ptr(rdip, cap_ptr); /* * Allocate interrupt vectors */ (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_ALLOC_VECTORS, result); ! if (*(int *)result == 0) ! return (DDI_INTR_NOTFOUND); /* verify behavior flag and take appropriate action */ if ((behavior == DDI_INTR_ALLOC_STRICT) && (*(int *)result < hdlp->ih_scratch1)) { DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: behavior %x, " "couldn't get enough intrs\n", behavior)); hdlp->ih_scratch1 = *(int *)result; ! (void) (*psm_intr_ops)(rdip, hdlp, ! PSM_INTR_OP_FREE_VECTORS, NULL); ! return (DDI_EAGAIN); } if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) { if (!(msix_p = i_ddi_get_msix(hdlp->ih_dip))) { msix_p = pci_msix_init(hdlp->ih_dip); --- 369,401 ---- "cap property\n", (void *)rdip)); return (DDI_FAILURE); } } i_ddi_set_msi_msix_cap_ptr(rdip, cap_ptr); + did_msi_cap_set = B_TRUE; /* * Allocate interrupt vectors */ (void) (*psm_intr_ops)(rdip, hdlp, PSM_INTR_OP_ALLOC_VECTORS, result); ! if (*(int *)result == 0) { ! rv = DDI_INTR_NOTFOUND; ! goto HANDLE_ALLOC_FAILURE; ! } ! did_intr_vec_alloc = B_TRUE; /* verify behavior flag and take appropriate action */ if ((behavior == DDI_INTR_ALLOC_STRICT) && (*(int *)result < hdlp->ih_scratch1)) { DDI_INTR_NEXDBG((CE_CONT, "pci_common_intr_ops: behavior %x, " "couldn't get enough intrs\n", behavior)); hdlp->ih_scratch1 = *(int *)result; ! rv = DDI_EAGAIN; ! goto HANDLE_ALLOC_FAILURE; } if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) { if (!(msix_p = i_ddi_get_msix(hdlp->ih_dip))) { msix_p = pci_msix_init(hdlp->ih_dip);
*** 399,414 **** "table initilization failed" ", rdip 0x%p inum 0x%x\n", (void *)rdip, hdlp->ih_inum)); ! (void) (*psm_intr_ops)(rdip, ! hdlp, ! PSM_INTR_OP_FREE_VECTORS, ! NULL); ! ! return (DDI_FAILURE); } } } if (pciepci) { --- 408,419 ---- "table initilization failed" ", rdip 0x%p inum 0x%x\n", (void *)rdip, hdlp->ih_inum)); ! rv = DDI_FAILURE; ! goto HANDLE_ALLOC_FAILURE; } } } if (pciepci) {
*** 422,431 **** --- 427,449 ---- } } else return (DDI_FAILURE); break; + + HANDLE_ALLOC_FAILURE: + if (did_intr_vec_alloc == B_TRUE) + (void) (*psm_intr_ops)(rdip, hdlp, + PSM_INTR_OP_FREE_VECTORS, NULL); + if (did_msi_cap_set == B_TRUE) + i_ddi_set_msi_msix_cap_ptr(rdip, 0); + if (did_pci_config_setup == B_TRUE) { + (void) pci_config_teardown(&handle); + i_ddi_set_pci_config_handle(rdip, NULL); + } + return (rv); + case DDI_INTROP_FREE: if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) && (psm_intr_ops != NULL)) { if (i_ddi_intr_get_current_nintrs(hdlp->ih_dip) - 1 == 0) {