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>

Split Close
Expand all
Collapse all
          --- old/usr/src/uts/i86pc/io/pci/pci_common.c
          +++ new/usr/src/uts/i86pc/io/pci/pci_common.c
↓ open down ↓ 13 lines elided ↑ open up ↑
  14   14   * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15   15   * If applicable, add the following below this CDDL HEADER, with the
  16   16   * fields enclosed by brackets "[]" replaced with your own identifying
  17   17   * information: Portions Copyright [yyyy] [name of copyright owner]
  18   18   *
  19   19   * CDDL HEADER END
  20   20   */
  21   21  
  22   22  /*
  23   23   * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
       24 + *
       25 + * Copyright (c) 2012, Nexenta Systems, Inc.  All rights reserved.
  24   26   */
  25   27  
  26   28  /*
  27   29   *      File that has code which is common between pci(7d) and npe(7d)
  28   30   *      It shares the following:
  29   31   *      - interrupt code
  30   32   *      - pci_tools ioctl code
  31   33   *      - name_child code
  32   34   *      - set_parent_private_data code
  33   35   */
↓ open down ↓ 159 lines elided ↑ open up ↑
 193  195          int                     priority = 0;
 194  196          int                     psm_status = 0;
 195  197          int                     pci_status = 0;
 196  198          int                     pci_rval, psm_rval = PSM_FAILURE;
 197  199          int                     types = 0;
 198  200          int                     pciepci = 0;
 199  201          int                     i, j, count;
 200  202          int                     rv;
 201  203          int                     behavior;
 202  204          int                     cap_ptr;
      205 +        boolean_t               did_pci_config_setup = B_FALSE;
      206 +        boolean_t               did_intr_vec_alloc = B_FALSE;
      207 +        boolean_t               did_msi_cap_set = B_FALSE;
 203  208          uint16_t                msi_cap_base, msix_cap_base, cap_ctrl;
 204  209          char                    *prop;
 205  210          ddi_intrspec_t          isp;
 206  211          struct intrspec         *ispec;
 207  212          ddi_intr_handle_impl_t  tmp_hdl;
 208  213          ddi_intr_msix_t         *msix_p;
 209  214          ihdl_plat_t             *ihdl_plat_datap;
 210  215          ddi_intr_handle_t       *h_array;
 211  216          ddi_acc_handle_t        handle;
 212  217          apic_get_intr_t         intrinfo;
