ddi_hp_ndi.c revision 269473047d747f7815af570197e4ef7322d3632c
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER START
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The contents of this file are subject to the terms of the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Common Development and Distribution License (the "License").
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You may not use this file except in compliance with the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
269473047d747f7815af570197e4ef7322d3632cEvan Yan * See the License for the specific language governing permissions
269473047d747f7815af570197e4ef7322d3632cEvan Yan * and limitations under the License.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * When distributing Covered Code, include this CDDL HEADER in each
269473047d747f7815af570197e4ef7322d3632cEvan Yan * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If applicable, add the following below this CDDL HEADER, with the
269473047d747f7815af570197e4ef7322d3632cEvan Yan * fields enclosed by brackets "[]" replaced with your own identifying
269473047d747f7815af570197e4ef7322d3632cEvan Yan * information: Portions Copyright [yyyy] [name of copyright owner]
269473047d747f7815af570197e4ef7322d3632cEvan Yan * CDDL HEADER END
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Use is subject to license terms.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Sun NDI hotplug interfaces
269473047d747f7815af570197e4ef7322d3632cEvan Yan/* Local functions prototype */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic int ddihp_cn_req_handler(ddi_hp_cn_handle_t *hdlp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Global functions (called by hotplug controller or nexus drivers)
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Register the Hotplug Connection (CN)
269473047d747f7815af570197e4ef7322d3632cEvan Yanndi_hp_register(dev_info_t *dip, ddi_hp_cn_info_t *info_p)
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ndi_hp_register: dip %p, info_p %p\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Validate the arguments */
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Lock before access */
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp = ddihp_cn_name_to_handle(dip, info_p->cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* This cn_name is already registered. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Create and initialize hotplug Connection handle
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Copy the Connection information */
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Copy cn_name */
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp->cn_info.cn_name = ddi_strdup(info_p->cn_name, KM_SLEEP);
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ndi_hp_register: dip %p, hdlp %p"
269473047d747f7815af570197e4ef7322d3632cEvan Yan "ddi_cn_getstate failed\n", (void *)dip, (void *)hdlp));
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Append the handle to the list
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDIHP_LIST_APPEND(ddi_hp_cn_handle_t, (DEVI(dip)->devi_hp_hdlp),
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(hdlp->cn_info.cn_name, strlen(hdlp->cn_info.cn_name) + 1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Unregister a Hotplug Connection (CN)
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ndi_hp_unregister: dip %p, cn name %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Validate the arguments */
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Notify the Hotplug Connection (CN) to change state.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * DDI_HP_REQ_SYNC Return after the change is finished.
269473047d747f7815af570197e4ef7322d3632cEvan Yan * DDI_HP_REQ_ASYNC Return after the request is dispatched.
269473047d747f7815af570197e4ef7322d3632cEvan Yanndi_hp_state_change_req(dev_info_t *dip, char *cn_name,
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ndi_hp_state_change_req: dip %p "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "cn_name: %s, state %x, flag %x\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Validate the arguments */
269473047d747f7815af570197e4ef7322d3632cEvan Yan * If the request is to handle the event synchronously, then call
269473047d747f7815af570197e4ef7322d3632cEvan Yan * the event handler without queuing the event.
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ndi_hp_state_change_req: hdlp %p "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "calling ddihp_cn_req_handler() directly to handle "
269473047d747f7815af570197e4ef7322d3632cEvan Yan eventp = kmem_zalloc(sizeof (ddi_hp_cn_async_event_entry_t),
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(eventp, sizeof (ddi_hp_cn_async_event_entry_t));
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Hold the parent's ref so that it won't disappear when the taskq is
269473047d747f7815af570197e4ef7322d3632cEvan Yan * scheduled to run.
269473047d747f7815af570197e4ef7322d3632cEvan Yan if (!taskq_dispatch(system_taskq, ddihp_cn_run_event, eventp,
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ndi_hp_state_change_req: "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "taskq_dispatch failed! dip %p "
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Walk the link of Hotplug Connection handles of a dip:
269473047d747f7815af570197e4ef7322d3632cEvan Yan * DEVI(dip)->devi_hp_hdlp->[link of connections]
269473047d747f7815af570197e4ef7322d3632cEvan Yanndi_hp_walk_cn(dev_info_t *dip, int (*f)(ddi_hp_cn_info_t *,
269473047d747f7815af570197e4ef7322d3632cEvan Yan void *), void *arg)
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ndi_hp_walk_cn: dip %p arg %p\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Validate the arguments */
269473047d747f7815af570197e4ef7322d3632cEvan Yan "current cn_name: %s\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The current node is head and it is removed
269473047d747f7815af570197e4ef7322d3632cEvan Yan * by last call to (*f)()
269473047d747f7815af570197e4ef7322d3632cEvan Yan * The current node is a middle node or tail
269473047d747f7815af570197e4ef7322d3632cEvan Yan * node and it is removed by last call to
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* no removal accurred on curr node */
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Local functions (called within this file)
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Wrapper function for ddihp_cn_req_handler() called from taskq
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Lock before access */
269473047d747f7815af570197e4ef7322d3632cEvan Yan hdlp = ddihp_cn_name_to_handle(dip, eventp->cn_name);
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void) ddihp_cn_req_handler(hdlp, eventp->target_state);
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_run_event: no handle for "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "cn_name: %s dip %p. Request for target_state %x is"
269473047d747f7815af570197e4ef7322d3632cEvan Yan " dropped. \n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan eventp->cn_name, (void *)dip, eventp->target_state));
269473047d747f7815af570197e4ef7322d3632cEvan Yan /* Release the devi's ref that is held from interrupt context. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(eventp->cn_name, strlen(eventp->cn_name) + 1);
269473047d747f7815af570197e4ef7322d3632cEvan Yan kmem_free(eventp, sizeof (ddi_hp_cn_async_event_entry_t));
269473047d747f7815af570197e4ef7322d3632cEvan Yan * Handle state change request of a Hotplug Connection (CN)
269473047d747f7815af570197e4ef7322d3632cEvan Yan " hdlp %p, target_state %x\n",
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_req_handler: dip %p, "
269473047d747f7815af570197e4ef7322d3632cEvan Yan (void *)&target_state, (void *)&result_state, ret);
269473047d747f7815af570197e4ef7322d3632cEvan Yan DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_req_handler: dip %p, "
269473047d747f7815af570197e4ef7322d3632cEvan Yan "hdlp %p changed state to %x, ret=%x\n",