xref: /titanic_41/usr/src/uts/common/io/usb/usba/hcdi.c (revision 7535ae1914017b0e648abd7a139aca709fa82be3)
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
usba_hcdi_initialization()68 usba_hcdi_initialization()
69 {
70 }
71 
72 
73 void
usba_hcdi_destroy()74 usba_hcdi_destroy()
75 {
76 }
77 
78 
79 /*
80  * store hcdi structure in the dip
81  */
82 void
usba_hcdi_set_hcdi(dev_info_t * dip,usba_hcdi_t * hcdi)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 *
usba_hcdi_get_hcdi(dev_info_t * dip)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
usba_hcdi_register(usba_hcdi_register_args_t * args,uint_t flags)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
usba_hcdi_unregister(dev_info_t * dip)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 *
usba_alloc_hcdi_ops()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
usba_free_hcdi_ops(usba_hcdi_ops_t * hcdi_ops)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
usba_hcdi_create_stats(usba_hcdi_t * hcdi,int instance)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_no_resources,
347 		    "No Resources", KSTAT_DATA_UINT64);
348 		kstat_named_init(&esp->cc_unspecified_err,
349 		    "Unspecified Error", KSTAT_DATA_UINT64);
350 		kstat_named_init(&esp->cc_stopped_polling,
351 		    "Stopped Polling", KSTAT_DATA_UINT64);
352 		kstat_named_init(&esp->cc_pipe_closing,
353 		    "Pipe Closing", KSTAT_DATA_UINT64);
354 		kstat_named_init(&esp->cc_pipe_reset,
355 		    "Pipe Reset", KSTAT_DATA_UINT64);
356 		kstat_named_init(&esp->cc_not_supported,
357 		    "Command Not Supported", KSTAT_DATA_UINT64);
358 		kstat_named_init(&esp->cc_flushed,
359 		    "Request Flushed", KSTAT_DATA_UINT64);
360 
361 		HCDI_ERROR_STATS(hcdi)->ks_private = hcdi;
362 		HCDI_ERROR_STATS(hcdi)->ks_update = nulldev;
363 		kstat_install(HCDI_ERROR_STATS(hcdi));
364 	}
365 }
366 
367 
368 /*
369  * Do actual error stats
370  */
371 void
usba_hcdi_update_error_stats(usba_hcdi_t * hcdi,usb_cr_t completion_reason)372 usba_hcdi_update_error_stats(usba_hcdi_t *hcdi, usb_cr_t completion_reason)
373 {
374 	if (HCDI_ERROR_STATS(hcdi) == NULL) {
375 
376 		return;
377 	}
378 
379 	switch (completion_reason) {
380 	case USB_CR_OK:
381 		break;
382 	case USB_CR_CRC:
383 		HCDI_ERROR_STATS_DATA(hcdi)->cc_crc.value.ui64++;
384 		break;
385 	case USB_CR_BITSTUFFING:
386 		HCDI_ERROR_STATS_DATA(hcdi)->cc_bitstuffing.value.ui64++;
387 		break;
388 	case USB_CR_DATA_TOGGLE_MM:
389 		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_toggle_mm.value.ui64++;
390 		break;
391 	case USB_CR_STALL:
392 		HCDI_ERROR_STATS_DATA(hcdi)->cc_stall.value.ui64++;
393 		break;
394 	case USB_CR_DEV_NOT_RESP:
395 		HCDI_ERROR_STATS_DATA(hcdi)->cc_dev_not_resp.value.ui64++;
396 		break;
397 	case USB_CR_PID_CHECKFAILURE:
398 		HCDI_ERROR_STATS_DATA(hcdi)->cc_pid_checkfailure.value.ui64++;
399 		break;
400 	case USB_CR_UNEXP_PID:
401 		HCDI_ERROR_STATS_DATA(hcdi)->cc_unexp_pid.value.ui64++;
402 		break;
403 	case USB_CR_DATA_OVERRUN:
404 		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_overrun.value.ui64++;
405 		break;
406 	case USB_CR_DATA_UNDERRUN:
407 		HCDI_ERROR_STATS_DATA(hcdi)->cc_data_underrun.value.ui64++;
408 		break;
409 	case USB_CR_BUFFER_OVERRUN:
410 		HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_overrun.value.ui64++;
411 		break;
412 	case USB_CR_BUFFER_UNDERRUN:
413 		HCDI_ERROR_STATS_DATA(hcdi)->cc_buffer_underrun.value.ui64++;
414 		break;
415 	case USB_CR_TIMEOUT:
416 		HCDI_ERROR_STATS_DATA(hcdi)->cc_timeout.value.ui64++;
417 		break;
418 	case USB_CR_NOT_ACCESSED:
419 		HCDI_ERROR_STATS_DATA(hcdi)->cc_not_accessed.value.ui64++;
420 		break;
421 	case USB_CR_NO_RESOURCES:
422 		HCDI_ERROR_STATS_DATA(hcdi)->cc_no_resources.value.ui64++;
423 		break;
424 	case USB_CR_UNSPECIFIED_ERR:
425 		HCDI_ERROR_STATS_DATA(hcdi)->cc_unspecified_err.value.ui64++;
426 		break;
427 	case USB_CR_STOPPED_POLLING:
428 		HCDI_ERROR_STATS_DATA(hcdi)->cc_stopped_polling.value.ui64++;
429 		break;
430 	case USB_CR_PIPE_CLOSING:
431 		HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_closing.value.ui64++;
432 		break;
433 	case USB_CR_PIPE_RESET:
434 		HCDI_ERROR_STATS_DATA(hcdi)->cc_pipe_reset.value.ui64++;
435 		break;
436 	case USB_CR_NOT_SUPPORTED:
437 		HCDI_ERROR_STATS_DATA(hcdi)->cc_not_supported.value.ui64++;
438 		break;
439 	case USB_CR_FLUSHED:
440 		HCDI_ERROR_STATS_DATA(hcdi)->cc_flushed.value.ui64++;
441 		break;
442 	default:
443 		break;
444 	}
445 }
446 
447 
448 /*
449  * Destroy the hotplug kstats structure
450  */
451 static void
usba_hcdi_destroy_stats(usba_hcdi_t * hcdi)452 usba_hcdi_destroy_stats(usba_hcdi_t *hcdi)
453 {
454 	if (HCDI_HOTPLUG_STATS(hcdi)) {
455 		kstat_delete(HCDI_HOTPLUG_STATS(hcdi));
456 		HCDI_HOTPLUG_STATS(hcdi) = NULL;
457 	}
458 
459 	if (HCDI_ERROR_STATS(hcdi)) {
460 		kstat_delete(HCDI_ERROR_STATS(hcdi));
461 		HCDI_ERROR_STATS(hcdi) = NULL;
462 	}
463 }
464 
465 
466 /*
467  * HCD callback handling
468  */
469 void
usba_hcdi_cb(usba_pipe_handle_data_t * ph_data,usb_opaque_t req,usb_cr_t completion_reason)470 usba_hcdi_cb(usba_pipe_handle_data_t *ph_data,
471 	usb_opaque_t	req,
472 	usb_cr_t	completion_reason)
473 {
474 
475 	usba_device_t		*usba_device = ph_data->p_usba_device;
476 	usba_hcdi_t		*hcdi =	usba_hcdi_get_hcdi(
477 	    usba_device->usb_root_hub_dip);
478 	usba_req_wrapper_t	*req_wrp = USBA_REQ2WRP(req);
479 	usb_ep_descr_t		*eptd = &ph_data->p_ep;
480 
481 	mutex_enter(&ph_data->p_mutex);
482 
483 #ifdef DEBUG
484 	mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
485 
486 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
487 	    "usba_hcdi_cb: "
488 	    "ph_data=0x%p req=0x%p state=%d ref=%d cnt=%d cr=%d",
489 	    (void *)ph_data, (void *)req, ph_data->p_ph_impl->usba_ph_state,
490 	    ph_data->p_ph_impl->usba_ph_ref_count, ph_data->p_req_count,
491 	    completion_reason);
492 
493 	mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
494 #endif
495 
496 	/* Set the completion reason */
497 	switch (eptd->bmAttributes & USB_EP_ATTR_MASK) {
498 	case USB_EP_ATTR_CONTROL:
499 		((usb_ctrl_req_t *)req)->
500 		    ctrl_completion_reason = completion_reason;
501 		break;
502 	case USB_EP_ATTR_BULK:
503 		((usb_bulk_req_t *)req)->
504 		    bulk_completion_reason = completion_reason;
505 		break;
506 	case USB_EP_ATTR_INTR:
507 		((usb_intr_req_t *)req)->
508 		    intr_completion_reason = completion_reason;
509 		break;
510 	case USB_EP_ATTR_ISOCH:
511 		((usb_isoc_req_t *)req)->
512 		    isoc_completion_reason = completion_reason;
513 		break;
514 	}
515 
516 	/*
517 	 * exception callbacks will still go thru a taskq thread
518 	 * but should occur after the soft interrupt callback
519 	 * By design of periodic pipes, polling will stop on any
520 	 * exception
521 	 */
522 	if ((ph_data->p_spec_flag & USBA_PH_FLAG_USE_SOFT_INTR) &&
523 	    (completion_reason == USB_CR_OK)) {
524 		ph_data->p_soft_intr++;
525 		mutex_exit(&ph_data->p_mutex);
526 
527 		usba_add_to_list(&hcdi->hcdi_cb_queue, &req_wrp->wr_queue);
528 
529 		if (ddi_intr_trigger_softint(hcdi->hcdi_softint_hdl, NULL) !=
530 		    DDI_SUCCESS)
531 			USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
532 			    "usba_hcdi_cb: ddi_intr_trigger_softint  failed");
533 
534 		return;
535 	}
536 
537 	/*
538 	 * USBA_PH_FLAG_TQ_SHARE is for bulk and intr requests,
539 	 * USBA_PH_FLAG_USE_SOFT_INTR is only for isoch,
540 	 * so there are no conflicts.
541 	 */
542 	if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
543 		int iface;
544 
545 		mutex_exit(&ph_data->p_mutex);
546 		iface = usb_get_if_number(ph_data->p_dip);
547 		if (iface < 0) {
548 			/* we own the device, use the first taskq */
549 			iface = 0;
550 		}
551 		if (taskq_dispatch(usba_device->usb_shared_taskq[iface],
552 		    hcdi_shared_cb_thread, req_wrp, TQ_NOSLEEP) ==
553 		    NULL) {
554 			usba_req_exc_cb(req_wrp,
555 			    USB_CR_NO_RESOURCES, USB_CB_ASYNC_REQ_FAILED);
556 		}
557 
558 		return;
559 	}
560 
561 	/* Add the callback to the pipehandles callback list */
562 	usba_add_to_list(&ph_data->p_cb_queue, &req_wrp->wr_queue);
563 
564 	/* only dispatch if there is no thread running */
565 	if (ph_data->p_thread_id == 0) {
566 		if (usba_async_ph_req(ph_data, hcdi_cb_thread,
567 		    ph_data, USB_FLAGS_NOSLEEP) != USB_SUCCESS) {
568 			USB_DPRINTF_L2(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
569 			    "usba_hcdi_cb: taskq_dispatch failed");
570 			if (usba_rm_from_list(&ph_data->p_cb_queue,
571 			    &req_wrp->wr_queue) == USB_SUCCESS) {
572 				mutex_exit(&ph_data->p_mutex);
573 				usba_req_exc_cb(req_wrp,
574 				    USB_CR_NO_RESOURCES,
575 				    USB_CB_ASYNC_REQ_FAILED);
576 
577 				return;
578 			}
579 		} else {
580 			ph_data->p_thread_id = (kthread_t *)1;
581 		}
582 	}
583 	mutex_exit(&ph_data->p_mutex);
584 }
585 
586 
587 /*
588  * thread to perform the callbacks
589  */
590 static void
hcdi_cb_thread(void * arg)591 hcdi_cb_thread(void *arg)
592 {
593 	usba_pipe_handle_data_t	*ph_data =
594 	    (usba_pipe_handle_data_t *)arg;
595 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
596 	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(ph_data->
597 	    p_usba_device->usb_root_hub_dip);
598 	usba_req_wrapper_t	*req_wrp;
599 
600 	mutex_enter(&ph_data->p_mutex);
601 	ASSERT(ph_data->p_thread_id == (kthread_t *)1);
602 	ph_data->p_thread_id = curthread;
603 
604 	/*
605 	 * hold the ph_data. we can't use usba_hold_ph_data() since
606 	 * it will return NULL if we are closing the pipe which would
607 	 * then leave all requests stuck in the cb_queue
608 	 */
609 	mutex_enter(&ph_impl->usba_ph_mutex);
610 	ph_impl->usba_ph_ref_count++;
611 
612 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
613 	    "hcdi_cb_thread: ph_data=0x%p ref=%d", (void *)ph_data,
614 	    ph_impl->usba_ph_ref_count);
615 
616 	mutex_exit(&ph_impl->usba_ph_mutex);
617 
618 	/*
619 	 * wait till soft interrupt callbacks are taken care of
620 	 */
621 	while (ph_data->p_soft_intr) {
622 		mutex_exit(&ph_data->p_mutex);
623 		delay(1);
624 		mutex_enter(&ph_data->p_mutex);
625 	}
626 
627 	while ((req_wrp = (usba_req_wrapper_t *)
628 	    usba_rm_first_pvt_from_list(&ph_data->p_cb_queue)) != NULL) {
629 		hcdi_do_cb(ph_data, req_wrp, hcdi);
630 	}
631 
632 	ph_data->p_thread_id = 0;
633 	mutex_exit(&ph_data->p_mutex);
634 
635 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
636 	    "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
637 
638 	usba_release_ph_data(ph_impl);
639 }
640 
641 
642 static void
hcdi_do_cb(usba_pipe_handle_data_t * ph_data,usba_req_wrapper_t * req_wrp,usba_hcdi_t * hcdi)643 hcdi_do_cb(usba_pipe_handle_data_t *ph_data, usba_req_wrapper_t *req_wrp,
644     usba_hcdi_t *hcdi)
645 {
646 	usb_cr_t		completion_reason;
647 	usb_req_attrs_t		attrs = req_wrp->wr_attrs;
648 
649 	switch (req_wrp->wr_ph_data->p_ep.bmAttributes &
650 	    USB_EP_ATTR_MASK) {
651 	case USB_EP_ATTR_CONTROL:
652 		completion_reason =
653 		    USBA_WRP2CTRL_REQ(req_wrp)->ctrl_completion_reason;
654 		break;
655 	case USB_EP_ATTR_INTR:
656 		completion_reason =
657 		    USBA_WRP2INTR_REQ(req_wrp)->intr_completion_reason;
658 		break;
659 	case USB_EP_ATTR_BULK:
660 		completion_reason =
661 		    USBA_WRP2BULK_REQ(req_wrp)->bulk_completion_reason;
662 		break;
663 	case USB_EP_ATTR_ISOCH:
664 		completion_reason =
665 		    USBA_WRP2ISOC_REQ(req_wrp)->isoc_completion_reason;
666 		break;
667 	}
668 	req_wrp->wr_cr = completion_reason;
669 
670 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
671 	    "hcdi_do_cb: wrp=0x%p cr=0x%x", (void *)req_wrp, completion_reason);
672 
673 	/*
674 	 * Normal callbacks:
675 	 */
676 	if (completion_reason == USB_CR_OK) {
677 		mutex_exit(&ph_data->p_mutex);
678 		usba_req_normal_cb(req_wrp);
679 		mutex_enter(&ph_data->p_mutex);
680 	} else {
681 		usb_pipe_state_t pipe_state;
682 
683 		USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
684 		    "exception callback handling: attrs=0x%x", attrs);
685 
686 		/*
687 		 * In exception callback handling, if we were
688 		 * not able to clear stall, we need to modify
689 		 * pipe state. Also if auto-clearing is not set
690 		 * pipe state needs to be modified.
691 		 */
692 		pipe_state = usba_get_ph_state(ph_data);
693 
694 		if (!USBA_PIPE_CLOSING(pipe_state)) {
695 			switch (completion_reason) {
696 			case USB_CR_STOPPED_POLLING:
697 				if (pipe_state ==
698 				    USB_PIPE_STATE_ACTIVE) {
699 					usba_pipe_new_state(ph_data,
700 					    USB_PIPE_STATE_IDLE);
701 				}
702 				break;
703 			case USB_CR_NOT_SUPPORTED:
704 				usba_pipe_new_state(ph_data,
705 				    USB_PIPE_STATE_IDLE);
706 				break;
707 			case USB_CR_PIPE_RESET:
708 			case USB_CR_FLUSHED:
709 				break;
710 			default:
711 				usba_pipe_new_state(ph_data,
712 				    USB_PIPE_STATE_ERROR);
713 				break;
714 			}
715 		}
716 
717 		pipe_state = usba_get_ph_state(ph_data);
718 
719 		mutex_exit(&ph_data->p_mutex);
720 		if (attrs & USB_ATTRS_PIPE_RESET) {
721 			if ((completion_reason != USB_CR_PIPE_RESET) &&
722 			    (pipe_state == USB_PIPE_STATE_ERROR)) {
723 
724 				hcdi_autoclearing(req_wrp);
725 			}
726 		}
727 
728 		usba_req_exc_cb(req_wrp, 0, 0);
729 		mutex_enter(&ph_data->p_mutex);
730 	}
731 
732 	/* Update the hcdi error kstats */
733 	if (completion_reason) {
734 		mutex_enter(&hcdi->hcdi_mutex);
735 		usba_hcdi_update_error_stats(hcdi, completion_reason);
736 		mutex_exit(&hcdi->hcdi_mutex);
737 	}
738 
739 	/*
740 	 * Once the callback is finished, release the pipe handle
741 	 * we start the next request first to avoid that the
742 	 * pipe gets closed while starting the next request
743 	 */
744 	mutex_exit(&ph_data->p_mutex);
745 	usba_start_next_req(ph_data);
746 
747 	mutex_enter(&ph_data->p_mutex);
748 }
749 
750 
751 /*
752  * thread to perform callbacks on the shared queue
753  */
754 static void
hcdi_shared_cb_thread(void * arg)755 hcdi_shared_cb_thread(void *arg)
756 {
757 	usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)arg;
758 	usba_pipe_handle_data_t	*ph_data = req_wrp->wr_ph_data;
759 	usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
760 	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(ph_data->
761 	    p_usba_device->usb_root_hub_dip);
762 	/*
763 	 * hold the ph_data. we can't use usba_hold_ph_data() since
764 	 * it will return NULL if we are closing the pipe which would
765 	 * then leave all requests stuck in the cb_queue
766 	 */
767 	mutex_enter(&ph_impl->usba_ph_mutex);
768 	ph_impl->usba_ph_ref_count++;
769 
770 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
771 	    "hcdi_shared_cb_thread: ph_data=0x%p ref=%d req=0x%p",
772 	    (void *)ph_data, ph_impl->usba_ph_ref_count, (void *)req_wrp);
773 	mutex_exit(&ph_impl->usba_ph_mutex);
774 
775 	/* do the callback */
776 	mutex_enter(&ph_data->p_mutex);
777 	hcdi_do_cb(ph_data, req_wrp, hcdi);
778 	mutex_exit(&ph_data->p_mutex);
779 
780 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
781 	    "hcdi_cb_thread done: ph_data=0x%p", (void *)ph_data);
782 
783 	usba_release_ph_data(ph_impl);
784 }
785 
786 
787 /*
788  * soft interrupt handler
789  */
790 /*ARGSUSED*/
791 static uint_t
hcdi_soft_intr(caddr_t arg1,caddr_t arg2)792 hcdi_soft_intr(caddr_t arg1, caddr_t arg2)
793 {
794 	usba_hcdi_t		*hcdi = (void *)arg1;
795 	usba_req_wrapper_t	*req_wrp;
796 	int			count = 0;
797 
798 	while ((req_wrp = (usba_req_wrapper_t *)
799 	    usba_rm_first_pvt_from_list(&hcdi->hcdi_cb_queue)) != NULL) {
800 		usba_pipe_handle_data_t *ph_data = req_wrp->wr_ph_data;
801 		usba_ph_impl_t		*ph_impl = ph_data->p_ph_impl;
802 
803 		/* hold the pipe */
804 		mutex_enter(&ph_impl->usba_ph_mutex);
805 		ph_impl->usba_ph_ref_count++;
806 		mutex_exit(&ph_impl->usba_ph_mutex);
807 
808 		/* do the callback */
809 		usba_req_normal_cb(req_wrp);
810 
811 		/* decrement the soft interrupt count */
812 		mutex_enter(&ph_data->p_mutex);
813 		ph_data->p_soft_intr--;
814 		mutex_exit(&ph_data->p_mutex);
815 
816 		/* release the pipe */
817 		mutex_enter(&ph_impl->usba_ph_mutex);
818 		ph_impl->usba_ph_ref_count--;
819 		mutex_exit(&ph_impl->usba_ph_mutex);
820 
821 		count++;
822 	}
823 
824 	return (count == 0 ? DDI_INTR_UNCLAIMED : DDI_INTR_CLAIMED);
825 }
826 
827 
828 /*
829  * hcdi_autoclearing:
830  *	This function is called under the taskq context. It
831  *	resets the pipe, and clears the stall, if necessary
832  */
833 static void
hcdi_autoclearing(usba_req_wrapper_t * req_wrp)834 hcdi_autoclearing(usba_req_wrapper_t *req_wrp)
835 {
836 	usb_cr_t		cr = req_wrp->wr_cr;
837 	usb_pipe_handle_t	pipe_handle, def_pipe_handle;
838 	usb_cr_t		completion_reason;
839 	usb_cb_flags_t		cb_flags;
840 	int			rval;
841 	usba_device_t		*usba_device =
842 	    req_wrp->wr_ph_data->p_usba_device;
843 	usba_hcdi_t		*hcdi = usba_hcdi_get_hcdi(
844 	    usba_device->usb_root_hub_dip);
845 	usb_req_attrs_t		attrs = req_wrp->wr_attrs;
846 
847 	USB_DPRINTF_L4(DPRINT_MASK_HCDI, hcdi->hcdi_log_handle,
848 	    "hcdi_autoclearing: wrp=0x%p", (void *)req_wrp);
849 
850 	pipe_handle = usba_get_pipe_handle(req_wrp->wr_ph_data);
851 	def_pipe_handle = usba_get_dflt_pipe_handle(req_wrp->wr_ph_data->p_dip);
852 
853 	/*
854 	 * first reset the pipe synchronously
855 	 */
856 	if ((attrs & USB_ATTRS_PIPE_RESET) == USB_ATTRS_PIPE_RESET) {
857 		usba_pipe_clear(pipe_handle);
858 		usba_req_set_cb_flags(req_wrp, USB_CB_RESET_PIPE);
859 	}
860 
861 	ASSERT(def_pipe_handle);
862 
863 	/* Do not clear if this request was a usb_get_status request */
864 	if ((pipe_handle == def_pipe_handle) &&
865 	    (USBA_WRP2CTRL_REQ(req_wrp)->ctrl_bRequest ==
866 	    USB_REQ_GET_STATUS)) {
867 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
868 		    "hcdi_autoclearing: usb_get_status failed, no clearing");
869 
870 	/* if default pipe and stall no auto clearing */
871 	} else if ((pipe_handle == def_pipe_handle) && (cr == USB_CR_STALL)) {
872 		USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
873 		    "hcdi_autoclearing: default pipe stalled, no clearing");
874 
875 		usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
876 
877 	/* else do auto clearing */
878 	} else if (((attrs & USB_ATTRS_AUTOCLEARING) ==
879 	    USB_ATTRS_AUTOCLEARING) && (cr == USB_CR_STALL)) {
880 		ushort_t status = 0;
881 
882 		rval = usb_get_status(req_wrp->wr_dip, def_pipe_handle,
883 		    USB_DEV_REQ_DEV_TO_HOST | USB_DEV_REQ_RCPT_EP,
884 		    req_wrp->wr_ph_data->p_ep.bEndpointAddress,
885 		    &status, USB_FLAGS_SLEEP);
886 		if (rval != USB_SUCCESS) {
887 			USB_DPRINTF_L2(DPRINT_MASK_USBAI, hcdi->hcdi_log_handle,
888 			    "get status (STALL) failed: rval=%d", rval);
889 
890 			usba_pipe_clear(def_pipe_handle);
891 		}
892 
893 		if ((rval != USB_SUCCESS) ||
894 		    (status & USB_EP_HALT_STATUS)) {
895 			usba_req_set_cb_flags(req_wrp, USB_CB_FUNCTIONAL_STALL);
896 
897 			if ((rval = usb_pipe_sync_ctrl_xfer(
898 			    req_wrp->wr_dip, def_pipe_handle,
899 			    USB_DEV_REQ_HOST_TO_DEV |
900 			    USB_DEV_REQ_RCPT_EP,
901 			    USB_REQ_CLEAR_FEATURE,
902 			    0,
903 			    req_wrp->wr_ph_data->p_ep.bEndpointAddress,
904 			    0,
905 			    NULL, 0,
906 			    &completion_reason,
907 			    &cb_flags, USB_FLAGS_SLEEP)) != USB_SUCCESS) {
908 				USB_DPRINTF_L2(DPRINT_MASK_USBAI,
909 				    hcdi->hcdi_log_handle,
910 				    "auto clearing (STALL) failed: "
911 				    "rval=%d, cr=0x%x cb=0x%x",
912 				    rval, completion_reason, cb_flags);
913 
914 				usba_pipe_clear(def_pipe_handle);
915 			} else {
916 				usba_req_set_cb_flags(req_wrp,
917 				    USB_CB_STALL_CLEARED);
918 			}
919 		} else {
920 			usba_req_set_cb_flags(req_wrp, USB_CB_PROTOCOL_STALL);
921 		}
922 	}
923 }
924 
925 
926 /*
927  * usba_hcdi_get_req_private:
928  *	This function is used to get the HCD private field
929  *	maintained by USBA. HCD calls this function.
930  *
931  * Arguments:
932  *	req		- pointer to usb_*_req_t
933  *
934  * Return Values:
935  *	wr_hcd_private field from wrapper
936  */
937 usb_opaque_t
usba_hcdi_get_req_private(usb_opaque_t req)938 usba_hcdi_get_req_private(usb_opaque_t req)
939 {
940 	usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
941 
942 	return (wrp->wr_hcd_private);
943 }
944 
945 
946 /*
947  * usba_hcdi_set_req_private:
948  *	This function is used to set the HCD private field
949  *	maintained by USBA. HCD calls this function.
950  *
951  * Arguments:
952  *	req		- pointer to usb_*_req_t
953  *	hcd_private	- wr_hcd_private field from wrapper
954  */
955 void
usba_hcdi_set_req_private(usb_opaque_t req,usb_opaque_t hcd_private)956 usba_hcdi_set_req_private(usb_opaque_t req,
957 			usb_opaque_t	hcd_private)
958 {
959 	usba_req_wrapper_t *wrp = USBA_REQ2WRP(req);
960 
961 	wrp->wr_hcd_private = hcd_private;
962 }
963 
964 
965 /* get data toggle information for this endpoint */
966 uchar_t
usba_hcdi_get_data_toggle(usba_device_t * usba_device,uint8_t ep_addr)967 usba_hcdi_get_data_toggle(usba_device_t *usba_device, uint8_t ep_addr)
968 {
969 	uchar_t		toggle;
970 	usba_ph_impl_t	*ph_impl;
971 	int		ep_index;
972 
973 	ep_index = usb_get_ep_index(ep_addr);
974 	mutex_enter(&usba_device->usb_mutex);
975 	ph_impl = &usba_device->usb_ph_list[ep_index];
976 	mutex_enter(&ph_impl->usba_ph_mutex);
977 	toggle = (uchar_t)(ph_impl->usba_ph_flags & USBA_PH_DATA_TOGGLE);
978 	mutex_exit(&ph_impl->usba_ph_mutex);
979 	mutex_exit(&usba_device->usb_mutex);
980 
981 	return (toggle);
982 }
983 
984 
985 /* set data toggle information for this endpoint */
986 void
usba_hcdi_set_data_toggle(usba_device_t * usba_device,uint8_t ep_addr,uchar_t toggle)987 usba_hcdi_set_data_toggle(usba_device_t *usba_device, uint8_t ep_addr,
988     uchar_t toggle)
989 {
990 	usba_ph_impl_t	*ph_impl;
991 	int		ep_index;
992 
993 	ep_index = usb_get_ep_index(ep_addr);
994 	mutex_enter(&usba_device->usb_mutex);
995 	ph_impl = &usba_device->usb_ph_list[ep_index];
996 	mutex_enter(&ph_impl->usba_ph_mutex);
997 	ph_impl->usba_ph_flags &= ~USBA_PH_DATA_TOGGLE;
998 	ph_impl->usba_ph_flags |= (USBA_PH_DATA_TOGGLE & toggle);
999 	mutex_exit(&ph_impl->usba_ph_mutex);
1000 	mutex_exit(&usba_device->usb_mutex);
1001 }
1002 
1003 
1004 /* get pipe_handle_impl ptr for this ep */
1005 usba_pipe_handle_data_t *
usba_hcdi_get_ph_data(usba_device_t * usba_device,uint8_t ep_addr)1006 usba_hcdi_get_ph_data(usba_device_t *usba_device, uint8_t ep_addr)
1007 {
1008 	return (usba_device->usb_ph_list[usb_get_ep_index(ep_addr)].
1009 	    usba_ph_data);
1010 }
1011