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