Print this page
5045 use atomic_{inc,dec}_* instead of atomic_add_*
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.c
+++ new/usr/src/uts/common/io/usb/usba/usbai_pipe_mgmt.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 2009 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 */
25 25
26 26
27 27 /*
28 28 * USBA: Solaris USB Architecture support
29 29 *
30 30 * all functions exposed to client drivers have prefix usb_ while all USBA
31 31 * internal functions or functions exposed to HCD or hubd only have prefix
32 32 * usba_
33 33 *
34 34 * this file contains all USBAI pipe management
35 35 * usb_pipe_open()
36 36 * usb_pipe_close()
37 37 * usb_pipe_set_private()
38 38 * usb_pipe_get_private()
39 39 * usb_pipe_abort()
40 40 * usb_pipe_reset()
41 41 * usb_pipe_drain_reqs()
42 42 */
43 43 #define USBA_FRAMEWORK
44 44 #include <sys/usb/usba/usba_impl.h>
45 45 #include <sys/usb/usba/hcdi_impl.h>
46 46 #include <sys/atomic.h>
47 47
48 48 extern pri_t maxclsyspri;
49 49 extern pri_t minclsyspri;
50 50
51 51 /* function prototypes */
52 52 static void usba_pipe_do_async_func_thread(void *arg);
53 53 static int usba_pipe_sync_close(dev_info_t *, usba_ph_impl_t *,
54 54 usba_pipe_async_req_t *, usb_flags_t);
55 55 static int usba_pipe_sync_reset(dev_info_t *, usba_ph_impl_t *,
56 56 usba_pipe_async_req_t *, usb_flags_t);
57 57 static int usba_pipe_sync_drain_reqs(dev_info_t *, usba_ph_impl_t *,
58 58 usba_pipe_async_req_t *, usb_flags_t);
59 59
60 60 /* local tunables */
61 61 int usba_drain_timeout = 1000; /* in ms */
62 62
63 63 /* return the default pipe for this device */
64 64 usb_pipe_handle_t
65 65 usba_get_dflt_pipe_handle(dev_info_t *dip)
66 66 {
67 67 usba_device_t *usba_device;
68 68 usb_pipe_handle_t pipe_handle = NULL;
69 69
70 70 if (dip) {
71 71 usba_device = usba_get_usba_device(dip);
72 72 if (usba_device) {
73 73 pipe_handle =
74 74 (usb_pipe_handle_t)&usba_device->usb_ph_list[0];
75 75 }
76 76 }
77 77
78 78 return (pipe_handle);
79 79 }
80 80
81 81
82 82 /* return dip owner of pipe_handle */
83 83 dev_info_t *
84 84 usba_get_dip(usb_pipe_handle_t pipe_handle)
85 85 {
86 86 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle;
87 87 dev_info_t *dip = NULL;
88 88
89 89 if (ph_impl) {
90 90 mutex_enter(&ph_impl->usba_ph_mutex);
91 91 dip = ph_impl->usba_ph_dip;
92 92 mutex_exit(&ph_impl->usba_ph_mutex);
93 93 }
94 94
95 95 return (dip);
96 96 }
97 97
98 98
99 99 usb_pipe_handle_t
100 100 usba_usbdev_to_dflt_pipe_handle(usba_device_t *usba_device)
101 101 {
102 102 usb_pipe_handle_t pipe_handle = NULL;
103 103
104 104 if ((usba_device) &&
105 105 (usba_device->usb_ph_list[0].usba_ph_data != NULL)) {
106 106 pipe_handle = (usb_pipe_handle_t)&usba_device->usb_ph_list[0];
107 107 }
108 108
109 109 return (pipe_handle);
110 110 }
111 111
112 112
113 113 usba_pipe_handle_data_t *
114 114 usba_get_ph_data(usb_pipe_handle_t pipe_handle)
115 115 {
116 116 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle;
117 117 usba_pipe_handle_data_t *ph_data = NULL;
118 118
119 119 if (ph_impl) {
120 120 mutex_enter(&ph_impl->usba_ph_mutex);
121 121 ASSERT(ph_impl->usba_ph_ref_count >= 0);
122 122 ph_data = ph_impl->usba_ph_data;
123 123 mutex_exit(&ph_impl->usba_ph_mutex);
124 124 }
125 125
126 126 return (ph_data);
127 127 }
128 128
129 129
130 130 usb_pipe_handle_t
131 131 usba_get_pipe_handle(usba_pipe_handle_data_t *ph_data)
132 132 {
133 133 usb_pipe_handle_t ph = NULL;
134 134
135 135 if (ph_data) {
136 136 mutex_enter(&ph_data->p_mutex);
137 137 ASSERT(ph_data->p_req_count >= 0);
138 138 ph = (usb_pipe_handle_t)ph_data->p_ph_impl;
139 139 mutex_exit(&ph_data->p_mutex);
140 140 }
141 141
142 142 return (ph);
143 143 }
144 144
145 145
146 146 /*
147 147 * opaque to pipe handle impl translation with incr of ref count. The caller
148 148 * must release ph_data when done. Increment the ref count ensures that
149 149 * the ph_data will not be freed underneath us.
150 150 */
151 151 usba_pipe_handle_data_t *
152 152 usba_hold_ph_data(usb_pipe_handle_t pipe_handle)
153 153 {
154 154 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle;
155 155 usba_pipe_handle_data_t *ph_data = NULL;
156 156
157 157 if (ph_impl) {
158 158 mutex_enter(&ph_impl->usba_ph_mutex);
159 159
160 160 switch (ph_impl->usba_ph_state) {
161 161 case USB_PIPE_STATE_IDLE:
162 162 case USB_PIPE_STATE_ACTIVE:
163 163 case USB_PIPE_STATE_ERROR:
164 164 ph_data = ph_impl->usba_ph_data;
165 165 ph_impl->usba_ph_ref_count++;
166 166 break;
167 167 case USB_PIPE_STATE_CLOSED:
168 168 case USB_PIPE_STATE_CLOSING:
169 169 default:
170 170 break;
171 171 }
172 172
173 173 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
174 174 "usba_hold_ph_data: ph_impl=0x%p state=%d ref=%d",
175 175 (void *)ph_impl, ph_impl->usba_ph_state,
176 176 ph_impl->usba_ph_ref_count);
177 177
178 178 mutex_exit(&ph_impl->usba_ph_mutex);
179 179 }
180 180
181 181 return (ph_data);
182 182 }
183 183
184 184
185 185 void
186 186 usba_release_ph_data(usba_ph_impl_t *ph_impl)
187 187 {
188 188 if (ph_impl) {
189 189 mutex_enter(&ph_impl->usba_ph_mutex);
190 190
191 191 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
192 192 "usba_release_ph_data: "
193 193 "ph_impl=0x%p state=%d ref=%d",
194 194 (void *)ph_impl, ph_impl->usba_ph_state,
195 195 ph_impl->usba_ph_ref_count);
196 196
197 197 #ifndef __lock_lint
198 198 if (ph_impl->usba_ph_data) {
199 199 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
200 200 "usba_release_ph_data: req_count=%d",
201 201 ph_impl->usba_ph_data->p_req_count);
202 202 ASSERT(ph_impl->usba_ph_data->p_req_count >= 0);
203 203 }
204 204 #endif
205 205 ph_impl->usba_ph_ref_count--;
206 206 ASSERT(ph_impl->usba_ph_ref_count >= 0);
207 207
208 208 mutex_exit(&ph_impl->usba_ph_mutex);
209 209 }
210 210 }
211 211
212 212
213 213 /*
214 214 * get pipe state from ph_data
215 215 */
216 216 usb_pipe_state_t
217 217 usba_get_ph_state(usba_pipe_handle_data_t *ph_data)
218 218 {
219 219 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl;
220 220 usb_pipe_state_t pipe_state;
221 221
222 222 ASSERT(mutex_owned(&ph_data->p_mutex));
223 223 mutex_enter(&ph_impl->usba_ph_mutex);
224 224 pipe_state = ph_impl->usba_ph_state;
225 225 mutex_exit(&ph_impl->usba_ph_mutex);
226 226
227 227 return (pipe_state);
228 228 }
229 229
230 230
231 231 /*
232 232 * get ref_count from ph_data
233 233 */
234 234 int
235 235 usba_get_ph_ref_count(usba_pipe_handle_data_t *ph_data)
236 236 {
237 237 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl;
238 238 int ref_count;
239 239
240 240 mutex_enter(&ph_impl->usba_ph_mutex);
241 241 ref_count = ph_impl->usba_ph_ref_count;
242 242 mutex_exit(&ph_impl->usba_ph_mutex);
243 243
244 244 return (ref_count);
245 245 }
246 246
247 247
248 248 /*
249 249 * new pipe state
250 250 * We need to hold both pipe mutex and ph_impl mutex
251 251 */
252 252 void
253 253 usba_pipe_new_state(usba_pipe_handle_data_t *ph_data, usb_pipe_state_t state)
254 254 {
255 255 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl;
256 256
257 257 ASSERT(mutex_owned(&ph_data->p_mutex));
258 258
259 259 mutex_enter(&ph_impl->usba_ph_mutex);
260 260 ASSERT(ph_data->p_req_count >= 0);
261 261 ASSERT(ph_impl->usba_ph_ref_count >= 0);
262 262
263 263 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
264 264 "usba_pipe_new_state: "
265 265 "ph_data=0x%p old=%s new=%s ref=%d req=%d",
266 266 (void *)ph_data, usb_str_pipe_state(ph_impl->usba_ph_state),
267 267 usb_str_pipe_state(state),
268 268 ph_impl->usba_ph_ref_count, ph_data->p_req_count);
269 269
270 270 switch (ph_impl->usba_ph_state) {
271 271 case USB_PIPE_STATE_IDLE:
272 272 case USB_PIPE_STATE_ACTIVE:
273 273 case USB_PIPE_STATE_ERROR:
274 274 case USB_PIPE_STATE_CLOSED:
275 275 ph_impl->usba_ph_state = state;
276 276 break;
277 277 case USB_PIPE_STATE_CLOSING:
278 278 default:
279 279 break;
280 280 }
281 281 mutex_exit(&ph_impl->usba_ph_mutex);
282 282 }
283 283
284 284
285 285 /*
286 286 * async function execution support
287 287 * Arguments:
288 288 * dip - devinfo pointer
289 289 * sync_func - function to be executed
290 290 * ph_impl - impl pipehandle
291 291 * arg - opaque arg
292 292 * usb_flags - none
293 293 * callback - function to be called on completion, may be NULL
294 294 * callback_arg - argument for callback function
295 295 *
296 296 * Note: The caller must do a hold on ph_data
297 297 * We sleep for memory resources and taskq_dispatch which will ensure
298 298 * that this function succeeds
299 299 */
300 300 int
301 301 usba_pipe_setup_func_call(
302 302 dev_info_t *dip,
303 303 int (*sync_func)(dev_info_t *,
304 304 usba_ph_impl_t *, usba_pipe_async_req_t *,
305 305 usb_flags_t),
306 306 usba_ph_impl_t *ph_impl,
307 307 usb_opaque_t arg,
308 308 usb_flags_t usb_flags,
309 309 void (*callback)(usb_pipe_handle_t,
310 310 usb_opaque_t, int, usb_cb_flags_t),
311 311 usb_opaque_t callback_arg)
312 312 {
313 313 usba_pipe_async_req_t *request;
314 314 usb_pipe_handle_t pipe_handle = (usb_pipe_handle_t)ph_impl;
315 315 usba_pipe_handle_data_t *ph_data = ph_impl->usba_ph_data;
316 316 int rval = USB_SUCCESS;
317 317 usb_cb_flags_t callback_flags;
318 318
319 319 USB_DPRINTF_L3(DPRINT_MASK_USBAI, usbai_log_handle,
320 320 "usba_pipe_setup_func_call: ph_impl=0x%p, func=0x%p",
321 321 (void *)ph_impl, (void *)sync_func);
322 322
323 323 if (((usb_flags & USB_FLAGS_SLEEP) == 0) && (callback == NULL)) {
324 324 usba_release_ph_data(ph_impl);
325 325 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
326 326 "usba_pipe_setup_func_call: async request with "
327 327 "no callback");
328 328
329 329 return (USB_INVALID_ARGS);
330 330 }
331 331
332 332 request = kmem_zalloc(sizeof (usba_pipe_async_req_t), KM_SLEEP);
333 333 request->dip = dip;
334 334 request->ph_impl = ph_impl;
335 335 request->arg = arg;
336 336
337 337 /*
338 338 * OR in sleep flag. regardless of calling sync_func directly
339 339 * or in a new thread, we will always wait for completion
340 340 */
341 341 request->usb_flags = usb_flags | USB_FLAGS_SLEEP;
342 342 request->sync_func = sync_func;
343 343 request->callback = callback;
344 344 request->callback_arg = callback_arg;
345 345
346 346 if (usb_flags & USB_FLAGS_SLEEP) {
347 347 rval = sync_func(dip, ph_impl, request, usb_flags);
348 348 kmem_free(request, sizeof (usba_pipe_async_req_t));
349 349
350 350 } else if (usba_async_ph_req(ph_data,
351 351 usba_pipe_do_async_func_thread,
352 352 (void *)request, USB_FLAGS_SLEEP) != USB_SUCCESS) {
353 353 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
354 354 "usb_async_req failed: ph_impl=0x%p, func=0x%p",
355 355 (void *)ph_impl, (void *)sync_func);
356 356
357 357 if (callback) {
358 358 callback_flags =
359 359 usba_check_intr_context(USB_CB_ASYNC_REQ_FAILED);
360 360 callback(pipe_handle, callback_arg, USB_FAILURE,
361 361 callback_flags);
362 362 }
363 363
364 364 kmem_free(request, sizeof (usba_pipe_async_req_t));
365 365 usba_release_ph_data(ph_impl);
366 366 }
367 367
368 368 return (rval);
369 369 }
370 370
371 371
372 372 /*
373 373 * taskq thread function to execute function synchronously
374 374 * Note: caller must have done a hold on ph_data
375 375 */
376 376 static void
377 377 usba_pipe_do_async_func_thread(void *arg)
378 378 {
379 379 usba_pipe_async_req_t *request = (usba_pipe_async_req_t *)arg;
380 380 usba_ph_impl_t *ph_impl = request->ph_impl;
381 381 usb_pipe_handle_t pipe_handle = (usb_pipe_handle_t)ph_impl;
382 382 int rval;
383 383 usb_cb_flags_t cb_flags = USB_CB_NO_INFO;
384 384
385 385 if ((rval = request->sync_func(request->dip, ph_impl,
386 386 request, request->usb_flags | USB_FLAGS_SLEEP)) !=
387 387 USB_SUCCESS) {
388 388 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
389 389 "sync func failed (%d)", rval);
390 390 }
391 391
392 392 if (request->callback) {
393 393 request->callback(pipe_handle, request->callback_arg, rval,
394 394 cb_flags);
395 395 }
396 396
397 397 kmem_free(request, sizeof (usba_pipe_async_req_t));
398 398 }
399 399
400 400
401 401 /*
402 402 * default endpoint descriptor and pipe policy
403 403 */
404 404 usb_ep_descr_t usba_default_ep_descr =
405 405 {7, 5, 0, USB_EP_ATTR_CONTROL, 8, 0};
406 406
407 407 /* set some meaningful defaults */
408 408 static usb_pipe_policy_t usba_default_ep_pipe_policy = {3};
409 409
410 410
411 411 /*
412 412 * usb_get_ep_index: create an index from endpoint address that can
413 413 * be used to index into endpoint pipe lists
414 414 */
415 415 uchar_t
416 416 usb_get_ep_index(uint8_t ep_addr)
417 417 {
418 418 return ((ep_addr & USB_EP_NUM_MASK) +
419 419 ((ep_addr & USB_EP_DIR_MASK) ? 16 : 0));
420 420 }
421 421
422 422
423 423 /*
424 424 * pipe management
425 425 * utility functions to init and destroy a pipehandle
426 426 */
427 427 static int
428 428 usba_init_pipe_handle(dev_info_t *dip,
429 429 usba_device_t *usba_device,
430 430 usb_ep_descr_t *ep,
431 431 usb_pipe_policy_t *pipe_policy,
432 432 usba_ph_impl_t *ph_impl)
433 433 {
434 434 int instance = ddi_get_instance(dip);
435 435 unsigned int def_instance = instance;
436 436 static unsigned int anon_instance = 0;
437 437 char tq_name[TASKQ_NAMELEN];
438 438
439 439 usba_pipe_handle_data_t *ph_data = ph_impl->usba_ph_data;
440 440 ddi_iblock_cookie_t iblock_cookie =
441 441 usba_hcdi_get_hcdi(usba_device->usb_root_hub_dip)->
442 442 hcdi_iblock_cookie;
443 443
444 444 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
445 445 "usba_init_pipe_handle: "
446 446 "usba_device=0x%p ep=0x%x", (void *)usba_device,
447 447 ep->bEndpointAddress);
448 448 mutex_init(&ph_data->p_mutex, NULL, MUTEX_DRIVER, iblock_cookie);
449 449
450 450 /* just to keep warlock happy, there is no contention yet */
↓ open down ↓ |
450 lines elided |
↑ open up ↑ |
451 451 mutex_enter(&ph_data->p_mutex);
452 452 mutex_enter(&usba_device->usb_mutex);
453 453
454 454 ASSERT(pipe_policy->pp_max_async_reqs);
455 455
456 456 if (instance != -1) {
457 457 (void) snprintf(tq_name, sizeof (tq_name),
458 458 "USB_%s_%x_pipehndl_tq_%d",
459 459 ddi_driver_name(dip), ep->bEndpointAddress, instance);
460 460 } else {
461 - def_instance = atomic_add_32_nv(&anon_instance, 1);
461 + def_instance = atomic_inc_32_nv(&anon_instance);
462 462
463 463 (void) snprintf(tq_name, sizeof (tq_name),
464 464 "USB_%s_%x_pipehndl_tq_%d_",
465 465 ddi_driver_name(dip), ep->bEndpointAddress, def_instance);
466 466 }
467 467
468 468 ph_data->p_taskq = taskq_create(tq_name,
469 469 pipe_policy->pp_max_async_reqs + 1,
470 470 ((ep->bmAttributes & USB_EP_ATTR_MASK) ==
471 471 USB_EP_ATTR_ISOCH) ?
472 472 (maxclsyspri - 5) : minclsyspri,
473 473 2 * (pipe_policy->pp_max_async_reqs + 1),
474 474 8 * (pipe_policy->pp_max_async_reqs + 1),
475 475 TASKQ_PREPOPULATE);
476 476
477 477 /*
478 478 * Create a shared taskq.
479 479 */
480 480 if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
481 481 int iface = usb_get_if_number(dip);
482 482 if (iface < 0) {
483 483 /* we own the device, use first entry */
484 484 iface = 0;
485 485 }
486 486
487 487 if (instance != -1) {
488 488 (void) snprintf(tq_name, sizeof (tq_name),
489 489 "USB_%s_%x_shared_tq_%d",
490 490 ddi_driver_name(dip), ep->bEndpointAddress,
491 491 instance);
492 492 } else {
493 493 (void) snprintf(tq_name, sizeof (tq_name),
494 494 "USB_%s_%x_shared_tq_%d_",
495 495 ddi_driver_name(dip), ep->bEndpointAddress,
496 496 def_instance);
497 497 }
498 498
499 499 if (usba_device->usb_shared_taskq_ref_count[iface] == 0) {
500 500 usba_device->usb_shared_taskq[iface] =
501 501 taskq_create(tq_name,
502 502 1, /* Number threads. */
503 503 maxclsyspri - 5, /* Priority */
504 504 1, /* minalloc */
505 505 USBA_N_ENDPOINTS + 4, /* maxalloc */
506 506 TASKQ_PREPOPULATE);
507 507 ASSERT(usba_device->usb_shared_taskq[iface] != NULL);
508 508 }
509 509 usba_device->usb_shared_taskq_ref_count[iface]++;
510 510 }
511 511
512 512 ph_data->p_dip = dip;
513 513 ph_data->p_usba_device = usba_device;
514 514 ph_data->p_ep = *ep;
515 515 ph_data->p_ph_impl = ph_impl;
516 516 if ((ep->bmAttributes & USB_EP_ATTR_MASK) ==
517 517 USB_EP_ATTR_ISOCH) {
518 518 ph_data->p_spec_flag |= USBA_PH_FLAG_USE_SOFT_INTR;
519 519 }
520 520
521 521 /* fix up the MaxPacketSize if it is the default endpoint descr */
522 522 if ((ep == &usba_default_ep_descr) && usba_device) {
523 523 uint16_t maxpktsize;
524 524
525 525 maxpktsize = usba_device->usb_dev_descr->bMaxPacketSize0;
526 526 if (usba_device->usb_is_wireless) {
527 527 /*
528 528 * according to wusb 1.0 spec 4.8.1, the host must
529 529 * assume a wMaxPacketSize of 512 for the default
530 530 * control pipe of a wusb device
531 531 */
532 532 maxpktsize = 0x200;
533 533 }
534 534 USB_DPRINTF_L3(DPRINT_MASK_USBAI, usbai_log_handle,
535 535 "adjusting max packet size from %d to %d",
536 536 ph_data->p_ep.wMaxPacketSize, maxpktsize);
537 537
538 538 ph_data->p_ep.wMaxPacketSize = maxpktsize;
539 539 }
540 540
541 541 /* now update usba_ph_impl structure */
542 542 mutex_enter(&ph_impl->usba_ph_mutex);
543 543 ph_impl->usba_ph_dip = dip;
544 544 ph_impl->usba_ph_ep = ph_data->p_ep;
545 545 ph_impl->usba_ph_policy = ph_data->p_policy = *pipe_policy;
546 546 mutex_exit(&ph_impl->usba_ph_mutex);
547 547
548 548 usba_init_list(&ph_data->p_queue, (usb_opaque_t)ph_data, iblock_cookie);
549 549 usba_init_list(&ph_data->p_cb_queue, (usb_opaque_t)ph_data,
550 550 iblock_cookie);
551 551 mutex_exit(&usba_device->usb_mutex);
552 552 mutex_exit(&ph_data->p_mutex);
553 553
554 554 return (USB_SUCCESS);
555 555 }
556 556
557 557
558 558 static void
559 559 usba_taskq_destroy(void *arg)
560 560 {
561 561 taskq_destroy((taskq_t *)arg);
562 562 }
563 563
564 564
565 565 static void
566 566 usba_destroy_pipe_handle(usba_pipe_handle_data_t *ph_data)
567 567 {
568 568 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl;
569 569 int timeout;
570 570 usba_device_t *usba_device;
571 571
572 572 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
573 573 "usba_destroy_pipe_handle: ph_data=0x%p", (void *)ph_data);
574 574
575 575 mutex_enter(&ph_data->p_mutex);
576 576 mutex_enter(&ph_impl->usba_ph_mutex);
577 577
578 578 /* check for all activity to drain */
579 579 for (timeout = 0; timeout < usba_drain_timeout; timeout++) {
580 580 if ((ph_impl->usba_ph_ref_count <= 1) &&
581 581 (ph_data->p_req_count == 0)) {
582 582
583 583 break;
584 584 }
585 585 mutex_exit(&ph_data->p_mutex);
586 586 mutex_exit(&ph_impl->usba_ph_mutex);
587 587 delay(drv_usectohz(1000));
588 588 mutex_enter(&ph_data->p_mutex);
589 589 mutex_enter(&ph_impl->usba_ph_mutex);
590 590 }
591 591
592 592 /*
593 593 * set state to closed here so any other thread
594 594 * that is waiting for the CLOSED state will
595 595 * continue. Otherwise, taskq_destroy might deadlock
596 596 */
597 597 ph_impl->usba_ph_data = NULL;
598 598 ph_impl->usba_ph_ref_count = 0;
599 599 ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSED;
600 600
601 601 if (ph_data->p_taskq) {
602 602 mutex_exit(&ph_data->p_mutex);
603 603 mutex_exit(&ph_impl->usba_ph_mutex);
604 604 if (taskq_member(ph_data->p_taskq, curthread)) {
605 605 /*
606 606 * use system taskq to destroy ph's taskq to avoid
607 607 * deadlock
608 608 */
609 609 (void) taskq_dispatch(system_taskq,
610 610 usba_taskq_destroy, ph_data->p_taskq, TQ_SLEEP);
611 611 } else {
612 612 taskq_destroy(ph_data->p_taskq);
613 613 }
614 614 } else {
615 615 mutex_exit(&ph_data->p_mutex);
616 616 mutex_exit(&ph_impl->usba_ph_mutex);
617 617 }
618 618
619 619 usba_device = ph_data->p_usba_device;
620 620 mutex_enter(&ph_data->p_mutex);
621 621 if (ph_data->p_spec_flag & USBA_PH_FLAG_TQ_SHARE) {
622 622 int iface = usb_get_if_number(ph_data->p_dip);
623 623 if (iface < 0) {
624 624 /* we own the device, use the first entry */
625 625 iface = 0;
626 626 }
627 627 mutex_enter(&usba_device->usb_mutex);
628 628 if (--usba_device->usb_shared_taskq_ref_count[iface] == 0) {
629 629 ph_data->p_spec_flag &= ~USBA_PH_FLAG_TQ_SHARE;
630 630 if (taskq_member(usba_device->usb_shared_taskq[iface],
631 631 curthread)) {
632 632 (void) taskq_dispatch(
633 633 system_taskq,
634 634 usba_taskq_destroy,
635 635 usba_device->usb_shared_taskq[iface],
636 636 TQ_SLEEP);
637 637 } else {
638 638 taskq_destroy(
639 639 usba_device->usb_shared_taskq[iface]);
640 640 }
641 641 }
642 642 mutex_exit(&usba_device->usb_mutex);
643 643 }
644 644 mutex_exit(&ph_data->p_mutex);
645 645
646 646
647 647 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
648 648 "usba_destroy_pipe_handle: destroying ph_data=0x%p",
649 649 (void *)ph_data);
650 650
651 651 usba_destroy_list(&ph_data->p_queue);
652 652 usba_destroy_list(&ph_data->p_cb_queue);
653 653
654 654 /* destroy mutexes */
655 655 mutex_destroy(&ph_data->p_mutex);
656 656
657 657 kmem_free(ph_data, sizeof (usba_pipe_handle_data_t));
658 658 }
659 659
660 660
661 661 /*
662 662 * usba_drain_cbs:
663 663 * Drain the request callbacks on the pipe handle
664 664 */
665 665 int
666 666 usba_drain_cbs(usba_pipe_handle_data_t *ph_data, usb_cb_flags_t cb_flags,
667 667 usb_cr_t cr)
668 668 {
669 669 usba_req_wrapper_t *req_wrp;
670 670 int flush_requests = 1;
671 671 usba_ph_impl_t *ph_impl = ph_data->p_ph_impl;
672 672 int timeout;
673 673 int rval = USB_SUCCESS;
674 674
675 675 ASSERT(mutex_owned(&ph_data->p_mutex));
676 676
677 677 mutex_enter(&ph_impl->usba_ph_mutex);
678 678 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
679 679 "usba_drain_cbs: ph_data=0x%p ref=%d req=%d cb=0x%x cr=%d",
680 680 (void *)ph_data, ph_impl->usba_ph_ref_count, ph_data->p_req_count,
681 681 cb_flags, cr);
682 682 ASSERT(ph_data->p_req_count >= 0);
683 683 mutex_exit(&ph_impl->usba_ph_mutex);
684 684
685 685 if (ph_data->p_dip) {
686 686 if (USBA_IS_DEFAULT_PIPE(ph_data)) {
687 687 USB_DPRINTF_L4(DPRINT_MASK_USBAI,
688 688 usbai_log_handle,
689 689 "no flushing on default pipe!");
690 690
691 691 flush_requests = 0;
692 692 }
693 693 }
694 694
695 695 if (flush_requests) {
696 696 /* flush all requests in the pipehandle queue */
697 697 while ((req_wrp = (usba_req_wrapper_t *)
698 698 usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) {
699 699 mutex_exit(&ph_data->p_mutex);
700 700 usba_do_req_exc_cb(req_wrp, cr, cb_flags);
701 701 mutex_enter(&ph_data->p_mutex);
702 702 }
703 703 }
704 704
705 705 /*
706 706 * wait for any callbacks in progress but don't wait for
707 707 * for queued requests on the default pipe
708 708 */
709 709 for (timeout = 0; (timeout < usba_drain_timeout) &&
710 710 (ph_data->p_req_count >
711 711 usba_list_entry_count(&ph_data->p_queue));
712 712 timeout++) {
713 713 mutex_exit(&ph_data->p_mutex);
714 714 delay(drv_usectohz(1000));
715 715 mutex_enter(&ph_data->p_mutex);
716 716 }
717 717
718 718 mutex_enter(&ph_impl->usba_ph_mutex);
719 719 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
720 720 "usba_drain_cbs done: ph_data=0x%p ref=%d req=%d",
721 721 (void *)ph_data, ph_impl->usba_ph_ref_count, ph_data->p_req_count);
722 722 mutex_exit(&ph_impl->usba_ph_mutex);
723 723
724 724 if (timeout == usba_drain_timeout) {
725 725 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
726 726 "draining callbacks timed out!");
727 727
728 728 rval = USB_FAILURE;
729 729 }
730 730
731 731 return (rval);
732 732 }
733 733
734 734
735 735 /*
736 736 * usb_pipe_open():
737 737 *
738 738 * Before using any pipe including the default pipe, it should be opened
739 739 * using usb_pipe_open(). On a successful open, a pipe handle is returned
740 740 * for use in other usb_pipe_*() functions
741 741 *
742 742 * The default pipe can only be opened by the hub driver
743 743 *
744 744 * The bandwidth has been allocated and guaranteed on successful
745 745 * opening of an isoc/intr pipes.
746 746 *
747 747 * Only the default pipe can be shared. all other control pipes
748 748 * are excusively opened by default.
749 749 * A pipe policy and endpoint descriptor must always be provided
750 750 * except for default pipe
751 751 *
752 752 * Arguments:
753 753 * dip - devinfo ptr
754 754 * ep - endpoint descriptor pointer
755 755 * pipe_policy - pointer to pipe policy which provides hints on how
756 756 * the pipe will be used.
757 757 * flags - USB_FLAGS_SLEEP wait for resources
758 758 * to become available
759 759 * pipe_handle - a pipe handle pointer. On a successful open,
760 760 * a pipe_handle is returned in this pointer.
761 761 *
762 762 * Return values:
763 763 * USB_SUCCESS - open succeeded
764 764 * USB_FAILURE - unspecified open failure or pipe is already open
765 765 * USB_NO_RESOURCES - no resources were available to complete the open
766 766 * USB_NO_BANDWIDTH - no bandwidth available (isoc/intr pipes)
767 767 * USB_* - refer to usbai.h
768 768 */
769 769 int
770 770 usb_pipe_open(
771 771 dev_info_t *dip,
772 772 usb_ep_descr_t *ep,
773 773 usb_pipe_policy_t *pipe_policy,
774 774 usb_flags_t usb_flags,
775 775 usb_pipe_handle_t *pipe_handle)
776 776 {
777 777 usba_device_t *usba_device;
778 778 int rval;
779 779 usba_pipe_handle_data_t *ph_data;
780 780 usba_ph_impl_t *ph_impl;
781 781 uchar_t ep_index;
782 782 int kmflag;
783 783 size_t size;
784 784
785 785 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
786 786 "usb_pipe_open:\n\t"
787 787 "dip=0x%p ep=0x%p pp=0x%p uf=0x%x ph=0x%p",
788 788 (void *)dip, (void *)ep, (void *)pipe_policy, usb_flags,
789 789 (void *)pipe_handle);
790 790
791 791 if ((dip == NULL) || (pipe_handle == NULL)) {
792 792
793 793 return (USB_INVALID_ARGS);
794 794 }
795 795
796 796 if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
797 797
798 798 return (USB_INVALID_CONTEXT);
799 799 }
800 800 usba_device = usba_get_usba_device(dip);
801 801
802 802 if ((ep != NULL) && (pipe_policy == NULL)) {
803 803 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
804 804 "usb_pipe_open: null pipe policy");
805 805
806 806 return (USB_INVALID_ARGS);
807 807 }
808 808
809 809 /* is the device still connected? */
810 810 if ((ep != NULL) & DEVI_IS_DEVICE_REMOVED(dip)) {
811 811 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
812 812 "usb_pipe_open: device has been removed");
813 813
814 814 return (USB_FAILURE);
815 815 }
816 816
817 817
818 818 /*
819 819 * if a null endpoint pointer was passed, use the default
820 820 * endpoint descriptor
821 821 */
822 822 if (ep == NULL) {
823 823 if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
824 824 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
825 825 "usb_pipe_open: not allowed to open def pipe");
826 826
827 827 return (USB_INVALID_PERM);
828 828 }
829 829
830 830 ep = &usba_default_ep_descr;
831 831 pipe_policy = &usba_default_ep_pipe_policy;
832 832 }
833 833
834 834 if (usb_flags & USB_FLAGS_SERIALIZED_CB) {
835 835 if (((ep->bmAttributes & USB_EP_ATTR_MASK) ==
836 836 USB_EP_ATTR_CONTROL) ||
837 837 ((ep->bmAttributes & USB_EP_ATTR_MASK) ==
838 838 USB_EP_ATTR_ISOCH)) {
839 839 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
840 840 "usb_pipe_open: shared taskq not allowed with "
841 841 "ctrl or isoch pipe");
842 842
843 843 return (USB_INVALID_ARGS);
844 844 }
845 845 }
846 846
847 847 kmflag = (usb_flags & USB_FLAGS_SLEEP) ? KM_SLEEP : KM_NOSLEEP;
848 848 size = sizeof (usba_pipe_handle_data_t);
849 849
850 850 if ((ph_data = kmem_zalloc(size, kmflag)) == NULL) {
851 851
852 852 return (USB_NO_RESOURCES);
853 853 }
854 854
855 855 /* check if pipe is already open and if so fail */
856 856 ep_index = usb_get_ep_index(ep->bEndpointAddress);
857 857 ph_impl = &usba_device->usb_ph_list[ep_index];
858 858
859 859 mutex_enter(&usba_device->usb_mutex);
860 860 mutex_enter(&ph_impl->usba_ph_mutex);
861 861
862 862 if (ph_impl->usba_ph_data) {
863 863 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
864 864 "usb_pipe_open: pipe to ep %d already open", ep_index);
865 865 mutex_exit(&ph_impl->usba_ph_mutex);
866 866 mutex_exit(&usba_device->usb_mutex);
867 867 kmem_free(ph_data, size);
868 868
869 869 return (USB_BUSY);
870 870 }
871 871
872 872 ph_impl->usba_ph_data = ph_data;
873 873
874 874 mutex_exit(&ph_impl->usba_ph_mutex);
875 875 mutex_exit(&usba_device->usb_mutex);
876 876
877 877 if (usb_flags & USB_FLAGS_SERIALIZED_CB) {
878 878 mutex_enter(&ph_data->p_mutex);
879 879 ph_data->p_spec_flag |= USBA_PH_FLAG_TQ_SHARE;
880 880 mutex_exit(&ph_data->p_mutex);
881 881 }
882 882
883 883 /*
884 884 * allocate and initialize the pipe handle
885 885 */
886 886 if ((rval = usba_init_pipe_handle(dip, usba_device,
887 887 ep, pipe_policy, ph_impl)) != USB_SUCCESS) {
888 888 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
889 889 "usb_pipe_open: pipe init failed (%d)", rval);
890 890
891 891 return (rval);
892 892 }
893 893 ph_data = ph_impl->usba_ph_data;
894 894
895 895 /*
896 896 * ask the hcd to open the pipe
897 897 */
898 898 if ((rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_open(ph_data,
899 899 usb_flags)) != USB_SUCCESS) {
900 900 usba_destroy_pipe_handle(ph_data);
901 901
902 902 *pipe_handle = NULL;
903 903 } else {
904 904 *pipe_handle = (usb_pipe_handle_t)ph_impl;
905 905
906 906 /* set the pipe state after a successful hcd open */
907 907 mutex_enter(&ph_data->p_mutex);
908 908 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
909 909 mutex_exit(&ph_data->p_mutex);
910 910 }
911 911
912 912 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
913 913 "usb_pipe_open: ph_impl=0x%p (0x%p)",
914 914 (void *)ph_impl, (void *)ph_data);
915 915
916 916 return (rval);
917 917 }
918 918
919 919
920 920 /*
921 921 * usb_pipe_close/sync_close:
922 922 *
923 923 * Close a pipe and release all resources and free the pipe_handle.
924 924 * Automatic polling, if active, will be terminated
925 925 *
926 926 * Arguments:
927 927 * dip - devinfo ptr
928 928 * pipehandle - pointer to pipehandle. The pipehandle will be
929 929 * zeroed on successful completion
930 930 * flags - USB_FLAGS_SLEEP:
931 931 * wait for resources, pipe
932 932 * to become free, all callbacks completed
933 933 * callback - If USB_FLAGS_SLEEP has not been specified, a
934 934 * callback will be performed.
935 935 * callback_arg - the first argument of the callback. Note that
936 936 * the pipehandle will be zeroed and not passed
937 937 *
938 938 * Notes:
939 939 * Pipe close will always succeed regardless whether USB_FLAGS_SLEEP has been
940 940 * specified or not.
941 941 * An async close will always succeed if the hint in the pipe policy
942 942 * has been correct about the max number of async taskq requests required.
943 943 * If there are really no resources, the pipe handle will be linked into
944 944 * a garbage pipe list and periodically checked by USBA until it can be
945 945 * closed. This may cause a hang in the detach of the driver.
946 946 * USBA will prevent the client from submitting more requests to a pipe
947 947 * that is being closed
948 948 * Subsequent usb_pipe_close() requests on the same pipe to USBA will
949 949 * wait for the previous close(s) to finish.
950 950 *
951 951 * Note that once we start closing a pipe, we cannot go back anymore
952 952 * to a normal pipe state
953 953 */
954 954 void
955 955 usb_pipe_close(dev_info_t *dip,
956 956 usb_pipe_handle_t pipe_handle,
957 957 usb_flags_t usb_flags,
958 958 void (*callback)(
959 959 usb_pipe_handle_t pipe_handle,
960 960 usb_opaque_t arg,
961 961 int rval,
962 962 usb_cb_flags_t flags),
963 963 usb_opaque_t callback_arg)
964 964 {
965 965 usba_pipe_handle_data_t *ph_data;
966 966 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle;
967 967 usb_cb_flags_t callback_flags;
968 968
969 969 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
970 970 "usb_pipe_close: ph=0x%p", (void *)pipe_handle);
971 971
972 972 callback_flags = usba_check_intr_context(USB_CB_NO_INFO);
973 973 if ((dip == NULL) || (pipe_handle == NULL)) {
974 974 if (callback) {
975 975 callback(pipe_handle, callback_arg,
976 976 USB_INVALID_ARGS, callback_flags);
977 977 } else {
978 978 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
979 979 usbai_log_handle,
980 980 "usb_pipe_close: invalid arguments");
981 981 }
982 982
983 983 return;
984 984 }
985 985
986 986 if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
987 987 /*
988 988 * It is the client driver doing the pipe close,
989 989 * the pipe is no longer persistent then.
990 990 */
991 991 mutex_enter(&ph_impl->usba_ph_mutex);
992 992 ph_impl->usba_ph_flags &= ~USBA_PH_DATA_PERSISTENT;
993 993 mutex_exit(&ph_impl->usba_ph_mutex);
994 994 }
995 995
996 996 if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
997 997 if (callback) {
998 998 callback(pipe_handle, callback_arg,
999 999 USB_INVALID_CONTEXT, callback_flags);
1000 1000 } else {
1001 1001 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1002 1002 usbai_log_handle,
1003 1003 "usb_pipe_close: invalid context");
1004 1004 }
1005 1005
1006 1006 return;
1007 1007 }
1008 1008
1009 1009 if ((ph_data = usba_hold_ph_data(pipe_handle)) == NULL) {
1010 1010
1011 1011 /* hold pipehandle anyways since we will decrement later */
1012 1012 mutex_enter(&ph_impl->usba_ph_mutex);
1013 1013 ph_impl->usba_ph_ref_count++;
1014 1014 mutex_exit(&ph_impl->usba_ph_mutex);
1015 1015
1016 1016 (void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close,
1017 1017 ph_impl, NULL, usb_flags, callback, callback_arg);
1018 1018
1019 1019 return;
1020 1020 }
1021 1021
1022 1022 mutex_enter(&ph_data->p_mutex);
1023 1023
1024 1024 if (USBA_IS_DEFAULT_PIPE(ph_data) &&
1025 1025 ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0)) {
1026 1026 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1027 1027 "usb_pipe_close: not allowed to close def pipe");
1028 1028 mutex_exit(&ph_data->p_mutex);
1029 1029
1030 1030 usba_release_ph_data(ph_impl);
1031 1031
1032 1032 if (callback) {
1033 1033 callback(pipe_handle, callback_arg,
1034 1034 USB_INVALID_PIPE, callback_flags);
1035 1035 } else {
1036 1036 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1037 1037 usbai_log_handle,
1038 1038 "usb_pipe_close: invalid pipe");
1039 1039 }
1040 1040
1041 1041 return;
1042 1042 }
1043 1043
1044 1044 mutex_exit(&ph_data->p_mutex);
1045 1045
1046 1046 (void) usba_pipe_setup_func_call(dip, usba_pipe_sync_close,
1047 1047 ph_impl, NULL, usb_flags, callback, callback_arg);
1048 1048 }
1049 1049
1050 1050
1051 1051 /*ARGSUSED*/
1052 1052 static int
1053 1053 usba_pipe_sync_close(dev_info_t *dip, usba_ph_impl_t *ph_impl,
1054 1054 usba_pipe_async_req_t *request, usb_flags_t usb_flags)
1055 1055 {
1056 1056 usba_device_t *usba_device;
1057 1057 usba_pipe_handle_data_t *ph_data = usba_get_ph_data(
1058 1058 (usb_pipe_handle_t)ph_impl);
1059 1059 int attribute;
1060 1060 uchar_t dir;
1061 1061 int timeout;
1062 1062
1063 1063 if (ph_impl == NULL) {
1064 1064
1065 1065 return (USB_SUCCESS);
1066 1066 }
1067 1067
1068 1068 mutex_enter(&ph_impl->usba_ph_mutex);
1069 1069 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1070 1070 "usba_pipe_sync_close: dip=0x%p ph_data=0x%p state=%d ref=%d",
1071 1071 (void *)dip, (void *)ph_data, ph_impl->usba_ph_state,
1072 1072 ph_impl->usba_ph_ref_count);
1073 1073
1074 1074 /*
1075 1075 * if another thread opens the pipe again, this loop could
1076 1076 * be truly forever
1077 1077 */
1078 1078 if ((ph_data == NULL) ||
1079 1079 (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSING) ||
1080 1080 (ph_impl->usba_ph_state == USB_PIPE_STATE_CLOSED)) {
1081 1081 /* wait forever till really closed */
1082 1082 mutex_exit(&ph_impl->usba_ph_mutex);
1083 1083 usba_release_ph_data(ph_impl);
1084 1084
1085 1085 while (usba_get_ph_data((usb_pipe_handle_t)ph_impl)) {
1086 1086 delay(1);
1087 1087 }
1088 1088
1089 1089 return (USB_SUCCESS);
1090 1090 }
1091 1091 ph_impl->usba_ph_state = USB_PIPE_STATE_CLOSING;
1092 1092 mutex_exit(&ph_impl->usba_ph_mutex);
1093 1093
1094 1094 mutex_enter(&ph_data->p_mutex);
1095 1095 mutex_enter(&ph_impl->usba_ph_mutex);
1096 1096
1097 1097 attribute = ph_data->p_ep.bmAttributes & USB_EP_ATTR_MASK;
1098 1098 dir = ph_data->p_ep.bEndpointAddress & USB_EP_DIR_MASK;
1099 1099
1100 1100 usba_device = ph_data->p_usba_device;
1101 1101
1102 1102 /*
1103 1103 * For control and bulk, we will drain till ref_count <= 1 and
1104 1104 * req_count == 0 but for isoc and intr IN, we can only wait
1105 1105 * till the ref_count === 1 as the req_count will never go to 0
1106 1106 */
1107 1107 for (timeout = 0; timeout < usba_drain_timeout; timeout++) {
1108 1108 switch (attribute) {
1109 1109 case USB_EP_ATTR_CONTROL:
1110 1110 case USB_EP_ATTR_BULK:
1111 1111 if ((ph_data->p_req_count == 0) &&
1112 1112 (ph_impl->usba_ph_ref_count <= 1)) {
1113 1113 goto done;
1114 1114 }
1115 1115 break;
1116 1116 case USB_EP_ATTR_INTR:
1117 1117 case USB_EP_ATTR_ISOCH:
1118 1118 if (dir == USB_EP_DIR_IN) {
1119 1119 if (ph_impl->usba_ph_ref_count <= 1) {
1120 1120 goto done;
1121 1121 }
1122 1122 } else if ((ph_data->p_req_count == 0) &&
1123 1123 (ph_impl->usba_ph_ref_count <= 1)) {
1124 1124 goto done;
1125 1125 }
1126 1126 break;
1127 1127 }
1128 1128 mutex_exit(&ph_impl->usba_ph_mutex);
1129 1129 mutex_exit(&ph_data->p_mutex);
1130 1130 delay(drv_usectohz(1000));
1131 1131 mutex_enter(&ph_data->p_mutex);
1132 1132 mutex_enter(&ph_impl->usba_ph_mutex);
1133 1133 }
1134 1134 done:
1135 1135
1136 1136 mutex_exit(&ph_impl->usba_ph_mutex);
1137 1137 mutex_exit(&ph_data->p_mutex);
1138 1138
1139 1139 if (timeout >= usba_drain_timeout) {
1140 1140 int draining_succeeded;
1141 1141
1142 1142 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1143 1143 "timeout on draining requests, resetting pipe 0x%p",
1144 1144 (void *)ph_impl);
1145 1145
1146 1146 (void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1147 1147 USB_FLAGS_SLEEP);
1148 1148
1149 1149 mutex_enter(&ph_data->p_mutex);
1150 1150 draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE,
1151 1151 USB_CR_PIPE_RESET);
1152 1152 /* this MUST have succeeded */
1153 1153 ASSERT(draining_succeeded == USB_SUCCESS);
1154 1154 mutex_exit(&ph_data->p_mutex);
1155 1155
1156 1156 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1157 1157 "draining requests done");
1158 1158 }
1159 1159
1160 1160 if (usba_device->usb_hcdi_ops->usba_hcdi_pipe_close(ph_data,
1161 1161 usb_flags) != USB_SUCCESS) {
1162 1162 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1163 1163 "usba_pipe_sync_close: hcd close failed");
1164 1164 /* carry on regardless! */
1165 1165 }
1166 1166
1167 1167 usba_destroy_pipe_handle(ph_data);
1168 1168
1169 1169 return (USB_SUCCESS);
1170 1170 }
1171 1171
1172 1172
1173 1173 /*
1174 1174 * usb_pipe_set_private:
1175 1175 * set private client date in the pipe handle
1176 1176 */
1177 1177 int
1178 1178 usb_pipe_set_private(usb_pipe_handle_t pipe_handle, usb_opaque_t data)
1179 1179 {
1180 1180 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1181 1181
1182 1182 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1183 1183 "usb_pipe_set_private: ");
1184 1184
1185 1185 if (ph_data == NULL) {
1186 1186
1187 1187 return (USB_INVALID_PIPE);
1188 1188 }
1189 1189 if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1190 1190 usba_release_ph_data(ph_data->p_ph_impl);
1191 1191
1192 1192 return (USB_INVALID_PERM);
1193 1193 }
1194 1194
1195 1195 mutex_enter(&ph_data->p_mutex);
1196 1196 ph_data->p_client_private = data;
1197 1197 mutex_exit(&ph_data->p_mutex);
1198 1198
1199 1199 usba_release_ph_data(ph_data->p_ph_impl);
1200 1200
1201 1201 return (USB_SUCCESS);
1202 1202 }
1203 1203
1204 1204
1205 1205 /*
1206 1206 * usb_pipe_get_private:
1207 1207 * get private client date from the pipe handle
1208 1208 */
1209 1209 usb_opaque_t
1210 1210 usb_pipe_get_private(usb_pipe_handle_t pipe_handle)
1211 1211 {
1212 1212 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1213 1213 usb_opaque_t data;
1214 1214
1215 1215 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1216 1216 "usb_pipe_get_private:");
1217 1217
1218 1218 if (ph_data == NULL) {
1219 1219
1220 1220 return (NULL);
1221 1221 }
1222 1222
1223 1223 mutex_enter(&ph_data->p_mutex);
1224 1224 data = ph_data->p_client_private;
1225 1225 mutex_exit(&ph_data->p_mutex);
1226 1226
1227 1227 usba_release_ph_data(ph_data->p_ph_impl);
1228 1228
1229 1229 return (data);
1230 1230 }
1231 1231
1232 1232
1233 1233 /*
1234 1234 * usb_pipe_reset
1235 1235 * Arguments:
1236 1236 * dip - devinfo pointer
1237 1237 * pipe_handle - opaque pipe handle
1238 1238 * Returns:
1239 1239 * USB_SUCCESS - pipe successfully reset or request queued
1240 1240 * USB_FAILURE - undetermined failure
1241 1241 * USB_INVALID_PIPE - pipe is invalid or already closed
1242 1242 */
1243 1243 void
1244 1244 usb_pipe_reset(dev_info_t *dip,
1245 1245 usb_pipe_handle_t pipe_handle,
1246 1246 usb_flags_t usb_flags,
1247 1247 void (*callback)(
1248 1248 usb_pipe_handle_t ph,
1249 1249 usb_opaque_t arg,
1250 1250 int rval,
1251 1251 usb_cb_flags_t flags),
1252 1252 usb_opaque_t callback_arg)
1253 1253 {
1254 1254 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle;
1255 1255 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1256 1256 usb_cb_flags_t callback_flags;
1257 1257
1258 1258 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1259 1259 "usb_pipe_reset: dip=0x%p ph=0x%p uf=0x%x",
1260 1260 (void *)dip, (void *)pipe_handle, usb_flags);
1261 1261
1262 1262 callback_flags = usba_check_intr_context(USB_CB_NO_INFO);
1263 1263
1264 1264 if ((dip == NULL) || (ph_data == NULL)) {
1265 1265 if (callback) {
1266 1266 callback(pipe_handle, callback_arg,
1267 1267 USB_INVALID_ARGS, callback_flags);
1268 1268 } else {
1269 1269 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1270 1270 usbai_log_handle,
1271 1271 "usb_pipe_reset: invalid arguments");
1272 1272 }
1273 1273
1274 1274 usba_release_ph_data(ph_impl);
1275 1275
1276 1276 return;
1277 1277 }
1278 1278 if (servicing_interrupt() && (usb_flags & USB_FLAGS_SLEEP)) {
1279 1279 if (callback) {
1280 1280 callback(pipe_handle, callback_arg,
1281 1281 USB_INVALID_CONTEXT, callback_flags);
1282 1282 } else {
1283 1283 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1284 1284 usbai_log_handle,
1285 1285 "usb_pipe_reset: invalid context");
1286 1286 }
1287 1287
1288 1288 usba_release_ph_data(ph_impl);
1289 1289
1290 1290 return;
1291 1291 }
1292 1292
1293 1293 mutex_enter(&ph_data->p_mutex);
1294 1294
1295 1295 /* is this the default pipe? */
1296 1296 if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1297 1297 if ((usb_flags & USBA_FLAGS_PRIVILEGED) == 0) {
1298 1298 USB_DPRINTF_L2(DPRINT_MASK_USBAI, usbai_log_handle,
1299 1299 "usb_pipe_reset: not allowed to reset def pipe");
1300 1300 mutex_exit(&ph_data->p_mutex);
1301 1301
1302 1302 if (callback) {
1303 1303 callback(pipe_handle, callback_arg,
1304 1304 USB_INVALID_PIPE, callback_flags);
1305 1305 } else {
1306 1306 USB_DPRINTF_L2(DPRINT_MASK_USBAI,
1307 1307 usbai_log_handle,
1308 1308 "usb_pipe_reset: invalid pipe");
1309 1309 }
1310 1310 usba_release_ph_data(ph_impl);
1311 1311
1312 1312 return;
1313 1313 }
1314 1314 }
1315 1315 mutex_exit(&ph_data->p_mutex);
1316 1316
1317 1317 (void) usba_pipe_setup_func_call(dip,
1318 1318 usba_pipe_sync_reset, ph_impl, NULL, usb_flags, callback,
1319 1319 callback_arg);
1320 1320 }
1321 1321
1322 1322
1323 1323 /*ARGSUSED*/
1324 1324 int
1325 1325 usba_pipe_sync_reset(dev_info_t *dip,
1326 1326 usba_ph_impl_t *ph_impl,
1327 1327 usba_pipe_async_req_t *request,
1328 1328 usb_flags_t usb_flags)
1329 1329 {
1330 1330 int rval, draining_succeeded;
1331 1331 usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t)
1332 1332 ph_impl);
1333 1333 usba_device_t *usba_device;
1334 1334
1335 1335 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1336 1336 "usba_pipe_sync_reset: dip=0x%p ph_data=0x%p uf=0x%x",
1337 1337 (void *)dip, (void *)ph_data, usb_flags);
1338 1338
1339 1339 mutex_enter(&ph_data->p_mutex);
1340 1340 usba_device = ph_data->p_usba_device;
1341 1341 mutex_exit(&ph_data->p_mutex);
1342 1342
1343 1343 rval = usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1344 1344 usb_flags);
1345 1345 mutex_enter(&ph_data->p_mutex);
1346 1346
1347 1347 /*
1348 1348 * The host controller has stopped polling of the endpoint.
1349 1349 */
1350 1350 draining_succeeded = usba_drain_cbs(ph_data, USB_CB_RESET_PIPE,
1351 1351 USB_CR_PIPE_RESET);
1352 1352
1353 1353 /* this MUST have succeeded */
1354 1354 ASSERT(draining_succeeded == USB_SUCCESS);
1355 1355
1356 1356 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
1357 1357 mutex_exit(&ph_data->p_mutex);
1358 1358
1359 1359 /*
1360 1360 * if there are requests still queued on the default pipe,
1361 1361 * start them now
1362 1362 */
1363 1363 usba_start_next_req(ph_data);
1364 1364
1365 1365 usba_release_ph_data(ph_impl);
1366 1366
1367 1367 return (rval);
1368 1368 }
1369 1369
1370 1370
1371 1371 /*
1372 1372 * usba_pipe_clear:
1373 1373 * call hcd to clear pipe but don't wait for draining
1374 1374 */
1375 1375 void
1376 1376 usba_pipe_clear(usb_pipe_handle_t pipe_handle)
1377 1377 {
1378 1378 usba_pipe_handle_data_t *ph_data = usba_get_ph_data(pipe_handle);
1379 1379 usba_device_t *usba_device;
1380 1380 usba_req_wrapper_t *req_wrp;
1381 1381 int flush_requests = 1;
1382 1382
1383 1383 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1384 1384 "usba_pipe_clear: ph_data=0x%p", (void *)ph_data);
1385 1385
1386 1386 if (ph_data == NULL) {
1387 1387
1388 1388 return;
1389 1389 }
1390 1390
1391 1391 mutex_enter(&ph_data->p_mutex);
1392 1392 if (USBA_PIPE_CLOSING(usba_get_ph_state(ph_data))) {
1393 1393 mutex_exit(&ph_data->p_mutex);
1394 1394
1395 1395 return;
1396 1396 }
1397 1397 usba_device = ph_data->p_usba_device;
1398 1398 mutex_exit(&ph_data->p_mutex);
1399 1399
1400 1400 (void) usba_device->usb_hcdi_ops->usba_hcdi_pipe_reset(ph_data,
1401 1401 USB_FLAGS_SLEEP);
1402 1402
1403 1403 mutex_enter(&ph_data->p_mutex);
1404 1404 if (ph_data->p_dip) {
1405 1405 if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1406 1406 USB_DPRINTF_L4(DPRINT_MASK_USBAI,
1407 1407 usbai_log_handle,
1408 1408 "no flushing on default pipe!");
1409 1409
1410 1410 flush_requests = 0;
1411 1411 }
1412 1412 }
1413 1413
1414 1414 if (flush_requests) {
1415 1415 /* flush all requests in the pipehandle queue */
1416 1416 while ((req_wrp = (usba_req_wrapper_t *)
1417 1417 usba_rm_first_pvt_from_list(&ph_data->p_queue)) != NULL) {
1418 1418 mutex_exit(&ph_data->p_mutex);
1419 1419 usba_do_req_exc_cb(req_wrp, USB_CR_FLUSHED,
1420 1420 USB_CB_RESET_PIPE);
1421 1421 mutex_enter(&ph_data->p_mutex);
1422 1422 }
1423 1423 }
1424 1424
1425 1425 usba_pipe_new_state(ph_data, USB_PIPE_STATE_IDLE);
1426 1426 mutex_exit(&ph_data->p_mutex);
1427 1427 }
1428 1428
1429 1429
1430 1430 /*
1431 1431 *
1432 1432 * usb_pipe_drain_reqs
1433 1433 * this function blocks until there are no more requests
1434 1434 * owned by this dip on the pipe
1435 1435 *
1436 1436 * Arguments:
1437 1437 * dip - devinfo pointer
1438 1438 * pipe_handle - opaque pipe handle
1439 1439 * timeout - timeout in seconds
1440 1440 * flags - USB_FLAGS_SLEEP:
1441 1441 * wait for completion.
1442 1442 * cb - if USB_FLAGS_SLEEP has not been specified
1443 1443 * this callback function will be called on
1444 1444 * completion. This callback may be NULL
1445 1445 * and no notification of completion will then
1446 1446 * be provided.
1447 1447 * cb_arg - 2nd argument to callback function.
1448 1448 *
1449 1449 * callback and callback_arg should be NULL if USB_FLAGS_SLEEP has
1450 1450 * been specified
1451 1451 *
1452 1452 * Returns:
1453 1453 * USB_SUCCESS - pipe successfully reset or request queued
1454 1454 * USB_FAILURE - timeout
1455 1455 * USB_* - refer to usbai.h
1456 1456 */
1457 1457 int
1458 1458 usb_pipe_drain_reqs(dev_info_t *dip,
1459 1459 usb_pipe_handle_t pipe_handle,
1460 1460 uint_t time,
1461 1461 usb_flags_t usb_flags,
1462 1462 void (*cb)(
1463 1463 usb_pipe_handle_t ph,
1464 1464 usb_opaque_t arg, /* cb arg */
1465 1465 int rval,
1466 1466 usb_cb_flags_t flags),
1467 1467 usb_opaque_t cb_arg)
1468 1468 {
1469 1469 usba_ph_impl_t *ph_impl = (usba_ph_impl_t *)pipe_handle;
1470 1470 usba_pipe_handle_data_t *ph_data = usba_hold_ph_data(pipe_handle);
1471 1471
1472 1472 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1473 1473 "usb_pipe_drain_reqs: dip=0x%p ph_data=0x%p tm=%d uf=0x%x",
1474 1474 (void *)dip, (void *)ph_data, time, usb_flags);
1475 1475
1476 1476 if (ph_data == NULL) {
1477 1477
1478 1478 return (USB_INVALID_PIPE);
1479 1479 }
1480 1480 if (dip == NULL) {
1481 1481 usba_release_ph_data(ph_impl);
1482 1482
1483 1483 return (USB_INVALID_ARGS);
1484 1484 }
1485 1485
1486 1486 if ((usb_flags & USB_FLAGS_SLEEP) && servicing_interrupt()) {
1487 1487 usba_release_ph_data(ph_impl);
1488 1488
1489 1489 return (USB_INVALID_CONTEXT);
1490 1490 }
1491 1491
1492 1492 (void) usba_pipe_setup_func_call(dip, usba_pipe_sync_drain_reqs,
1493 1493 ph_impl, (usb_opaque_t)((uintptr_t)time), usb_flags, cb, cb_arg);
1494 1494
1495 1495 return (USB_SUCCESS);
1496 1496 }
1497 1497
1498 1498
1499 1499 /*
1500 1500 * usba_pipe_sync_drain_reqs
1501 1501 * this function blocks until there are no more requests
1502 1502 * owned by this dip on the pipe
1503 1503 *
1504 1504 * Arguments:
1505 1505 * dip - devinfo pointer
1506 1506 * ph_impl - pipe impl handle
1507 1507 * timeout - timeout in seconds
1508 1508 * Returns:
1509 1509 * USB_SUCCESS - pipe successfully reset or request queued
1510 1510 * USB_FAILURE - timeout
1511 1511 * USB_* - see usbai.h
1512 1512 */
1513 1513 /*ARGSUSED*/
1514 1514 int
1515 1515 usba_pipe_sync_drain_reqs(dev_info_t *dip,
1516 1516 usba_ph_impl_t *ph_impl,
1517 1517 usba_pipe_async_req_t *request,
1518 1518 usb_flags_t usb_flags)
1519 1519 {
1520 1520 usba_pipe_handle_data_t *ph_data = usba_get_ph_data((usb_pipe_handle_t)
1521 1521 ph_impl);
1522 1522 int i;
1523 1523 int timeout = 100 * (int)((uintptr_t)(request->arg));
1524 1524 /* delay will be 10 ms */
1525 1525
1526 1526 mutex_enter(&ph_data->p_mutex);
1527 1527
1528 1528 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1529 1529 "usba_pipe_sync_drain_reqs: "
1530 1530 "dip=0x%p ph_data=0x%p timeout=%d ref=%d req=%d",
1531 1531 (void *)dip, (void *)ph_data, timeout,
1532 1532 usba_get_ph_ref_count(ph_data),
1533 1533 ph_data->p_req_count);
1534 1534
1535 1535 ASSERT(ph_data->p_req_count >= 0);
1536 1536
1537 1537 /*
1538 1538 * for default pipe, we need to check the active request
1539 1539 * and the queue
1540 1540 * Note that a pipe reset on the default pipe doesn't flush
1541 1541 * the queue
1542 1542 * for all other pipes we just check ref and req count since
1543 1543 * these pipes are unshared
1544 1544 */
1545 1545 if (USBA_IS_DEFAULT_PIPE(ph_data)) {
1546 1546 for (i = 0; (i < timeout) || (request->arg == 0); i++) {
1547 1547 usba_list_entry_t *next, *tmpnext;
1548 1548 usba_req_wrapper_t *req_wrp = (usba_req_wrapper_t *)
1549 1549 ph_data->p_active_cntrl_req_wrp;
1550 1550 int found = 0;
1551 1551 int count = 0;
1552 1552
1553 1553 /* active_req_wrp is only for control pipes */
1554 1554 if ((req_wrp == NULL) || (req_wrp->wr_dip != dip)) {
1555 1555 /* walk the queue */
1556 1556 mutex_enter(&ph_data->p_queue.list_mutex);
1557 1557 next = ph_data->p_queue.next;
1558 1558 while (next != NULL) {
1559 1559 mutex_enter(&next->list_mutex);
1560 1560 req_wrp = (usba_req_wrapper_t *)
1561 1561 next->private;
1562 1562 found = (req_wrp->wr_dip == dip);
1563 1563 if (found) {
1564 1564 mutex_exit(&next->list_mutex);
1565 1565
1566 1566 break;
1567 1567 }
1568 1568 tmpnext = next->next;
1569 1569 mutex_exit(&next->list_mutex);
1570 1570 next = tmpnext;
1571 1571 count++;
1572 1572 }
1573 1573 mutex_exit(&ph_data->p_queue.list_mutex);
1574 1574 if (found == 0) {
1575 1575 break;
1576 1576 }
1577 1577 }
1578 1578
1579 1579 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1580 1580 "usb_pipe_sync_drain_reqs: "
1581 1581 "cnt=%d active_req_wrp=0x%p",
1582 1582 count, (void *)ph_data->p_active_cntrl_req_wrp);
1583 1583
1584 1584 mutex_exit(&ph_data->p_mutex);
1585 1585 delay(drv_usectohz(10000));
1586 1586 mutex_enter(&ph_data->p_mutex);
1587 1587 }
1588 1588 } else {
1589 1589 mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
1590 1590 for (i = 0; (i < timeout) || (request->arg == 0); i++) {
1591 1591 ASSERT(ph_data->p_req_count >= 0);
1592 1592 if (ph_data->p_req_count ||
1593 1593 (ph_data->p_ph_impl->usba_ph_ref_count > 1)) {
1594 1594 mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
1595 1595 mutex_exit(&ph_data->p_mutex);
1596 1596 delay(drv_usectohz(10000));
1597 1597 mutex_enter(&ph_data->p_mutex);
1598 1598 mutex_enter(&ph_data->p_ph_impl->usba_ph_mutex);
1599 1599 } else {
1600 1600 break;
1601 1601 }
1602 1602 }
1603 1603 mutex_exit(&ph_data->p_ph_impl->usba_ph_mutex);
1604 1604 }
1605 1605
1606 1606 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1607 1607 "usb_pipe_sync_drain_reqs: timeout=%d active_req_wrp=0x%p req=%d",
1608 1608 i, (void *)ph_data->p_active_cntrl_req_wrp, ph_data->p_req_count);
1609 1609
1610 1610 mutex_exit(&ph_data->p_mutex);
1611 1611
1612 1612 usba_release_ph_data(ph_impl);
1613 1613
1614 1614 return (i >= timeout ? USB_FAILURE : USB_SUCCESS);
1615 1615 }
1616 1616
1617 1617
1618 1618 /*
1619 1619 * usba_persistent_pipe_open
1620 1620 * Open all the pipes marked persistent for this device
1621 1621 */
1622 1622 int
1623 1623 usba_persistent_pipe_open(usba_device_t *usba_device)
1624 1624 {
1625 1625 usba_ph_impl_t *ph_impl;
1626 1626 usb_pipe_handle_t pipe_handle;
1627 1627 int i;
1628 1628 int rval = USB_SUCCESS;
1629 1629
1630 1630 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1631 1631 "usba_persistent_pipe_open: usba_device=0x%p", (void *)usba_device);
1632 1632
1633 1633 if (usba_device != NULL) {
1634 1634 /* default pipe is the first one to be opened */
1635 1635 mutex_enter(&usba_device->usb_mutex);
1636 1636 for (i = 0; (rval == USB_SUCCESS) &&
1637 1637 (i < USBA_N_ENDPOINTS); i++) {
1638 1638
1639 1639 ph_impl = &usba_device->usb_ph_list[i];
1640 1640 mutex_enter(&ph_impl->usba_ph_mutex);
1641 1641 if (ph_impl->usba_ph_flags & USBA_PH_DATA_PERSISTENT) {
1642 1642 ph_impl->usba_ph_flags &=
1643 1643 ~USBA_PH_DATA_PERSISTENT;
1644 1644 mutex_exit(&ph_impl->usba_ph_mutex);
1645 1645 mutex_exit(&usba_device->usb_mutex);
1646 1646
1647 1647 rval = usb_pipe_open(ph_impl->usba_ph_dip,
1648 1648 &ph_impl->usba_ph_ep,
1649 1649 &ph_impl->usba_ph_policy,
1650 1650 USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
1651 1651 &pipe_handle);
1652 1652
1653 1653 USB_DPRINTF_L3(DPRINT_MASK_USBAI,
1654 1654 usbai_log_handle,
1655 1655 "usba_persistent_pipe_open: "
1656 1656 "ep_index=%d, rval=%d", i, rval);
1657 1657 mutex_enter(&usba_device->usb_mutex);
1658 1658 mutex_enter(&ph_impl->usba_ph_mutex);
1659 1659 }
1660 1660 mutex_exit(&ph_impl->usba_ph_mutex);
1661 1661 }
1662 1662 mutex_exit(&usba_device->usb_mutex);
1663 1663 }
1664 1664
1665 1665 return (rval);
1666 1666 }
1667 1667
1668 1668
1669 1669 /*
1670 1670 * usba_persistent_pipe_close
1671 1671 * Close all pipes of this device and mark them persistent
1672 1672 */
1673 1673 void
1674 1674 usba_persistent_pipe_close(usba_device_t *usba_device)
1675 1675 {
1676 1676 usba_ph_impl_t *ph_impl;
1677 1677 usb_pipe_handle_t pipe_handle;
1678 1678 int i;
1679 1679
1680 1680 USB_DPRINTF_L4(DPRINT_MASK_USBAI, usbai_log_handle,
1681 1681 "usba_persistent_pipe_close: usba_device=0x%p",
1682 1682 (void *)usba_device);
1683 1683
1684 1684 if (usba_device != NULL) {
1685 1685 /* default pipe is the last one to be closed */
1686 1686 mutex_enter(&usba_device->usb_mutex);
1687 1687
1688 1688 for (i = (USBA_N_ENDPOINTS - 1); i >= 0; i--) {
1689 1689 ph_impl = &usba_device->usb_ph_list[i];
1690 1690 if (ph_impl->usba_ph_data != NULL) {
1691 1691 mutex_enter(&ph_impl->usba_ph_mutex);
1692 1692 ph_impl->usba_ph_flags |=
1693 1693 USBA_PH_DATA_PERSISTENT;
1694 1694 mutex_exit(&ph_impl->usba_ph_mutex);
1695 1695 mutex_exit(&usba_device->usb_mutex);
1696 1696
1697 1697 pipe_handle = (usb_pipe_handle_t)ph_impl;
1698 1698
1699 1699 usb_pipe_close(ph_impl->usba_ph_dip,
1700 1700 pipe_handle,
1701 1701 USB_FLAGS_SLEEP | USBA_FLAGS_PRIVILEGED,
1702 1702 NULL, NULL);
1703 1703 mutex_enter(&usba_device->usb_mutex);
1704 1704 ASSERT(ph_impl->usba_ph_data == NULL);
1705 1705 }
1706 1706 }
1707 1707 mutex_exit(&usba_device->usb_mutex);
1708 1708 }
1709 1709 }
↓ open down ↓ |
1238 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX