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