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