static void ppb_removechild(dev_info_t *dip) { struct ddi_parent_private_data *pdptr; ppb_devstate_t *ppb; ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state, ddi_get_instance(ddi_get_parent(dip))); if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) { pcie_fini_dom(dip); pcie_fini_cfghdl(dip); } else if ((pdptr = ddi_get_parent_data(dip)) != NULL) { kmem_free(pdptr, (sizeof (*pdptr) + sizeof (struct intrspec))); ddi_set_parent_data(dip, NULL); } ddi_set_name_addr(dip, NULL); /* * Strip the node to properly convert it back to prototype form */ ddi_remove_minor_node(dip, NULL); impl_rem_dev_props(dip); }
static void ppb_uninitchild(dev_info_t *child) { ppb_devstate_t *ppb; ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state, ddi_get_instance(ddi_get_parent(child))); /* * SG OPL FMA specific */ if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) { pcie_fini_dom(child); pcie_fini_cfghdl(child); } ppb_removechild(child); }
static int ppb_initchild(dev_info_t *child) { struct ddi_parent_private_data *pdptr; ppb_devstate_t *ppb; char name[MAXNAMELEN]; ddi_acc_handle_t config_handle; ushort_t command_preserve, command; ppb = (ppb_devstate_t *)ddi_get_soft_state(ppb_state, ddi_get_instance(ddi_get_parent(child))); if (ppb_name_child(child, name, MAXNAMELEN) != DDI_SUCCESS) return (DDI_FAILURE); ddi_set_name_addr(child, name); /* * Pseudo nodes indicate a prototype node with per-instance * properties to be merged into the real h/w device node. * The interpretation of the unit-address is DD[,F] * where DD is the device id and F is the function. */ if (ndi_dev_is_persistent_node(child) == 0) { extern int pci_allow_pseudo_children; ddi_set_parent_data(child, NULL); /* * Try to merge the properties from this prototype * node into real h/w nodes. */ if (ndi_merge_node(child, ppb_name_child) == DDI_SUCCESS) { /* * Merged ok - return failure to remove the node. */ ddi_set_name_addr(child, NULL); return (DDI_FAILURE); } /* workaround for ddivs to run under PCI */ if (pci_allow_pseudo_children) return (DDI_SUCCESS); /* * The child was not merged into a h/w node, * but there's not much we can do with it other * than return failure to cause the node to be removed. */ cmn_err(CE_WARN, "!%s@%s: %s.conf properties not merged", ddi_driver_name(child), ddi_get_name_addr(child), ddi_driver_name(child)); ddi_set_name_addr(child, NULL); return (DDI_NOT_WELL_FORMED); } ddi_set_parent_data(child, NULL); /* * PCIe FMA specific * * Note: parent_data for parent is created only if this is PCI-E * platform, for which, SG take a different route to handle device * errors. */ if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) { if (pcie_init_cfghdl(child) != DDI_SUCCESS) return (DDI_FAILURE); pcie_init_dom(child); } /* transfer select properties from PROM to kernel */ if (ddi_getprop(DDI_DEV_T_NONE, child, DDI_PROP_DONTPASS, "interrupts", -1) != -1) { pdptr = kmem_zalloc((sizeof (struct ddi_parent_private_data) + sizeof (struct intrspec)), KM_SLEEP); pdptr->par_intr = (struct intrspec *)(pdptr + 1); pdptr->par_nintr = 1; ddi_set_parent_data(child, pdptr); } else ddi_set_parent_data(child, NULL); if (pci_config_setup(child, &config_handle) != DDI_SUCCESS) { pcie_fini_dom(child); return (DDI_FAILURE); } /* * Support for the "command-preserve" property. */ command_preserve = ddi_prop_get_int(DDI_DEV_T_ANY, child, DDI_PROP_DONTPASS, "command-preserve", 0); command = pci_config_get16(config_handle, PCI_CONF_COMM); command &= (command_preserve | PCI_COMM_BACK2BACK_ENAB); command |= (ppb_command_default & ~command_preserve); pci_config_put16(config_handle, PCI_CONF_COMM, command); pci_config_teardown(&config_handle); return (DDI_SUCCESS); }