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