xref: /illumos-gate/usr/src/uts/common/os/ddi_hp_ndi.c (revision 269473047d747f7815af570197e4ef7322d3632c)
1*26947304SEvan Yan /*
2*26947304SEvan Yan  * CDDL HEADER START
3*26947304SEvan Yan  *
4*26947304SEvan Yan  * The contents of this file are subject to the terms of the
5*26947304SEvan Yan  * Common Development and Distribution License (the "License").
6*26947304SEvan Yan  * You may not use this file except in compliance with the License.
7*26947304SEvan Yan  *
8*26947304SEvan Yan  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*26947304SEvan Yan  * or http://www.opensolaris.org/os/licensing.
10*26947304SEvan Yan  * See the License for the specific language governing permissions
11*26947304SEvan Yan  * and limitations under the License.
12*26947304SEvan Yan  *
13*26947304SEvan Yan  * When distributing Covered Code, include this CDDL HEADER in each
14*26947304SEvan Yan  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*26947304SEvan Yan  * If applicable, add the following below this CDDL HEADER, with the
16*26947304SEvan Yan  * fields enclosed by brackets "[]" replaced with your own identifying
17*26947304SEvan Yan  * information: Portions Copyright [yyyy] [name of copyright owner]
18*26947304SEvan Yan  *
19*26947304SEvan Yan  * CDDL HEADER END
20*26947304SEvan Yan  */
21*26947304SEvan Yan /*
22*26947304SEvan Yan  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
23*26947304SEvan Yan  * Use is subject to license terms.
24*26947304SEvan Yan  */
25*26947304SEvan Yan 
26*26947304SEvan Yan /*
27*26947304SEvan Yan  * Sun NDI hotplug interfaces
28*26947304SEvan Yan  */
29*26947304SEvan Yan 
30*26947304SEvan Yan #include <sys/note.h>
31*26947304SEvan Yan #include <sys/sysmacros.h>
32*26947304SEvan Yan #include <sys/types.h>
33*26947304SEvan Yan #include <sys/param.h>
34*26947304SEvan Yan #include <sys/systm.h>
35*26947304SEvan Yan #include <sys/kmem.h>
36*26947304SEvan Yan #include <sys/cmn_err.h>
37*26947304SEvan Yan #include <sys/debug.h>
38*26947304SEvan Yan #include <sys/avintr.h>
39*26947304SEvan Yan #include <sys/autoconf.h>
40*26947304SEvan Yan #include <sys/sunndi.h>
41*26947304SEvan Yan #include <sys/ndi_impldefs.h>
42*26947304SEvan Yan #include <sys/ddi.h>
43*26947304SEvan Yan #include <sys/disp.h>
44*26947304SEvan Yan #include <sys/stat.h>
45*26947304SEvan Yan #include <sys/callb.h>
46*26947304SEvan Yan #include <sys/sysevent.h>
47*26947304SEvan Yan #include <sys/sysevent/eventdefs.h>
48*26947304SEvan Yan #include <sys/sysevent/dr.h>
49*26947304SEvan Yan #include <sys/taskq.h>
50*26947304SEvan Yan 
51*26947304SEvan Yan /* Local functions prototype */
52*26947304SEvan Yan static void ddihp_cn_run_event(void *arg);
53*26947304SEvan Yan static int ddihp_cn_req_handler(ddi_hp_cn_handle_t *hdlp,
54*26947304SEvan Yan     ddi_hp_cn_state_t target_state);
55*26947304SEvan Yan 
56*26947304SEvan Yan /*
57*26947304SEvan Yan  * Global functions (called by hotplug controller or nexus drivers)
58*26947304SEvan Yan  */
59*26947304SEvan Yan 
60*26947304SEvan Yan /*
61*26947304SEvan Yan  * Register the Hotplug Connection (CN)
62*26947304SEvan Yan  */
63*26947304SEvan Yan int
64*26947304SEvan Yan ndi_hp_register(dev_info_t *dip, ddi_hp_cn_info_t *info_p)
65*26947304SEvan Yan {
66*26947304SEvan Yan 	ddi_hp_cn_handle_t	*hdlp;
67*26947304SEvan Yan 	int			count;
68*26947304SEvan Yan 
69*26947304SEvan Yan 	DDI_HP_NEXDBG((CE_CONT, "ndi_hp_register: dip %p, info_p %p\n",
70*26947304SEvan Yan 	    (void *)dip, (void *)info_p));
71*26947304SEvan Yan 
72*26947304SEvan Yan 	ASSERT(!servicing_interrupt());
73*26947304SEvan Yan 	if (servicing_interrupt())
74*26947304SEvan Yan 		return (NDI_FAILURE);
75*26947304SEvan Yan 
76*26947304SEvan Yan 	/* Validate the arguments */
77*26947304SEvan Yan 	if ((dip == NULL) || (info_p == NULL))
78*26947304SEvan Yan 		return (NDI_EINVAL);
79*26947304SEvan Yan 
80*26947304SEvan Yan 	if (!NEXUS_HAS_HP_OP(dip)) {
81*26947304SEvan Yan 		return (NDI_ENOTSUP);
82*26947304SEvan Yan 	}
83*26947304SEvan Yan 	/* Lock before access */
84*26947304SEvan Yan 	ndi_devi_enter(dip, &count);
85*26947304SEvan Yan 
86*26947304SEvan Yan 	hdlp = ddihp_cn_name_to_handle(dip, info_p->cn_name);
87*26947304SEvan Yan 	if (hdlp) {
88*26947304SEvan Yan 		/* This cn_name is already registered. */
89*26947304SEvan Yan 		ndi_devi_exit(dip, count);
90*26947304SEvan Yan 
91*26947304SEvan Yan 		return (NDI_SUCCESS);
92*26947304SEvan Yan 	}
93*26947304SEvan Yan 	/*
94*26947304SEvan Yan 	 * Create and initialize hotplug Connection handle
95*26947304SEvan Yan 	 */
96*26947304SEvan Yan 	hdlp = (ddi_hp_cn_handle_t *)kmem_zalloc(
97*26947304SEvan Yan 	    (sizeof (ddi_hp_cn_handle_t)), KM_SLEEP);
98*26947304SEvan Yan 
99*26947304SEvan Yan 	/* Copy the Connection information */
100*26947304SEvan Yan 	hdlp->cn_dip = dip;
101*26947304SEvan Yan 	bcopy(info_p, &(hdlp->cn_info), sizeof (*info_p));
102*26947304SEvan Yan 
103*26947304SEvan Yan 	/* Copy cn_name */
104*26947304SEvan Yan 	hdlp->cn_info.cn_name = ddi_strdup(info_p->cn_name, KM_SLEEP);
105*26947304SEvan Yan 
106*26947304SEvan Yan 	if (ddihp_cn_getstate(hdlp) != DDI_SUCCESS) {
107*26947304SEvan Yan 		DDI_HP_NEXDBG((CE_CONT, "ndi_hp_register: dip %p, hdlp %p"
108*26947304SEvan Yan 		    "ddi_cn_getstate failed\n", (void *)dip, (void *)hdlp));
109*26947304SEvan Yan 
110*26947304SEvan Yan 		goto fail;
111*26947304SEvan Yan 	}
112*26947304SEvan Yan 
113*26947304SEvan Yan 	/*
114*26947304SEvan Yan 	 * Append the handle to the list
115*26947304SEvan Yan 	 */
116*26947304SEvan Yan 	DDIHP_LIST_APPEND(ddi_hp_cn_handle_t, (DEVI(dip)->devi_hp_hdlp),
117*26947304SEvan Yan 	    hdlp);
118*26947304SEvan Yan 
119*26947304SEvan Yan 	ndi_devi_exit(dip, count);
120*26947304SEvan Yan 
121*26947304SEvan Yan 	return (NDI_SUCCESS);
122*26947304SEvan Yan 
123*26947304SEvan Yan fail:
124*26947304SEvan Yan 	kmem_free(hdlp->cn_info.cn_name, strlen(hdlp->cn_info.cn_name) + 1);
125*26947304SEvan Yan 	kmem_free(hdlp, sizeof (ddi_hp_cn_handle_t));
126*26947304SEvan Yan 	ndi_devi_exit(dip, count);
127*26947304SEvan Yan 
128*26947304SEvan Yan 	return (NDI_FAILURE);
129*26947304SEvan Yan }
130*26947304SEvan Yan 
131*26947304SEvan Yan /*
132*26947304SEvan Yan  * Unregister a Hotplug Connection (CN)
133*26947304SEvan Yan  */
134*26947304SEvan Yan int
135*26947304SEvan Yan ndi_hp_unregister(dev_info_t *dip, char *cn_name)
136*26947304SEvan Yan {
137*26947304SEvan Yan 	ddi_hp_cn_handle_t	*hdlp;
138*26947304SEvan Yan 	int			count;
139*26947304SEvan Yan 	int			ret;
140*26947304SEvan Yan 
141*26947304SEvan Yan 	DDI_HP_NEXDBG((CE_CONT, "ndi_hp_unregister: dip %p, cn name %s\n",
142*26947304SEvan Yan 	    (void *)dip, cn_name));
143*26947304SEvan Yan 
144*26947304SEvan Yan 	ASSERT(!servicing_interrupt());
145*26947304SEvan Yan 	if (servicing_interrupt())
146*26947304SEvan Yan 		return (NDI_FAILURE);
147*26947304SEvan Yan 
148*26947304SEvan Yan 	/* Validate the arguments */
149*26947304SEvan Yan 	if ((dip == NULL) || (cn_name == NULL))
150*26947304SEvan Yan 		return (NDI_EINVAL);
151*26947304SEvan Yan 
152*26947304SEvan Yan 	ndi_devi_enter(dip, &count);
153*26947304SEvan Yan 
154*26947304SEvan Yan 	hdlp = ddihp_cn_name_to_handle(dip, cn_name);
155*26947304SEvan Yan 	if (hdlp == NULL) {
156*26947304SEvan Yan 		ndi_devi_exit(dip, count);
157*26947304SEvan Yan 		return (NDI_EINVAL);
158*26947304SEvan Yan 	}
159*26947304SEvan Yan 
160*26947304SEvan Yan 	switch (ddihp_cn_unregister(hdlp)) {
161*26947304SEvan Yan 	case DDI_SUCCESS:
162*26947304SEvan Yan 		ret = NDI_SUCCESS;
163*26947304SEvan Yan 		break;
164*26947304SEvan Yan 	case DDI_EINVAL:
165*26947304SEvan Yan 		ret = NDI_EINVAL;
166*26947304SEvan Yan 		break;
167*26947304SEvan Yan 	case DDI_EBUSY:
168*26947304SEvan Yan 		ret = NDI_BUSY;
169*26947304SEvan Yan 		break;
170*26947304SEvan Yan 	default:
171*26947304SEvan Yan 		ret = NDI_FAILURE;
172*26947304SEvan Yan 		break;
173*26947304SEvan Yan 	}
174*26947304SEvan Yan 
175*26947304SEvan Yan 	ndi_devi_exit(dip, count);
176*26947304SEvan Yan 
177*26947304SEvan Yan 	return (ret);
178*26947304SEvan Yan }
179*26947304SEvan Yan 
180*26947304SEvan Yan /*
181*26947304SEvan Yan  * Notify the Hotplug Connection (CN) to change state.
182*26947304SEvan Yan  * Flag:
183*26947304SEvan Yan  *	DDI_HP_REQ_SYNC	    Return after the change is finished.
184*26947304SEvan Yan  *	DDI_HP_REQ_ASYNC    Return after the request is dispatched.
185*26947304SEvan Yan  */
186*26947304SEvan Yan int
187*26947304SEvan Yan ndi_hp_state_change_req(dev_info_t *dip, char *cn_name,
188*26947304SEvan Yan     ddi_hp_cn_state_t state, uint_t flag)
189*26947304SEvan Yan {
190*26947304SEvan Yan 	ddi_hp_cn_async_event_entry_t	*eventp;
191*26947304SEvan Yan 
192*26947304SEvan Yan 	DDI_HP_NEXDBG((CE_CONT, "ndi_hp_state_change_req: dip %p "
193*26947304SEvan Yan 	    "cn_name: %s, state %x, flag %x\n",
194*26947304SEvan Yan 	    (void *)dip, cn_name, state, flag));
195*26947304SEvan Yan 
196*26947304SEvan Yan 	/* Validate the arguments */
197*26947304SEvan Yan 	if (dip == NULL || cn_name == NULL)
198*26947304SEvan Yan 		return (NDI_EINVAL);
199*26947304SEvan Yan 
200*26947304SEvan Yan 	if (!NEXUS_HAS_HP_OP(dip)) {
201*26947304SEvan Yan 		return (NDI_ENOTSUP);
202*26947304SEvan Yan 	}
203*26947304SEvan Yan 	/*
204*26947304SEvan Yan 	 * If the request is to handle the event synchronously, then call
205*26947304SEvan Yan 	 * the event handler without queuing the event.
206*26947304SEvan Yan 	 */
207*26947304SEvan Yan 	if (flag & DDI_HP_REQ_SYNC) {
208*26947304SEvan Yan 		ddi_hp_cn_handle_t	*hdlp;
209*26947304SEvan Yan 		int			count;
210*26947304SEvan Yan 		int			ret;
211*26947304SEvan Yan 
212*26947304SEvan Yan 		ASSERT(!servicing_interrupt());
213*26947304SEvan Yan 		if (servicing_interrupt())
214*26947304SEvan Yan 			return (NDI_FAILURE);
215*26947304SEvan Yan 
216*26947304SEvan Yan 		ndi_devi_enter(dip, &count);
217*26947304SEvan Yan 
218*26947304SEvan Yan 		hdlp = ddihp_cn_name_to_handle(dip, cn_name);
219*26947304SEvan Yan 		if (hdlp == NULL) {
220*26947304SEvan Yan 			ndi_devi_exit(dip, count);
221*26947304SEvan Yan 
222*26947304SEvan Yan 			return (NDI_EINVAL);
223*26947304SEvan Yan 		}
224*26947304SEvan Yan 
225*26947304SEvan Yan 		DDI_HP_NEXDBG((CE_CONT, "ndi_hp_state_change_req: hdlp %p "
226*26947304SEvan Yan 		    "calling ddihp_cn_req_handler() directly to handle "
227*26947304SEvan Yan 		    "target_state %x\n", (void *)hdlp, state));
228*26947304SEvan Yan 
229*26947304SEvan Yan 		ret = ddihp_cn_req_handler(hdlp, state);
230*26947304SEvan Yan 
231*26947304SEvan Yan 		ndi_devi_exit(dip, count);
232*26947304SEvan Yan 
233*26947304SEvan Yan 		return (ret);
234*26947304SEvan Yan 	}
235*26947304SEvan Yan 
236*26947304SEvan Yan 	eventp = kmem_zalloc(sizeof (ddi_hp_cn_async_event_entry_t),
237*26947304SEvan Yan 	    KM_NOSLEEP);
238*26947304SEvan Yan 	if (eventp == NULL)
239*26947304SEvan Yan 		return (NDI_NOMEM);
240*26947304SEvan Yan 
241*26947304SEvan Yan 	eventp->cn_name = ddi_strdup(cn_name, KM_NOSLEEP);
242*26947304SEvan Yan 	if (eventp->cn_name == NULL) {
243*26947304SEvan Yan 		kmem_free(eventp, sizeof (ddi_hp_cn_async_event_entry_t));
244*26947304SEvan Yan 		return (NDI_NOMEM);
245*26947304SEvan Yan 	}
246*26947304SEvan Yan 	eventp->dip = dip;
247*26947304SEvan Yan 	eventp->target_state = state;
248*26947304SEvan Yan 
249*26947304SEvan Yan 	/*
250*26947304SEvan Yan 	 * Hold the parent's ref so that it won't disappear when the taskq is
251*26947304SEvan Yan 	 * scheduled to run.
252*26947304SEvan Yan 	 */
253*26947304SEvan Yan 	ndi_hold_devi(dip);
254*26947304SEvan Yan 
255*26947304SEvan Yan 	if (!taskq_dispatch(system_taskq, ddihp_cn_run_event, eventp,
256*26947304SEvan Yan 	    TQ_NOSLEEP)) {
257*26947304SEvan Yan 		ndi_rele_devi(dip);
258*26947304SEvan Yan 		DDI_HP_NEXDBG((CE_CONT, "ndi_hp_state_change_req: "
259*26947304SEvan Yan 		    "taskq_dispatch failed! dip %p "
260*26947304SEvan Yan 		    "target_state %x\n", (void *)dip, state));
261*26947304SEvan Yan 		return (NDI_NOMEM);
262*26947304SEvan Yan 	}
263*26947304SEvan Yan 
264*26947304SEvan Yan 	return (NDI_CLAIMED);
265*26947304SEvan Yan }
266*26947304SEvan Yan 
267*26947304SEvan Yan /*
268*26947304SEvan Yan  * Walk the link of Hotplug Connection handles of a dip:
269*26947304SEvan Yan  *	DEVI(dip)->devi_hp_hdlp->[link of connections]
270*26947304SEvan Yan  */
271*26947304SEvan Yan void
272*26947304SEvan Yan ndi_hp_walk_cn(dev_info_t *dip, int (*f)(ddi_hp_cn_info_t *,
273*26947304SEvan Yan     void *), void *arg)
274*26947304SEvan Yan {
275*26947304SEvan Yan 	int			count;
276*26947304SEvan Yan 	ddi_hp_cn_handle_t	*head, *curr, *prev;
277*26947304SEvan Yan 
278*26947304SEvan Yan 	DDI_HP_NEXDBG((CE_CONT, "ndi_hp_walk_cn: dip %p arg %p\n",
279*26947304SEvan Yan 	    (void *)dip, arg));
280*26947304SEvan Yan 
281*26947304SEvan Yan 	ASSERT(!servicing_interrupt());
282*26947304SEvan Yan 	if (servicing_interrupt())
283*26947304SEvan Yan 		return;
284*26947304SEvan Yan 
285*26947304SEvan Yan 	/* Validate the arguments */
286*26947304SEvan Yan 	if (dip == NULL)
287*26947304SEvan Yan 		return;
288*26947304SEvan Yan 
289*26947304SEvan Yan 	ndi_devi_enter(dip, &count);
290*26947304SEvan Yan 
291*26947304SEvan Yan 	head = DEVI(dip)->devi_hp_hdlp;
292*26947304SEvan Yan 	curr = head;
293*26947304SEvan Yan 	prev = NULL;
294*26947304SEvan Yan 	while (curr != NULL) {
295*26947304SEvan Yan 		DDI_HP_NEXDBG((CE_CONT, "ndi_hp_walk_cn: dip %p "
296*26947304SEvan Yan 		    "current cn_name: %s\n",
297*26947304SEvan Yan 		    (void *)dip, curr->cn_info.cn_name));
298*26947304SEvan Yan 		switch ((*f)(&(curr->cn_info), arg)) {
299*26947304SEvan Yan 		case DDI_WALK_TERMINATE:
300*26947304SEvan Yan 			ndi_devi_exit(dip, count);
301*26947304SEvan Yan 
302*26947304SEvan Yan 			return;
303*26947304SEvan Yan 		case DDI_WALK_CONTINUE:
304*26947304SEvan Yan 		default:
305*26947304SEvan Yan 			if (DEVI(dip)->devi_hp_hdlp != head) {
306*26947304SEvan Yan 				/*
307*26947304SEvan Yan 				 * The current node is head and it is removed
308*26947304SEvan Yan 				 * by last call to (*f)()
309*26947304SEvan Yan 				 */
310*26947304SEvan Yan 				head = DEVI(dip)->devi_hp_hdlp;
311*26947304SEvan Yan 				curr = head;
312*26947304SEvan Yan 				prev = NULL;
313*26947304SEvan Yan 			} else if (prev && prev->next != curr) {
314*26947304SEvan Yan 				/*
315*26947304SEvan Yan 				 * The current node is a middle node or tail
316*26947304SEvan Yan 				 * node and it is removed by last call to
317*26947304SEvan Yan 				 * (*f)()
318*26947304SEvan Yan 				 */
319*26947304SEvan Yan 				curr = prev->next;
320*26947304SEvan Yan 			} else {
321*26947304SEvan Yan 				/* no removal accurred on curr node */
322*26947304SEvan Yan 				prev = curr;
323*26947304SEvan Yan 				curr = curr->next;
324*26947304SEvan Yan 			}
325*26947304SEvan Yan 		}
326*26947304SEvan Yan 	}
327*26947304SEvan Yan 	ndi_devi_exit(dip, count);
328*26947304SEvan Yan }
329*26947304SEvan Yan 
330*26947304SEvan Yan /*
331*26947304SEvan Yan  * Local functions (called within this file)
332*26947304SEvan Yan  */
333*26947304SEvan Yan 
334*26947304SEvan Yan /*
335*26947304SEvan Yan  * Wrapper function for ddihp_cn_req_handler() called from taskq
336*26947304SEvan Yan  */
337*26947304SEvan Yan static void
338*26947304SEvan Yan ddihp_cn_run_event(void *arg)
339*26947304SEvan Yan {
340*26947304SEvan Yan 	ddi_hp_cn_async_event_entry_t	*eventp =
341*26947304SEvan Yan 	    (ddi_hp_cn_async_event_entry_t *)arg;
342*26947304SEvan Yan 	dev_info_t			*dip = eventp->dip;
343*26947304SEvan Yan 	ddi_hp_cn_handle_t		*hdlp;
344*26947304SEvan Yan 	int				count;
345*26947304SEvan Yan 
346*26947304SEvan Yan 	/* Lock before access */
347*26947304SEvan Yan 	ndi_devi_enter(dip, &count);
348*26947304SEvan Yan 
349*26947304SEvan Yan 	hdlp = ddihp_cn_name_to_handle(dip, eventp->cn_name);
350*26947304SEvan Yan 	if (hdlp) {
351*26947304SEvan Yan 		(void) ddihp_cn_req_handler(hdlp, eventp->target_state);
352*26947304SEvan Yan 	} else {
353*26947304SEvan Yan 		DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_run_event: no handle for "
354*26947304SEvan Yan 		    "cn_name: %s dip %p. Request for target_state %x is"
355*26947304SEvan Yan 		    " dropped. \n",
356*26947304SEvan Yan 		    eventp->cn_name, (void *)dip, eventp->target_state));
357*26947304SEvan Yan 	}
358*26947304SEvan Yan 
359*26947304SEvan Yan 	ndi_devi_exit(dip, count);
360*26947304SEvan Yan 
361*26947304SEvan Yan 	/* Release the devi's ref that is held from interrupt context. */
362*26947304SEvan Yan 	ndi_rele_devi((dev_info_t *)DEVI(dip));
363*26947304SEvan Yan 	kmem_free(eventp->cn_name, strlen(eventp->cn_name) + 1);
364*26947304SEvan Yan 	kmem_free(eventp, sizeof (ddi_hp_cn_async_event_entry_t));
365*26947304SEvan Yan }
366*26947304SEvan Yan 
367*26947304SEvan Yan /*
368*26947304SEvan Yan  * Handle state change request of a Hotplug Connection (CN)
369*26947304SEvan Yan  */
370*26947304SEvan Yan static int
371*26947304SEvan Yan ddihp_cn_req_handler(ddi_hp_cn_handle_t *hdlp,
372*26947304SEvan Yan     ddi_hp_cn_state_t target_state)
373*26947304SEvan Yan {
374*26947304SEvan Yan 	dev_info_t	*dip = hdlp->cn_dip;
375*26947304SEvan Yan 	int		ret = DDI_SUCCESS;
376*26947304SEvan Yan 
377*26947304SEvan Yan 	DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_req_handler:"
378*26947304SEvan Yan 	    " hdlp %p, target_state %x\n",
379*26947304SEvan Yan 	    (void *)hdlp, target_state));
380*26947304SEvan Yan 
381*26947304SEvan Yan 	ASSERT(DEVI_BUSY_OWNED(dip));
382*26947304SEvan Yan 
383*26947304SEvan Yan 	if (ddihp_cn_getstate(hdlp) != DDI_SUCCESS) {
384*26947304SEvan Yan 		DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_req_handler: dip %p, "
385*26947304SEvan Yan 		    "hdlp %p ddi_cn_getstate failed\n", (void *)dip,
386*26947304SEvan Yan 		    (void *)hdlp));
387*26947304SEvan Yan 
388*26947304SEvan Yan 		return (NDI_UNCLAIMED);
389*26947304SEvan Yan 	}
390*26947304SEvan Yan 	if (hdlp->cn_info.cn_state != target_state) {
391*26947304SEvan Yan 		ddi_hp_cn_state_t result_state = 0;
392*26947304SEvan Yan 
393*26947304SEvan Yan 		DDIHP_CN_OPS(hdlp, DDI_HPOP_CN_CHANGE_STATE,
394*26947304SEvan Yan 		    (void *)&target_state, (void *)&result_state, ret);
395*26947304SEvan Yan 
396*26947304SEvan Yan 		DDI_HP_NEXDBG((CE_CONT, "ddihp_cn_req_handler: dip %p, "
397*26947304SEvan Yan 		    "hdlp %p changed state to %x, ret=%x\n",
398*26947304SEvan Yan 		    (void *)dip, (void *)hdlp, result_state, ret));
399*26947304SEvan Yan 	}
400*26947304SEvan Yan 
401*26947304SEvan Yan 	if (ret == DDI_SUCCESS)
402*26947304SEvan Yan 		return (NDI_CLAIMED);
403*26947304SEvan Yan 	else
404*26947304SEvan Yan 		return (NDI_UNCLAIMED);
405*26947304SEvan Yan }
406