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