↓ open down ↓ 120 lines elided ↑ open up ↑
 333  338                          behavior = (int)(uintptr_t)hdlp->ih_scratch2;
 334  339  
 335  340                          /*
 336  341                           * Cache in the config handle and cap_ptr
 337  342                           */
 338  343                          if (i_ddi_get_pci_config_handle(rdip) == NULL) {
 339  344                                  if (pci_config_setup(rdip, &handle) !=
 340  345                                      DDI_SUCCESS)
 341  346                                          return (DDI_FAILURE);
 342  347                                  i_ddi_set_pci_config_handle(rdip, handle);
      348 +                                did_pci_config_setup = B_TRUE;
 343  349                          }
 344  350  
 345  351                          prop = NULL;
 346  352                          cap_ptr = 0;
 347  353                          if (hdlp->ih_type == DDI_INTR_TYPE_MSI)
 348  354                                  prop = "pci-msi-capid-pointer";
 349  355                          else if (hdlp->ih_type == DDI_INTR_TYPE_MSIX)
 350  356                                  prop = "pci-msix-capid-pointer";
 351  357  
 352  358                          /*
↓ open down ↓ 5 lines elided ↑ open up ↑
 358  364                                      DDI_PROP_DONTPASS, prop, 0);
 359  365                                  if (cap_ptr == 0) {
 360  366                                          DDI_INTR_NEXDBG((CE_CONT,
 361  367                                              "pci_common_intr_ops: rdip: 0x%p "
 362  368                                              "attempted MSI(X) alloc without "
 363  369                                              "cap property\n", (void *)rdip));
 364  370                                          return (DDI_FAILURE);
 365  371                                  }
 366  372                          }
 367  373                          i_ddi_set_msi_msix_cap_ptr(rdip, cap_ptr);
      374 +                        did_msi_cap_set = B_TRUE;
 368  375  
 369  376                          /*
 370  377                           * Allocate interrupt vectors
 371  378                           */
 372  379                          (void) (*psm_intr_ops)(rdip, hdlp,
 373  380                              PSM_INTR_OP_ALLOC_VECTORS, result);
 374  381  
 375      -                        if (*(int *)result == 0)
 376      -                                return (DDI_INTR_NOTFOUND);
      382 +                        if (*(int *)result == 0) {
      383 +                                rv = DDI_INTR_NOTFOUND;
      384 +                                goto HANDLE_ALLOC_FAILURE;
      385 +                        }
      386 +                        did_intr_vec_alloc = B_TRUE;
 377  387  
 378  388                          /* verify behavior flag and take appropriate action */
 379  389                          if ((behavior == DDI_INTR_ALLOC_STRICT) &&
 380  390                              (*(int *)result < hdlp->ih_scratch1)) {
 381  391                                  DDI_INTR_NEXDBG((CE_CONT,
 382  392                                      "pci_common_intr_ops: behavior %x, "
 383  393                                      "couldn't get enough intrs\n", behavior));
 384  394                                  hdlp->ih_scratch1 = *(int *)result;
 385      -                                (void) (*psm_intr_ops)(rdip, hdlp,
 386      -                                    PSM_INTR_OP_FREE_VECTORS, NULL);
 387      -                                return (DDI_EAGAIN);
      395 +                                rv = DDI_EAGAIN;
      396 +                                goto HANDLE_ALLOC_FAILURE;
 388  397                          }
 389  398  
 390  399                          if (hdlp->ih_type == DDI_INTR_TYPE_MSIX) {
 391  400                                  if (!(msix_p = i_ddi_get_msix(hdlp->ih_dip))) {
 392  401                                          msix_p = pci_msix_init(hdlp->ih_dip);
 393  402                                          if (msix_p) {
 394  403                                                  i_ddi_set_msix(hdlp->ih_dip,
 395  404                                                      msix_p);
 396  405                                          } else {
 397  406                                                  DDI_INTR_NEXDBG((CE_CONT,
 398  407                                                      "pci_common_intr_ops: MSI-X"
 399  408                                                      "table initilization failed"
 400  409                                                      ", rdip 0x%p inum 0x%x\n",
 401  410                                                      (void *)rdip,
 402  411                                                      hdlp->ih_inum));
 403  412  
 404      -                                                (void) (*psm_intr_ops)(rdip,
 405      -                                                    hdlp,
 406      -                                                    PSM_INTR_OP_FREE_VECTORS,
 407      -                                                    NULL);
 408      -
 409      -                                                return (DDI_FAILURE);
      413 +                                                rv = DDI_FAILURE;
      414 +                                                goto HANDLE_ALLOC_FAILURE;
 410  415                                          }
 411  416                                  }
 412  417                          }
 413  418  
 414  419                          if (pciepci) {
 415  420                                  /* update priority in ispec */
 416  421                                  isp = pci_intx_get_ispec(pdip, rdip,
 417  422                                      (int)hdlp->ih_inum);
 418  423                                  ispec = (struct intrspec *)isp;
 419  424                                  if (ispec)
 420  425                                          ispec->intrspec_pri = hdlp->ih_pri;
 421  426                                  ++pcieb_intr_pri_counter;
 422  427                          }
 423  428  
 424  429                  } else
 425  430                          return (DDI_FAILURE);
 426  431                  break;
      432 +
      433 +HANDLE_ALLOC_FAILURE:
      434 +                if (did_intr_vec_alloc == B_TRUE)
      435 +                        (void) (*psm_intr_ops)(rdip, hdlp,
      436 +                            PSM_INTR_OP_FREE_VECTORS, NULL);
      437 +                if (did_msi_cap_set == B_TRUE)
      438 +                        i_ddi_set_msi_msix_cap_ptr(rdip, 0);
      439 +                if (did_pci_config_setup == B_TRUE) {
      440 +                        (void) pci_config_teardown(&handle);
      441 +                        i_ddi_set_pci_config_handle(rdip, NULL);
      442 +                }
      443 +                return (rv);
      444 +
 427  445          case DDI_INTROP_FREE:
 428  446                  if (DDI_INTR_IS_MSI_OR_MSIX(hdlp->ih_type) &&
 429  447                      (psm_intr_ops != NULL)) {
 430  448                          if (i_ddi_intr_get_current_nintrs(hdlp->ih_dip) - 1 ==
 431  449                              0) {
 432  450                                  if (handle = i_ddi_get_pci_config_handle(
 433  451                                      rdip)) {
 434  452                                          (void) pci_config_teardown(&handle);
 435  453                                          i_ddi_set_pci_config_handle(rdip, NULL);
 436  454                                  }
↓ open down ↓ 1325 lines elided ↑ open up ↑
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX