Exemplo n.º 1
0
/*ARGSUSED*/
static int
ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
	ppb_devstate_t *ppb;
	int		ret = DDI_SUCCESS;

	switch (cmd) {
	case DDI_DETACH:
		/*
		 * And finally free the per-pci soft state after
		 * uninitializing hotplug support for this bus.
		 */
		ppb = (ppb_devstate_t *)
		    ddi_get_soft_state(ppb_state, ddi_get_instance(devi));

		ppb_fm_fini(ppb);

		if (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV)
			ret = pcie_uninit(devi);
		else if (ppb->hotplug_capable == B_TRUE)
			ret = pcihp_init(devi);
		else
			ddi_remove_minor_node(devi, "devctl");

		if (ret != DDI_SUCCESS)
			return (DDI_FAILURE);

		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");

		if (ppb->ppb_pwr_p != NULL) {
			ppb_pwr_teardown(ppb, devi);
		}
		mutex_destroy(&ppb->ppb_mutex);
		ddi_soft_state_free(ppb_state, ddi_get_instance(devi));

		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		ppb = (ppb_devstate_t *)
		    ddi_get_soft_state(ppb_state, ddi_get_instance(devi));

		pci_pwr_suspend(devi, ppb->ppb_pwr_p);

		return (DDI_SUCCESS);
	}
	return (DDI_FAILURE);
}
Exemplo n.º 2
0
/*ARGSUSED*/
static int
ppb_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
{
	ppb_devstate_t *ppb;
	int		ret;

	switch (cmd) {
	case DDI_DETACH:
		(void) ddi_prop_remove(DDI_DEV_T_NONE, devi, "device_type");

		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
		if (ppb->ppb_fmcap & DDI_FM_ERRCB_CAPABLE)
			ddi_fm_handler_unregister(devi);
		if (ppb->ppb_fmcap & (DDI_FM_ERRCB_CAPABLE |
		    DDI_FM_EREPORT_CAPABLE))
			pci_ereport_teardown(devi);

		/*
		 * Uninitialize hotplug support on this bus.
		 */
		ret = (ppb->parent_bus == PCIE_PCIECAP_DEV_TYPE_PCIE_DEV) ?
		    pcie_uninit(devi) : pcihp_uninit(devi);
		if (ret != DDI_SUCCESS)
			return (DDI_FAILURE);

		mutex_destroy(&ppb->ppb_peek_poke_mutex);
		mutex_destroy(&ppb->ppb_err_mutex);
		mutex_destroy(&ppb->ppb_mutex);
		ddi_fm_fini(devi);

		/*
		 * And finally free the per-pci soft state.
		 */
		ddi_soft_state_free(ppb_state, ddi_get_instance(devi));

		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		ppb = ddi_get_soft_state(ppb_state, ddi_get_instance(devi));
		ppb_save_config_regs(ppb);
		return (DDI_SUCCESS);

	default:
		break;
	}
	return (DDI_FAILURE);
}
Exemplo n.º 3
0
/*ARGSUSED*/
static int
px_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
{
	int		instance = ddi_get_instance(dip);
	px_t		*px_p = INST_TO_STATE(instance);
	pcie_bus_t	*bus_p = PCIE_DIP2BUS(dip);
	int		ret;

	/*
	 * Make sure we are currently attached
	 */
	if (px_p->px_state != PX_ATTACHED) {
		DBG(DBG_DETACH, dip, "Instance not attached\n");
		return (DDI_FAILURE);
	}

	mutex_enter(&px_p->px_mutex);

	switch (cmd) {
	case DDI_DETACH:
		DBG(DBG_DETACH, dip, "DDI_DETACH\n");

		/*
		 * remove cpr callback
		 */
		px_cpr_rem_callb(px_p);

		(void) pcie_hpintr_disable(dip);

		if (PCIE_IS_PCIE_HOTPLUG_ENABLED(bus_p))
			(void) px_lib_hotplug_uninit(dip);

		if (pcie_uninit(dip) != DDI_SUCCESS) {
			mutex_exit(&px_p->px_mutex);
			return (DDI_FAILURE);
		}

		/* Destroy bus_t for the whole fabric */
		pcie_fab_fini_bus(dip, PCIE_BUS_ALL);

		/*
		 * things which used to be done in obj_destroy
		 * are now in-lined here.
		 */

		px_p->px_state = PX_DETACHED;

		pxtool_uninit(dip);

		px_disable_err_intr(px_p);
		px_fm_detach(px_p);
		px_pec_detach(px_p);
		px_pwr_teardown(dip);
		pwr_common_teardown(dip);
		px_msi_detach(px_p);
		px_msiq_detach(px_p);
		px_mmu_detach(px_p);
		px_ib_detach(px_p);
		if (px_lib_dev_fini(dip) != DDI_SUCCESS) {
			DBG(DBG_DETACH, dip, "px_lib_dev_fini failed\n");
		}

		/*
		 * Free the px soft state structure and the rest of the
		 * resources it's using.
		 */
		px_free_props(px_p);
		pcie_rc_fini_bus(dip);
		px_dbg_detach(dip, &px_p->px_dbg_hdl);
		mutex_exit(&px_p->px_mutex);
		mutex_destroy(&px_p->px_mutex);

		px_p->px_dev_hdl = NULL;
		ddi_soft_state_free(px_state_p, instance);

		return (DDI_SUCCESS);

	case DDI_SUSPEND:
		if (pcie_pwr_suspend(dip) != DDI_SUCCESS) {
			mutex_exit(&px_p->px_mutex);
			return (DDI_FAILURE);
		}
		if ((ret = px_lib_suspend(dip)) == DDI_SUCCESS)
			px_p->px_state = PX_SUSPENDED;
		mutex_exit(&px_p->px_mutex);

		return (ret);

	default:
		DBG(DBG_DETACH, dip, "unsupported detach op\n");
		mutex_exit(&px_p->px_mutex);
		return (DDI_FAILURE);
	}
}
Exemplo n.º 4
0
/*ARGSUSED*/
static int
px_attach(dev_info_t *dip, ddi_attach_cmd_t cmd)
{
	px_t		*px_p;	/* per bus state pointer */
	int		instance = DIP_TO_INST(dip);
	int		ret = DDI_SUCCESS;
	devhandle_t	dev_hdl = NULL;
	pcie_hp_regops_t regops;
	pcie_bus_t	*bus_p;

	switch (cmd) {
	case DDI_ATTACH:
		DBG(DBG_ATTACH, dip, "DDI_ATTACH\n");

		/* See pci_cfgacc.c */
		pci_cfgacc_acc_p = pci_cfgacc_acc;

		/*
		 * Allocate and get the per-px soft state structure.
		 */
		if (ddi_soft_state_zalloc(px_state_p, instance)
		    != DDI_SUCCESS) {
			cmn_err(CE_WARN, "%s%d: can't allocate px state",
			    ddi_driver_name(dip), instance);
			goto err_bad_px_softstate;
		}
		px_p = INST_TO_STATE(instance);
		px_p->px_dip = dip;
		mutex_init(&px_p->px_mutex, NULL, MUTEX_DRIVER, NULL);
		px_p->px_soft_state = PCI_SOFT_STATE_CLOSED;

		(void) ddi_prop_update_string(DDI_DEV_T_NONE, dip,
		    "device_type", "pciex");

		/* Initialize px_dbg for high pil printing */
		px_dbg_attach(dip, &px_p->px_dbg_hdl);
		pcie_rc_init_bus(dip);

		/*
		 * Get key properties of the pci bridge node and
		 * determine it's type (psycho, schizo, etc ...).
		 */
		if (px_get_props(px_p, dip) == DDI_FAILURE)
			goto err_bad_px_prop;

		if (px_lib_dev_init(dip, &dev_hdl) != DDI_SUCCESS)
			goto err_bad_dev_init;

		/* Initialize device handle */
		px_p->px_dev_hdl = dev_hdl;

		/* Cache the BDF of the root port nexus */
		px_p->px_bdf = px_lib_get_bdf(px_p);

		/*
		 * Initialize interrupt block.  Note that this
		 * initialize error handling for the PEC as well.
		 */
		if ((ret = px_ib_attach(px_p)) != DDI_SUCCESS)
			goto err_bad_ib;

		if (px_cb_attach(px_p) != DDI_SUCCESS)
			goto err_bad_cb;

		/*
		 * Start creating the modules.
		 * Note that attach() routines should
		 * register and enable their own interrupts.
		 */

		if ((px_mmu_attach(px_p)) != DDI_SUCCESS)
			goto err_bad_mmu;

		if ((px_msiq_attach(px_p)) != DDI_SUCCESS)
			goto err_bad_msiq;

		if ((px_msi_attach(px_p)) != DDI_SUCCESS)
			goto err_bad_msi;

		if ((px_pec_attach(px_p)) != DDI_SUCCESS)
			goto err_bad_pec;

		if ((px_dma_attach(px_p)) != DDI_SUCCESS)
			goto err_bad_dma; /* nothing to uninitialize on DMA */

		if ((px_fm_attach(px_p)) != DDI_SUCCESS)
			goto err_bad_dma;

		/*
		 * All of the error handlers have been registered
		 * by now so it's time to activate all the interrupt.
		 */
		if ((px_enable_err_intr(px_p)) != DDI_SUCCESS)
			goto err_bad_intr;

		if (px_lib_hotplug_init(dip, (void *)&regops) == DDI_SUCCESS) {
			pcie_bus_t	*bus_p = PCIE_DIP2BUS(dip);

			bus_p->bus_hp_sup_modes |= PCIE_NATIVE_HP_MODE;
		}

		(void) px_set_mps(px_p);

		if (pcie_init(dip, (caddr_t)&regops) != DDI_SUCCESS)
			goto err_bad_hotplug;

		(void) pcie_hpintr_enable(dip);

		if (pxtool_init(dip) != DDI_SUCCESS)
			goto err_bad_pcitool_node;

		/*
		 * power management setup. Even if it fails, attach will
		 * succeed as this is a optional feature. Since we are
		 * always at full power, this is not critical.
		 */
		if (pwr_common_setup(dip) != DDI_SUCCESS) {
			DBG(DBG_PWR, dip, "pwr_common_setup failed\n");
		} else if (px_pwr_setup(dip) != DDI_SUCCESS) {
			DBG(DBG_PWR, dip, "px_pwr_setup failed \n");
			pwr_common_teardown(dip);
		}

		/*
		 * add cpr callback
		 */
		px_cpr_add_callb(px_p);

		/*
		 * do fabric sync in case we don't need to wait for
		 * any bridge driver to be ready
		 */
		(void) px_lib_fabric_sync(dip);

		ddi_report_dev(dip);

		px_p->px_state = PX_ATTACHED;

		/*
		 * save base addr in bus_t for pci_cfgacc_xxx(), this
		 * depends of px structure being properly initialized.
		 */
		bus_p = PCIE_DIP2BUS(dip);
		bus_p->bus_cfgacc_base = px_lib_get_cfgacc_base(dip);

		/*
		 * Partially populate bus_t for all devices in this fabric
		 * for device type macros to work.
		 */
		/*
		 * Populate bus_t for all devices in this fabric, after FMA
		 * is initializated, so that config access errors could
		 * trigger panic.
		 */
		pcie_fab_init_bus(dip, PCIE_BUS_ALL);

		DBG(DBG_ATTACH, dip, "attach success\n");
		break;

err_bad_pcitool_node:
		(void) pcie_hpintr_disable(dip);
		(void) pcie_uninit(dip);
err_bad_hotplug:
		(void) px_lib_hotplug_uninit(dip);
		px_disable_err_intr(px_p);
err_bad_intr:
		px_fm_detach(px_p);
err_bad_dma:
		px_pec_detach(px_p);
err_bad_pec:
		px_msi_detach(px_p);
err_bad_msi:
		px_msiq_detach(px_p);
err_bad_msiq:
		px_mmu_detach(px_p);
err_bad_mmu:
err_bad_cb:
		px_ib_detach(px_p);
err_bad_ib:
		if (px_lib_dev_fini(dip) != DDI_SUCCESS) {
			DBG(DBG_ATTACH, dip, "px_lib_dev_fini failed\n");
		}
err_bad_dev_init:
		px_free_props(px_p);
err_bad_px_prop:
		pcie_rc_fini_bus(dip);
		px_dbg_detach(dip, &px_p->px_dbg_hdl);
		mutex_destroy(&px_p->px_mutex);
		ddi_soft_state_free(px_state_p, instance);
err_bad_px_softstate:
		ret = DDI_FAILURE;
		break;

	case DDI_RESUME:
		DBG(DBG_ATTACH, dip, "DDI_RESUME\n");

		px_p = INST_TO_STATE(instance);

		mutex_enter(&px_p->px_mutex);

		/* suspend might have not succeeded */
		if (px_p->px_state != PX_SUSPENDED) {
			DBG(DBG_ATTACH, px_p->px_dip,
			    "instance NOT suspended\n");
			ret = DDI_FAILURE;
			break;
		}

		px_msiq_resume(px_p);
		px_lib_resume(dip);
		(void) pcie_pwr_resume(dip);
		px_p->px_state = PX_ATTACHED;

		mutex_exit(&px_p->px_mutex);

		break;
	default:
		DBG(DBG_ATTACH, dip, "unsupported attach op\n");
		ret = DDI_FAILURE;
		break;
	}

	return (ret);
}