Esempio n. 1
0
void
pcmu_child_cfg_save(dev_info_t *dip)
{
	dev_info_t *cdip;
	int ret = DDI_SUCCESS;

	/*
	 * Save the state of the configuration headers of child
	 * nodes.
	 */

	for (cdip = ddi_get_child(dip); cdip != NULL;
	    cdip = ddi_get_next_sibling(cdip)) {

		/*
		 * Not interested in children who are not already
		 * init'ed.  They will be set up in pcmu_init_child().
		 */
		if (i_ddi_node_state(cdip) < DS_INITIALIZED) {
			PCMU_DBG2(PCMU_DBG_DETACH, dip, "DDI_SUSPEND: skipping "
			    "%s%d not in CF1\n", ddi_driver_name(cdip),
			    ddi_get_instance(cdip));

			continue;
		}

		/*
		 * Only save config registers if not already saved by child.
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
		    SAVED_CONFIG_REGS) == 1) {

			continue;
		}

		/*
		 * The nexus needs to save config registers.  Create a property
		 * so it knows to restore on resume.
		 */
		ret = ndi_prop_create_boolean(DDI_DEV_T_NONE, cdip,
		    "nexus-saved-config-regs");

		if (ret != DDI_PROP_SUCCESS) {
			cmn_err(CE_WARN, "%s%d can't update prop %s",
			    ddi_driver_name(cdip), ddi_get_instance(cdip),
			    "nexus-saved-config-regs");
		}

		(void) pci_save_config_regs(cdip);
	}
}
Esempio n. 2
0
void
pcmu_child_cfg_restore(dev_info_t *dip)
{
	dev_info_t *cdip;

	/*
	 * Restore config registers for children that did not save
	 * their own registers.  Children pwr states are UNKNOWN after
	 * a resume since it is possible for the PM framework to call
	 * resume without an actual power cycle. (ie if suspend fails).
	 */
	for (cdip = ddi_get_child(dip); cdip != NULL;
	    cdip = ddi_get_next_sibling(cdip)) {

		/*
		 * Not interested in children who are not already
		 * init'ed.  They will be set up by pcmu_init_child().
		 */
		if (i_ddi_node_state(cdip) < DS_INITIALIZED) {
			PCMU_DBG2(PCMU_DBG_DETACH, dip,
			    "DDI_RESUME: skipping %s%d not in CF1\n",
			    ddi_driver_name(cdip), ddi_get_instance(cdip));
			continue;
		}

		/*
		 * Only restore config registers if saved by nexus.
		 */
		if (ddi_prop_exists(DDI_DEV_T_ANY, cdip, DDI_PROP_DONTPASS,
		    "nexus-saved-config-regs") == 1) {
			(void) pci_restore_config_regs(cdip);

			PCMU_DBG2(PCMU_DBG_PWR, dip,
			    "DDI_RESUME: nexus restoring %s%d config regs\n",
			    ddi_driver_name(cdip), ddi_get_instance(cdip));

			if (ndi_prop_remove(DDI_DEV_T_NONE, cdip,
			    "nexus-saved-config-regs") != DDI_PROP_SUCCESS) {
				cmn_err(CE_WARN, "%s%d can't remove prop %s",
				    ddi_driver_name(cdip),
				    ddi_get_instance(cdip),
				    "nexus-saved-config-regs");
			}
		}
	}
}
Esempio n. 3
0
int
iommulib_nexus_register(dev_info_t *dip, iommulib_nexops_t *nexops,
    iommulib_nexhandle_t *handle)
{
	iommulib_nex_t *nexp;
	int instance = ddi_get_instance(dip);
	const char *driver = ddi_driver_name(dip);
	dev_info_t *pdip = ddi_get_parent(dip);
	const char *f = "iommulib_nexus_register";

	ASSERT(nexops);
	ASSERT(handle);

	*handle = NULL;

	/*
	 * Root node is never busy held
	 */
	if (dip != ddi_root_node() && (i_ddi_node_state(dip) < DS_PROBED ||
	    !DEVI_BUSY_OWNED(pdip))) {
		cmn_err(CE_WARN, "%s: NEXUS devinfo node not in DS_PROBED "
		    "or busy held for nexops vector (%p). Failing registration",
		    f, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_vers != IOMMU_NEXOPS_VERSION) {
		cmn_err(CE_WARN, "%s: %s%d: Invalid IOMMULIB nexops version "
		    "in nexops vector (%p). Failing NEXUS registration",
		    f, driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	ASSERT(nexops->nops_data == NULL);

	if (nexops->nops_id == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL ID field. "
		    "Failing registration for nexops vector: %p",
		    f, driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_allochdl == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_allochdl op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_freehdl == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_freehdl op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_bindhdl == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_bindhdl op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_sync == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_sync op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_reset_cookies == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_reset_cookies op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_get_cookies == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_cookies op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_set_cookies == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_set_cookies op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_clear_cookies == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_clear_cookies op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_get_sleep_flags == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_get_sleep_flags op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dma_win == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dma_win op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dmahdl_setprivate == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_setprivate op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	if (nexops->nops_dmahdl_getprivate == NULL) {
		cmn_err(CE_WARN, "%s: %s%d: NULL nops_dmahdl_getprivate op. "
		    "Failing registration for ops vector: %p", f,
		    driver, instance, (void *)nexops);
		return (DDI_FAILURE);
	}

	nexp = kmem_zalloc(sizeof (iommulib_nex_t), KM_SLEEP);

	mutex_enter(&iommulib_lock);
	if (iommulib_fini == 1) {
		mutex_exit(&iommulib_lock);
		cmn_err(CE_WARN, "%s: IOMMULIB unloading. "
		    "Failing NEXUS register.", f);
		kmem_free(nexp, sizeof (iommulib_nex_t));
		return (DDI_FAILURE);
	}

	/*
	 * fini/register race conditions have been handled. Now create the
	 * nexus struct
	 */
	ndi_hold_devi(dip);
	nexp->nex_dip = dip;
	nexp->nex_ops = *nexops;

	mutex_enter(&iommulib_nexus_lock);
	nexp->nex_next = iommulib_nexus_list;
	iommulib_nexus_list = nexp;
	nexp->nex_prev = NULL;

	if (nexp->nex_next != NULL)
		nexp->nex_next->nex_prev = nexp;

	nexp->nex_ref = 0;

	/*
	 * The nexus device won't be controlled by an IOMMU.
	 */
	DEVI(dip)->devi_iommulib_handle = IOMMU_HANDLE_UNUSED;

	DEVI(dip)->devi_iommulib_nex_handle = nexp;

	mutex_exit(&iommulib_nexus_lock);
	mutex_exit(&iommulib_lock);

	cmn_err(CE_NOTE, "!%s: %s%d: Succesfully registered NEXUS %s "
	    "nexops=%p", f, driver, instance, ddi_node_name(dip),
	    (void *)nexops);

	*handle = nexp;

	return (DDI_SUCCESS);
}