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