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