xref: /titanic_51/usr/src/uts/common/io/usb/usba/hcdi.c (revision c090e5dfb10cc96e71e6b0f55bf98c18027b002c)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 /*
22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 /*
27  * USBA: Solaris USB Architecture support
28  *
29  * hcdi.c contains the code for client driver callbacks.  A host controller
30  * driver registers/unregisters with usba through usba_hcdi_register/unregister.
31  *
32  * When the transfer has finished, the host controller driver will call into
33  * usba with the result.  The call is usba_hcdi_cb().
34  *
35  * The callback queue is maintained in FIFO order.  usba_hcdi_cb
36  * adds to the queue, and hcdi_cb_thread takes the callbacks off the queue
37  * and executes them.
38  */
39 #define	USBA_FRAMEWORK
40 #include <sys/usb/usba/usba_impl.h>
41 #include <sys/usb/usba/hcdi_impl.h>
42 #include <sys/kstat.h>
43 #include <sys/ddi_impldefs.h>
44 
45 /* function prototypes, XXXX use hcdi_ prefix?	*/
46 static void usba_hcdi_create_stats(usba_hcdi_t *, int);
47 static void usba_hcdi_update_error_stats(usba_hcdi_t *, usb_cr_t);
48 static void usba_hcdi_destroy_stats(usba_hcdi_t *);
49 
50 /* internal functions */
51 static uint_t hcdi_soft_intr(caddr_t arg1, caddr_t arg2);
52 
53 static void hcdi_cb_thread(void *);
54 static void hcdi_shared_cb_thread(void *);
55 static void hcdi_do_cb(usba_pipe_handle_data_t *, usba_req_wrapper_t *,
56 							usba_hcdi_t *);
57 static void hcdi_autoclearing(usba_req_wrapper_t *);
58 
59 /* private function from USBAI */
60 void	usba_pipe_clear(usb_pipe_handle_t);
61 
62 /* for debug messages */
63 uint_t	hcdi_errmask	= (uint_t)DPRINT_MASK_ALL;
64 uint_t	hcdi_errlevel	= USB_LOG_L4;
65 uint_t	hcdi_instance_debug = (uint_t)-1;
66 
67 void
68 usba_hcdi_initialization()
69 {
70 }
71 
72 
73 void
74 usba_hcdi_destroy()
75 {
76 }
77 
78 
79 /*
80  * store hcdi structure in the dip
81  */
82 void
83 usba_hcdi_set_hcdi(dev_info_t *dip, usba_hcdi_t *hcdi)
84 {
85 	ddi_set_driver_private(dip, hcdi);
86 }
87 
88 
89 /*
90  * retrieve hcdi structure from the dip
91  */
92 usba_hcdi_t *
93 usba_hcdi_get_hcdi(dev_info_t *dip)
94 {
95 	return (ddi_get_driver_private(dip));
96 }
97 
98 /*
99  * Called by an	HCD to attach an instance of the driver
100  *	make this instance known to USBA
101  *	the HCD	should initialize usba_hcdi structure prior
102  *	to calling this	interface
103  */
104 int
105 usba_hcdi_register(usba_hcdi_register_args_t *args, uint_t flags)
106 {
107 	char		*datap;
108 	uint_t		soft_prip;
109 	usba_hcdi_t	*hcdi = kmem_zalloc(sizeof (usba_hcdi_t), KM_SLEEP);
110 
111 	if (args->usba_hcdi_register_version != HCDI_REGISTER_VERS_0) {
112 		kmem_free(hcdi, sizeof (usba_hcdi_t));
113 
114 		return (USB_FAILURE);
115 	}
116 
117 	hcdi->hcdi_dip = args->usba_hcdi_register_dip;
118 
119 	/*
120 	 * Create a log_handle
121 	 */
122 	hcdi->hcdi_log_handle = usb_alloc_log_hdl(hcdi->hcdi_dip, NULL,
123 	    &hcdi_errlevel, &hcdi_errmask, &hcdi_instance_debug,
124 	    0);
125 
126 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
127 	    "usba_hcdi_register: %s", ddi_node_name(hcdi->hcdi_dip));
128 
129 	/*
130 	 * Initialize the mutex.  Use the iblock cookie passed in
131 	 * by the host controller driver.
132 	 */
133 	mutex_init(&hcdi->hcdi_mutex, NULL, MUTEX_DRIVER,
134 	    args->usba_hcdi_register_iblock_cookie);
135 
136 	/* add soft interrupt */
137 	if (ddi_intr_add_softint(hcdi->hcdi_dip, &hcdi->hcdi_softint_hdl,
138 	    DDI_INTR_SOFTPRI_MAX, hcdi_soft_intr, (caddr_t)hcdi) !=
139 	    DDI_SUCCESS) {
140 		USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
141 		    "usba_hcd_register: add soft interrupt failed");
142 		mutex_destroy(&hcdi->hcdi_mutex);
143 		usb_free_log_hdl(hcdi->hcdi_log_handle);
144 		kmem_free(hcdi, sizeof (usba_hcdi_t));
145 
146 		return (USB_FAILURE);
147 	}
148 
149 	if (ddi_intr_get_softint_pri(hcdi->hcdi_softint_hdl, &soft_prip) !=
150 	    DDI_SUCCESS) {
151 		USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
152 		    "usba_hcd_register: get soft interrupt priority failed");
153 		(void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl);
154 		mutex_destroy(&hcdi->hcdi_mutex);
155 		usb_free_log_hdl(hcdi->hcdi_log_handle);
156 		kmem_free(hcdi, sizeof (usba_hcdi_t));
157 
158 		return (USB_FAILURE);
159 	}
160 
161 	/*
162 	 * Priority and iblock_cookie are one and the same
163 	 * (However, retaining hcdi_soft_iblock_cookie for now
164 	 * assigning it w/ priority. In future all iblock_cookie
165 	 * could just go)
166 	 */
167 	hcdi->hcdi_soft_iblock_cookie =
168 	    (ddi_iblock_cookie_t)(uintptr_t)soft_prip;
169 
170 	usba_init_list(&hcdi->hcdi_cb_queue, NULL, NULL);
171 
172 	hcdi->hcdi_dma_attr	= args->usba_hcdi_register_dma_attr;
173 	hcdi->hcdi_flags	= flags;
174 	hcdi->hcdi_ops		= args->usba_hcdi_register_ops;
175 	hcdi->hcdi_iblock_cookie = args->usba_hcdi_register_iblock_cookie;
176 	usba_hcdi_create_stats(hcdi, ddi_get_instance(hcdi->hcdi_dip));
177 
178 	hcdi->hcdi_min_xfer	= hcdi->hcdi_dma_attr->dma_attr_minxfer;
179 	hcdi->hcdi_min_burst_size =
180 	    (1<<(ddi_ffs(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1));
181 	hcdi->hcdi_max_burst_size =
182 	    (1<<(ddi_fls(hcdi->hcdi_dma_attr->dma_attr_burstsizes)-1));
183 
184 	usba_hcdi_set_hcdi(hcdi->hcdi_dip, hcdi);
185 
186 	if (ddi_prop_lookup_string(DDI_DEV_T_ANY,
187 	    hcdi->hcdi_dip,
188 	    DDI_PROP_DONTPASS, "ugen-default-binding", &datap) ==
189 	    DDI_PROP_SUCCESS) {
190 		if (strcmp(datap, "device") == 0) {
191 			hcdi->hcdi_ugen_default_binding =
192 			    USBA_UGEN_DEVICE_BINDING;
193 		} else if (strcmp(datap, "interface") == 0) {
194 			hcdi->hcdi_ugen_default_binding =
195 			    USBA_UGEN_INTERFACE_BINDING;
196 		} else if (strcmp(datap, "interface-association") == 0) {
197 			hcdi->hcdi_ugen_default_binding =
198 			    USBA_UGEN_INTERFACE_ASSOCIATION_BINDING;
199 		} else {
200 			USB_DPRINTF_L2(DPRINT_MASK_HCDI,
201 			    hcdi->hcdi_log_handle,
202 			    "illegal value (%s) for "
203 			    "ugen_default_binding property",
204 			    datap);
205 		}
206 		ddi_prop_free(datap);
207 	}
208 
209 	return (USB_SUCCESS);
210 }
211 
212 
213 /*
214  * Called by an	HCD to detach an instance of the driver
215  */
216 /*ARGSUSED*/
217 void
218 usba_hcdi_unregister(dev_info_t *dip)
219 {
220 	usba_hcdi_t *hcdi = usba_hcdi_get_hcdi(dip);
221 
222 	if (hcdi) {
223 		USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
224 		    "usba_hcdi_unregister: %s", ddi_node_name(dip));
225 
226 		usba_hcdi_set_hcdi(dip, NULL);
227 
228 		mutex_destroy(&hcdi->hcdi_mutex);
229 		usba_hcdi_destroy_stats(hcdi);
230 		usb_free_log_hdl(hcdi->hcdi_log_handle);
231 
232 		/* Destroy the soft interrupt */
233 		(void) ddi_intr_remove_softint(hcdi->hcdi_softint_hdl);
234 		kmem_free(hcdi, sizeof (usba_hcdi_t));
235 	}
236 }
237 
238 
239 /*
240  * alloc usba_hcdi_ops structure
241  *	called from the HCD attach routine
242  */
243 usba_hcdi_ops_t *
244 usba_alloc_hcdi_ops()
245 {
246 	usba_hcdi_ops_t	*usba_hcdi_ops;
247 
248 	usba_hcdi_ops = kmem_zalloc(sizeof (usba_hcdi_ops_t), KM_SLEEP);
249 
250 	return (usba_hcdi_ops);
251 }
252 
253 
254 /*
255  * dealloc usba_hcdi_ops structure
256  */
257 void
258 usba_free_hcdi_ops(usba_hcdi_ops_t *hcdi_ops)
259 {
260 	if (hcdi_ops) {
261 		kmem_free(hcdi_ops, sizeof (usba_hcdi_ops_t));
262 	}
263 }
264 
265 
266 /*
267  * Allocate the hotplug kstats structure
268  */
269 void
270 usba_hcdi_create_stats(usba_hcdi_t *hcdi, int instance)
271 {
272 	char			kstatname[KSTAT_STRLEN];
273 	const char		*dname = ddi_driver_name(hcdi->hcdi_dip);
274 	hcdi_hotplug_stats_t	*hsp;
275 	hcdi_error_stats_t	*esp;
276 
277 	if (HCDI_HOTPLUG_STATS(hcdi) == NULL) {
278 		(void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,hotplug",
279 		    dname, instance);
280 		HCDI_HOTPLUG_STATS(hcdi) = kstat_create("usba", instance,
281 		    kstatname, "usb_hotplug", KSTAT_TYPE_NAMED,
282 		    sizeof (hcdi_hotplug_stats_t) / sizeof (kstat_named_t),
283 		    KSTAT_FLAG_PERSISTENT);
284 
285 		if (HCDI_HOTPLUG_STATS(hcdi) == NULL) {
286 
287 			return;
288 		}
289 
290 		hsp = HCDI_HOTPLUG_STATS_DATA(hcdi);
291 		kstat_named_init(&hsp->hcdi_hotplug_total_success,
292 		    "Total Hotplug Successes", KSTAT_DATA_UINT64);
293 		kstat_named_init(&hsp->hcdi_hotplug_success,
294 		    "Hotplug Successes", KSTAT_DATA_UINT64);
295 		kstat_named_init(&hsp->hcdi_hotplug_total_failure,
296 		    "Hotplug Total Failures", KSTAT_DATA_UINT64);
297 		kstat_named_init(&hsp->hcdi_hotplug_failure,
298 		    "Hotplug Failures", KSTAT_DATA_UINT64);
299 		kstat_named_init(&hsp->hcdi_device_count,
300 		    "Device Count", KSTAT_DATA_UINT64);
301 
302 		HCDI_HOTPLUG_STATS(hcdi)->ks_private = hcdi;
303 		HCDI_HOTPLUG_STATS(hcdi)->ks_update = nulldev;
304 		kstat_install(HCDI_HOTPLUG_STATS(hcdi));
305 	}
306 
307 	if (HCDI_ERROR_STATS(hcdi) == NULL) {
308 		(void) snprintf(kstatname, KSTAT_STRLEN, "%s%d,error",
309 		    dname, instance);
310 		HCDI_ERROR_STATS(hcdi) = kstat_create("usba", instance,
311 		    kstatname, "usb_errors", KSTAT_TYPE_NAMED,
312 		    sizeof (hcdi_error_stats_t) / sizeof (kstat_named_t),
313 		    KSTAT_FLAG_PERSISTENT);
314 
315 		if (HCDI_ERROR_STATS(hcdi) == NULL) {
316 
317 			return;
318 		}
319 
320 		esp = HCDI_ERROR_STATS_DATA(hcdi);
321 		kstat_named_init(&esp->cc_crc, "CRC Errors", KSTAT_DATA_UINT64);
322 		kstat_named_init(&esp->cc_bitstuffing,
323 		    "Bit Stuffing Violations", KSTAT_DATA_UINT64);
324 		kstat_named_init(&esp->cc_data_toggle_mm,
325 		    "Data Toggle PID Errors", KSTAT_DATA_UINT64);
326 		kstat_named_init(&esp->cc_stall,
327 		    "Endpoint Stalls", KSTAT_DATA_UINT64);
328 		kstat_named_init(&esp->cc_dev_not_resp,
329 		    "Device Not Responding", KSTAT_DATA_UINT64);
330 		kstat_named_init(&esp->cc_pid_checkfailure,
331 		    "PID Check Bit Errors", KSTAT_DATA_UINT64);
332 		kstat_named_init(&esp->cc_unexp_pid,
333 		    "Invalid PID Errors", KSTAT_DATA_UINT64);
334 		kstat_named_init(&esp->cc_data_overrun,
335 		    "Data Overruns", KSTAT_DATA_UINT64);
336 		kstat_named_init(&esp->cc_data_underrun,
337 		    "Data Underruns", KSTAT_DATA_UINT64);
338 		kstat_named_init(&esp->cc_buffer_overrun,
339 		    "Buffer Overruns", KSTAT_DATA_UINT64);
340 		kstat_named_init(&esp->cc_buffer_underrun,
341 		    "Buffer Underruns", KSTAT_DATA_UINT64);
342 		kstat_named_init(&esp->cc_timeout,
343 		    "Command Timed Out", KSTAT_DATA_UINT64);
344 		kstat_named_init(&esp->cc_not_accessed,
345 		    "Not Accessed By Hardware", KSTAT_DATA_UINT64);
346 		kstat_named_init(&esp->cc_unspecified_err,
347 		    "Unspecified Error", KSTAT_DATA_UINT64);
348 #ifdef	NOTYETNEEDED
349 		kstat_named_init(&esp->hcdi_usb_failure,
350 		    "USB Failure", KSTAT_DATA_UINT64);
351 		kstat_named_init(&esp->hcdi_usb_no_resources,
352 		    "No Resources", KSTAT_DATA_UINT64);
353 		kstat_named_init(&esp->hcdi_usb_no_bandwidth,
354 		    "No Bandwidth", KSTAT_DATA_UINT64);
355 		kstat_named_init(&esp->hcdi_usb_pipe_reserved,
356 		    "Pipe Reserved", KSTAT_DATA_UINT64);
357 		kstat_named_init(&esp->hcdi_usb_pipe_unshareable,
358 		    "Pipe Unshareable", KSTAT_DATA_UINT64);
359 		kstat_named_init(&esp->hcdi_usb_not_supported,
360 		    "Function Not Supported", KSTAT_DATA_UINT64);
361 		kstat_named_init(&esp->hcdi_usb_pipe_error,
362 		    "Pipe Error", KSTAT_DATA_UINT64);
363 		kstat_named_init(&esp->hcdi_usb_pipe_busy,
364 		    "Pipe Busy", KSTAT_DATA_UINT64);
365 #endif
366 
367 		HCDI_ERROR_STATS(hcdi)->ks_private = hcdi;
368 		HCDI_ERROR_STATS(hcdi)->ks_update = nulldev;
369 		kstat_install(HCDI_ERROR_STATS(hcdi));
370 	}
371 }
372 
373 
374 /*
375  * Do actual error stats
376  */
377 void
378 usba_hcdi_update_error_stats(usba_hcdi_t *hcdi, usb_cr_t completion_reason)
379 {
380 	if (HCDI_ERROR_STATS(hcdi) == NULL) {
381 
382 		return;
383 	}
384 
385 	switch (completion_reason) {
386 	case USB_CR_OK:
387 		break;
388 	case USB_CR_CRC:
389 		HCDI_ERROR_STATS_DATA(hcdi)->cc_crc.value.ui64++;
390 		break;
391 	case USB_CR_BITSTUFFING:
392 		HCDI_ERROR_STATS_DATA(hcdi)->cc_bitstuffing.value.ui64++;
393 		break;
394 	case USB_CR_DATA_TOGGLE_MM:
395 		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_toggle_mm.value.ui64++;
396 		break;
397 	case USB_CR_STALL:
398 		HCDI_ERROR_STATS_DATA(hcdi)->cc_stall.value.ui64++;
399 		break;
400 	case USB_CR_DEV_NOT_RESP:
401 		HCDI_ERROR_STATS_DATA(hcdi)->cc_dev_not_resp.value.ui64++;
402 		break;
403 	case USB_CR_PID_CHECKFAILURE:
404 		HCDI_ERROR_STATS_DATA(hcdi)->cc_pid_checkfailure.value.ui64++;
405 		break;
406 	case USB_CR_UNEXP_PID:
407 		HCDI_ERROR_STATS_DATA(hcdi)->cc_unexp_pid.value.ui64++;
408 		break;
409 	case USB_CR_DATA_OVERRUN:
410 		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_overrun.value.ui64++;
411 		break;
412 	case USB_CR_DATA_UNDERRUN:
413 		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_underrun.value.ui64++;
414 		break;
415 	case USB_CR_BUFFER_OVERRUN:
416 		HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_overrun.value.ui64++;
417 		break;
418 	case USB_CR_BUFFER_UNDERRUN:
419 		HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_underrun.value.ui64++;
420 		break;
421 	case USB_CR_TIMEOUT:
422 		HCDI_ERROR_STATS_DATA(hcdi)->cc_timeout.value.ui64++;
423 		break;
424 	case USB_CR_NOT_ACCESSED:
425 		HCDI_ERROR_STATS_DATA(hcdi)->cc_not_accessed.value.ui64++;
426 		break;
427 	case USB_CR_NO_RESOURCES:
428 		HCDI_ERROR_STATS_DATA(hcdi)->cc_no_resources.value.ui64++;
429 		break;
430 	case USB_CR_UNSPECIFIED_ERR:
431 		HCDI_ERROR_STATS_DATA(hcdi)->cc_unspecified_err.value.ui64++;
432 		break;
433 	case USB_CR_STOPPED_POLLING:
434 		HCDI_ERROR_STATS_DATA(hcdi)->cc_stopped_polling.value.ui64++;
435 		break;
436 	case USB_CR_PIPE_CLOSING:
437 		HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_closing.value.ui64++;
438 		break;
439 	case USB_CR_PIPE_RESET:
440 		HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_reset.value.ui64++;
441 		break;
442 	case USB_CR_NOT_SUPPORTED:
443 		HCDI_ERROR_STATS_DATA(hcdi)->cc_not_supported.value.ui64++;
444 		break;
445 	case USB_CR_FLUSHED:
446 		HCDI_ERROR_STATS_DATA(hcdi)->cc_flushed.value.ui64++;
447 		break;
448 	default:
449 		break;
450 	}
451 }
452 
453 
454 /*
455  * Destroy the hotplug kstats structure
456  */
457 static void
458 usba_hcdi_destroy_stats(usba_hcdi_t *hcdi)
459 {
460 	if (HCDI_HOTPLUG_STATS(hcdi)) {
461 		kstat_delete(HCDI_HOTPLUG_STATS(hcdi));
462 		HCDI_HOTPLUG_STATS(hcdi) = NULL;
463 	}
464 
465 	if (HCDI_ERROR_STATS(hcdi)) {
466 		kstat_delete(HCDI_ERROR_STATS(hcdi));
467 		HCDI_ERROR_STATS(hcdi) = NULL;
468 	}
469 }
470 
471 
472 /*
473  * HCD callback handling
474  */
475 void
476 usba_hcdi_cb(usba_pipe_handle_data_t *ph_data,
477 	usb_opaque_t	req,
478 	usb_cr_t	completion_reason)
479 {
480 
481 	usba_device_t		*usba_device = ph_data->p_usba_device;
482 	usba_hcdi_t		*hcdi =	usba_hcdi_get_hcdi(
483 	    usba_device->usb_root_hub_dip);
484 	usba_req_wrapper_t	*req_wrp = USBA_REQ2WRP(req);
485 	usb_ep_descr_t		*eptd = &ph_data->p_ep;
486 
487 	mutex_enter(&ph_data->p_mutex);
488 
489 #ifdef DEBUG
490 	mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
491 
492 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
493 	    "usba_hcdi_cb: "
494 	    "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d",
495 	    (void *)ph_data, (void *)req, ph_data->p_ph_impl->usba_ph_state,
496 	    ph_data->p_ph_impl->usba_ph_ref_count, ph_data->p_req_count,
497 	    completion_reason);
498 
499 	mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
500 #endif
501 
502 	/* Set the completion reason */
503 	switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
504 	case USB_EP_ATTR_CONTROL:
505 		((usb_ctrl_req_t *)req)->
506 		    ctrl_completion_reason = completion_reason;
507 		break;
508 	case USB_EP_ATTR_BULK:
509 		((usb_bulk_req_t *)req)->
510 		    bulk_completion_reason = completion_reason;
511 		break;
512 	case USB_EP_ATTR_INTR:
513 		((usb_intr_req_t *)req)->
514 		    intr_completion_reason = completion_reason;
515 		break;
516 	case USB_EP_ATTR_ISOCH:
517 		((usb_isoc_req_t *)req)->
518 		    isoc_completion_reason = completion_reason;
519 		break;
520 	}
521 
522 	/*
523 	 * exception callbacks will still go thru a taskq thread
524 	 * but should occur after the soft interrupt callback
525 	 * By design of periodic pipes, polling will stop on any
526 	 * exception
527 	 */
528 	if ((ph_data->p_spec_flag & USBA_PH_FLAG_USE_SOFT_INTR) &&
529 	    (completion_reason == USB_CR_OK)) {
530 		ph_data->p_soft_intr++;
531 		mutex_exit(&ph_data->p_mutex);
532 
533 		usba_add_to_list(&hcdi->hcdi_cb_queue, &req_wrp->wr_queue);
534 
535 		if (ddi_intr_trigger_softint(hcdi->hcdi_softint_hdl, NULL) !=
536 		    DDI_SUCCESS)
537 			USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
538 			    "usba_hcdi_cb: ddi_intr_trigger_softint  failed");
539 
540 		return;
541 	}
542 
543 	/*
544 	 * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests,
545 	 * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch,
546 	 * so there are no conflicts.
547 	 */
548 	if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
549 		int iface;
550 
551 		mutex_exit(&ph_data->p_mutex);
552 		iface = usb_get_if_number(ph_data->p_dip);
553 		if (iface < 0) {
554 			/* we own the device, use the first taskq */
555 			iface = 0;
556 		}
557 		if (taskq_dispatch(usba_device->usb_shared_taskq[iface],
558 		    hcdi_shared_cb_thread, req_wrp, TQ_NOSLEEP) ==
559 		    NULL) {
560 			usba_req_exc_cb(req_wrp,
561 			    USB_CR_NO_RESOURCES, USB_CB_ASYNC_REQ_FAILED);
562 		}
563 
564 		return;
565 	}
566 
567 	/* Add the callback to the pipehandles callback list */
568 	usba_add_to_list(&ph_data->p_cb_queue, &req_wrp->wr_queue);
569 
570 	/* only dispatch if there is no thread running */
571 	if (ph_data->p_thread_id == 0) {
572 		if (usba_async_ph_req(ph_data, hcdi_cb_thread,
573 		    ph_data, USB_FLAGS_NOSLEEP) != USB_SUCCESS) {
574 			USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
575 			    "usba_hcdi_cb: taskq_dispatch failed");
576 			if (usba_rm_from_list(&ph_data->p_cb_queue,
577 			    &req_wrp->wr_queue) == USB_SUCCESS) {
578 				mutex_exit(&ph_data->p_mutex);
579 				usba_req_exc_cb(req_wrp,
580 				    USB_CR_NO_RESOURCES,
581 				    USB_CB_ASYNC_REQ_FAILED);
582 
583 				return;
584 			}
585 		} else {
586 			ph_data->p_thread_id = (kthread_t *)1;
587 		}
588 	}
589 	mutex_exit(&ph_data->p_mutex);
590 }
591 
592 
593 /*
594  * thread to perform the callbacks
595  */
596 static void
597 hcdi_cb_thread(void *arg)
598 {
599 	usba_pipe_handle_data_t	*ph_data =
600 	    (usba_pipe_handle_data_t *)arg;
601 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
602 	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(ph_data->
603 	    p_usba_device->usb_root_hub_dip);
604 	usba_req_wrapper_t	*req_wrp;
605 
606 	mutex_enter(&ph_data->p_mutex);
607 	ASSERT(ph_data->p_thread_id == (kthread_t *)1);
608 	ph_data->p_thread_id = curthread;
609 
610 	/*
611 	 * hold the ph_data. we can't use usba_hold_ph_data() since
612 	 * it will return NULL if we are closing the pipe which would
613 	 * then leave all requests stuck in the cb_queue
614 	 */
615 	mutex_enter(&ph_impl->usba_ph_mutex);
616 	ph_impl->usba_ph_ref_count++;
617 
618 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
619 	    "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data,
620 	    ph_impl->usba_ph_ref_count);
621 
622 	mutex_exit(&ph_impl->usba_ph_mutex);
623 
624 	/*
625 	 * wait till soft interrupt callbacks are taken care of
626 	 */
627 	while (ph_data->p_soft_intr) {
628 		mutex_exit(&ph_data->p_mutex);
629 		delay(1);
630 		mutex_enter(&ph_data->p_mutex);
631 	}
632 
633 	while ((req_wrp = (usba_req_wrapper_t *)
634 	    usba_rm_first_pvt_from_list(&ph_data->p_cb_queue)) != NULL) {
635 		hcdi_do_cb(ph_data, req_wrp, hcdi);
636 	}
637 
638 	ph_data->p_thread_id = 0;
639 	mutex_exit(&ph_data->p_mutex);
640 
641 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
642 	    "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
643 
644 	usba_release_ph_data(ph_impl);
645 }
646 
647 
648 static void
649 hcdi_do_cb(usba_pipe_handle_data_t *ph_data, usba_req_wrapper_t *req_wrp,
650     usba_hcdi_t *hcdi)
651 {
652 	usb_cr_t		completion_reason;
653 	usb_req_attrs_t		attrs = req_wrp->wr_attrs;
654 
655 	switch (req_wrp->wr_ph_data->p_ep.bmAttributes &
656 	    USB_EP_ATTR_MASK) {
657 	case USB_EP_ATTR_CONTROL:
658 		completion_reason =
659 		    USBA_WRP2CTRL_REQ(req_wrp)->ctrl_completion_reason;
660 		break;
661 	case USB_EP_ATTR_INTR:
662 		completion_reason =
663 		    USBA_WRP2INTR_REQ(req_wrp)->intr_completion_reason;
664 		break;
665 	case USB_EP_ATTR_BULK:
666 		completion_reason =
667 		    USBA_WRP2BULK_REQ(req_wrp)->bulk_completion_reason;
668 		break;
669 	case USB_EP_ATTR_ISOCH:
670 		completion_reason =
671 		    USBA_WRP2ISOC_REQ(req_wrp)->isoc_completion_reason;
672 		break;
673 	}
674 	req_wrp->wr_cr = completion_reason;
675 
676 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
677 	    "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp, completion_reason);
678 
679 	/*
680 	 * Normal callbacks:
681 	 */
682 	if (completion_reason == USB_CR_OK) {
683 		mutex_exit(&ph_data->p_mutex);
684 		usba_req_normal_cb(req_wrp);
685 		mutex_enter(&ph_data->p_mutex);
686 	} else {
687 		usb_pipe_state_t pipe_state;
688 
689 		USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
690 		    "exception callback handling: attrs=0x%x", attrs);
691 
692 		/*
693 		 * In exception callback handling, if we were
694 		 * not able to clear stall, we need to modify
695 		 * pipe state. Also if auto-clearing is not set
696 		 * pipe state needs to be modified.
697 		 */
698 		pipe_state = usba_get_ph_state(ph_data);
699 
700 		if (!USBA_PIPE_CLOSING(pipe_state)) {
701 			switch (completion_reason) {
702 			case USB_CR_STOPPED_POLLING:
703 				if (pipe_state ==
704 				    USB_PIPE_STATE_ACTIVE) {
705 					usba_pipe_new_state(ph_data,
706 					    USB_PIPE_STATE_IDLE);
707 				}
708 				break;
709 			case USB_CR_NOT_SUPPORTED:
710 				usba_pipe_new_state(ph_data,
711 				    USB_PIPE_STATE_IDLE);
712 				break;
713 			case USB_CR_PIPE_RESET:
714 			case USB_CR_FLUSHED:
715 				break;
716 			default:
717 				usba_pipe_new_state(ph_data,
718 				    USB_PIPE_STATE_ERROR);
719 				break;
720 			}
721 		}
722 
723 		pipe_state = usba_get_ph_state(ph_data);
724 
725 		mutex_exit(&ph_data->p_mutex);
726 		if (attrs & USB_ATTRS_PIPE_RESET) {
727 			if ((completion_reason != USB_CR_PIPE_RESET) &&
728 			    (pipe_state == USB_PIPE_STATE_ERROR)) {
729 
730 				hcdi_autoclearing(req_wrp);
731 			}
732 		}
733 
734 		usba_req_exc_cb(req_wrp, 0, 0);
735 		mutex_enter(&ph_data->p_mutex);
736 	}
737 
738 	/* Update the hcdi error kstats */
739 	if (completion_reason) {
740 		mutex_enter(&hcdi->hcdi_mutex);
741 		usba_hcdi_update_error_stats(hcdi, completion_reason);
742 		mutex_exit(&hcdi->hcdi_mutex);
743 	}
744 
745 	/*
746 	 * Once the callback is finished, release the pipe handle
747 	 * we start the next request first to avoid that the
748 	 * pipe gets closed while starting the next request
749 	 */
750 	mutex_exit(&ph_data->p_mutex);
751 	usba_start_next_req(ph_data);
752 
753 	mutex_enter(&ph_data->p_mutex);
754 }
755 
756 
757 /*
758  * thread to perform callbacks on the shared queue
759  */
760 static void
761 hcdi_shared_cb_thread(void *arg)
762 {
763 	usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)arg;
764 	usba_pipe_handle_data_t	*ph_data = req_wrp->wr_ph_data;
765 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
766 	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(ph_data->
767 	    p_usba_device->usb_root_hub_dip);
768 	/*
769 	 * hold the ph_data. we can't use usba_hold_ph_data() since
770 	 * it will return NULL if we are closing the pipe which would
771 	 * then leave all requests stuck in the cb_queue
772 	 */
773 	mutex_enter(&ph_impl->usba_ph_mutex);
774 	ph_impl->usba_ph_ref_count++;
775 
776 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
777 	    "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p",
778 	    (void *)ph_data, ph_impl->usba_ph_ref_count, (void *)req_wrp);
779 	mutex_exit(&ph_impl->usba_ph_mutex);
780 
781 	/* do the callback */
782 	mutex_enter(&ph_data->p_mutex);
783 	hcdi_do_cb(ph_data, req_wrp, hcdi);
784 	mutex_exit(&ph_data->p_mutex);
785 
786 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
787 	    "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
788 
789 	usba_release_ph_data(ph_impl);
790 }
791 
792 
793 /*
794  * soft interrupt handler
795  */
796 /*ARGSUSED*/
797 static uint_t
798 hcdi_soft_intr(caddr_t arg1, caddr_t arg2)
799 {
800 	usba_hcdi_t		*hcdi = (void *)arg1;
801 	usba_req_wrapper_t	*req_wrp;
802 	int			count = 0;
803 
804 	while ((req_wrp = (usba_req_wrapper_t *)
805 	    usba_rm_first_pvt_from_list(&hcdi->hcdi_cb_queue)) != NULL) {
806 		usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data;
807 		usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
808 
809 		/* hold the pipe */
810 		mutex_enter(&ph_impl->usba_ph_mutex);
811 		ph_impl->usba_ph_ref_count++;
812 		mutex_exit(&ph_impl->usba_ph_mutex);
813 
814 		/* do the callback */
815 		usba_req_normal_cb(req_wrp);
816 
817 		/* decrement the soft interrupt count */
818 		mutex_enter(&ph_data->p_mutex);
819 		ph_data->p_soft_intr--;
820 		mutex_exit(&ph_data->p_mutex);
821 
822 		/* release the pipe */
823 		mutex_enter(&ph_impl->usba_ph_mutex);
824 		ph_impl->usba_ph_ref_count--;
825 		mutex_exit(&ph_impl->usba_ph_mutex);
826 
827 		count++;
828 	}
829 
830 	return (count == 0 ? DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED);
831 }
832 
833 
834 /*
835  * hcdi_autoclearing:
836  *	This function is called under the taskq context. It
837  *	resets the pipe, and clears the stall, if necessary
838  */
839 static void
840 hcdi_autoclearing(usba_req_wrapper_t *req_wrp)
841 {
842 	usb_cr_t		cr = req_wrp->wr_cr;
843 	usb_pipe_handle_t	pipe_handle, def_pipe_handle;
844 	usb_cr_t		completion_reason;
845 	usb_cb_flags_t		cb_flags;
846 	int			rval;
847 	usba_device_t		*usba_device =
848 	    req_wrp->wr_ph_data->p_usba_device;
849 	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(
850 	    usba_device->usb_root_hub_dip);
851 	usb_req_attrs_t		attrs = req_wrp->wr_attrs;
852 
853 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
854 	    "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp);
855 
856 	pipe_handle = usba_get_pipe_handle(req_wrp->wr_ph_data);
857 	def_pipe_handle = usba_get_dflt_pipe_handle(req_wrp->wr_ph_data->p_dip);
858 
859 	/*
860 	 * first reset the pipe synchronously
861 	 */
862 	if ((attrs & USB_ATTRS_PIPE_RESET) == USB_ATTRS_PIPE_RESET) {
863 		usba_pipe_clear(pipe_handle);
864 		usba_req_set_cb_flags(req_wrp, USB_CB_RESET_PIPE);
865 	}
866 
867 	ASSERT(def_pipe_handle);
868 
869 	/* Do not clear if this request was a usb_get_status request */
870 	if ((pipe_handle == def_pipe_handle) &&
871 	    (USBA_WRP2CTRL_REQ(req_wrp)->ctrl_bRequest ==
872 	    USB_REQ_GET_STATUS)) {
873 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
874 		    "hcdi_autoclearing: usb_get_status failed, no clearing");
875 
876 	/* if default pipe and stall no auto clearing */
877 	} else if ((pipe_handle == def_pipe_handle) && (cr == USB_CR_STALL)) {
878 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
879 		    "hcdi_autoclearing: default pipe stalled, no clearing");
880 
881 		usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
882 
883 	/* else do auto clearing */
884 	} else if (((attrs & USB_ATTRS_AUTOCLEARING) ==
885 	    USB_ATTRS_AUTOCLEARING) && (cr == USB_CR_STALL)) {
886 		ushort_t status = 0;
887 
888 		rval = usb_get_status(req_wrp->wr_dip, def_pipe_handle,
889 		    USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_EP,
890 		    req_wrp->wr_ph_data->p_ep.bEndpointAddress,
891 		    &status, USB_FLAGS_SLEEP);
892 		if (rval != USB_SUCCESS) {
893 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
894 			    "get status (STALL) failed: rval=%d", rval);
895 
896 			usba_pipe_clear(def_pipe_handle);
897 		}
898 
899 		if ((rval != USB_SUCCESS) ||
900 		    (status & USB_EP_HALT_STATUS)) {
901 			usba_req_set_cb_flags(req_wrp, USB_CB_FUNCTIONAL_STALL);
902 
903 			if ((rval = usb_pipe_sync_ctrl_xfer(
904 			    req_wrp->wr_dip, def_pipe_handle,
905 			    USB_DEV_REQ_HOST_TO_DEV |
906 			    USB_DEV_REQ_RCPT_EP,
907 			    USB_REQ_CLEAR_FEATURE,
908 			    0,
909 			    req_wrp->wr_ph_data->p_ep.bEndpointAddress,
910 			    0,
911 			    NULL, 0,
912 			    &completion_reason,
913 			    &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
914 				USB_DPRINTF_L2(DPRINT_MASK_USBAI,
915 				    hcdi->hcdi_log_handle,
916 				    "auto clearing (STALL) failed: "
917 				    "rval=%d, cr=0x%x cb=0x%x",
918 				    rval, completion_reason, cb_flags);
919 
920 				usba_pipe_clear(def_pipe_handle);
921 			} else {
922 				usba_req_set_cb_flags(req_wrp,
923 				    USB_CB_STALL_CLEARED);
924 			}
925 		} else {
926 			usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
927 		}
928 	}
929 }
930 
931 
932 /*
933  * usba_hcdi_get_req_private:
934  *	This function is used to get the HCD private field
935  *	maintained by USBA. HCD calls this function.
936  *
937  * Arguments:
938  *	req		- pointer to usb_*_req_t
939  *
940  * Return Values:
941  *	wr_hcd_private field from wrapper
942  */
943 usb_opaque_t
944 usba_hcdi_get_req_private(usb_opaque_t req)
945 {
946 	usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
947 
948 	return (wrp->wr_hcd_private);
949 }
950 
951 
952 /*
953  * usba_hcdi_set_req_private:
954  *	This function is used to set the HCD private field
955  *	maintained by USBA. HCD calls this function.
956  *
957  * Arguments:
958  *	req		- pointer to usb_*_req_t
959  *	hcd_private	- wr_hcd_private field from wrapper
960  */
961 void
962 usba_hcdi_set_req_private(usb_opaque_t req,
963 			usb_opaque_t	hcd_private)
964 {
965 	usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
966 
967 	wrp->wr_hcd_private = hcd_private;
968 }
969 
970 
971 /* get data toggle information for this endpoint */
972 uchar_t
973 usba_hcdi_get_data_toggle(usba_device_t *usba_device, uint8_t ep_addr)
974 {
975 	uchar_t		toggle;
976 	usba_ph_impl_t	*ph_impl;
977 	int		ep_index;
978 
979 	ep_index = usb_get_ep_index(ep_addr);
980 	mutex_enter(&usba_device->usb_mutex);
981 	ph_impl = &usba_device->usb_ph_list[ep_index];
982 	mutex_enter(&ph_impl->usba_ph_mutex);
983 	toggle = (uchar_t)(ph_impl->usba_ph_flags & USBA_PH_DATA_TOGGLE);
984 	mutex_exit(&ph_impl->usba_ph_mutex);
985 	mutex_exit(&usba_device->usb_mutex);
986 
987 	return (toggle);
988 }
989 
990 
991 /* set data toggle information for this endpoint */
992 void
993 usba_hcdi_set_data_toggle(usba_device_t *usba_device, uint8_t ep_addr,
994     uchar_t toggle)
995 {
996 	usba_ph_impl_t	*ph_impl;
997 	int		ep_index;
998 
999 	ep_index = usb_get_ep_index(ep_addr);
1000 	mutex_enter(&usba_device->usb_mutex);
1001 	ph_impl = &usba_device->usb_ph_list[ep_index];
1002 	mutex_enter(&ph_impl->usba_ph_mutex);
1003 	ph_impl->usba_ph_flags &= ~USBA_PH_DATA_TOGGLE;
1004 	ph_impl->usba_ph_flags |= (USBA_PH_DATA_TOGGLE & toggle);
1005 	mutex_exit(&ph_impl->usba_ph_mutex);
1006 	mutex_exit(&usba_device->usb_mutex);
1007 }
1008 
1009 
1010 /* get pipe_handle_impl ptr for this ep */
1011 usba_pipe_handle_data_t *
1012 usba_hcdi_get_ph_data(usba_device_t *usba_device, uint8_t ep_addr)
1013 {
1014 	return (usba_device->usb_ph_list[usb_get_ep_index(ep_addr)].
1015 	    usba_ph_data);
1016 }
1017