1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 * 21 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 22 * Use is subject to license terms. 23 */ 24 25 26 /* 27 * scsa2usb_ms_cbi.c: 28 * 29 * This file implements USB Mass Storage Class 30 * Control Bulk Interrupt (CB/CBI) transport v1.0 31 * http://www.usb.org/developers/data/devclass/usbmass-cbi10.pdf 32 */ 33 #include <sys/usb/usba/usbai_version.h> 34 #include <sys/scsi/scsi.h> 35 #include <sys/callb.h> /* needed by scsa2usb.h */ 36 #include <sys/strsubr.h> 37 38 #include <sys/usb/usba.h> 39 #include <sys/usb/usba/usba_private.h> 40 #include <sys/usb/usba/usba_ugen.h> 41 42 #include <sys/usb/clients/mass_storage/usb_cbi.h> 43 #include <sys/usb/scsa2usb/scsa2usb.h> 44 45 /* 46 * Function Prototypes 47 */ 48 int scsa2usb_cbi_transport(scsa2usb_state_t *, scsa2usb_cmd_t *); 49 static int scsa2usb_handle_cbi_status(usb_intr_req_t *); 50 static void scsa2usb_cbi_reset_recovery(scsa2usb_state_t *); 51 static void scsa2usb_cbi_handle_error(scsa2usb_state_t *, int, usb_cr_t); 52 static usb_intr_req_t *scsa2usb_cbi_start_intr_polling(scsa2usb_state_t *); 53 void scsa2usb_cbi_stop_intr_polling(scsa2usb_state_t *); 54 55 /* extern functions */ 56 extern void scsa2usb_setup_next_xfer(scsa2usb_state_t *, scsa2usb_cmd_t *); 57 extern int scsa2usb_handle_data_start(scsa2usb_state_t *, 58 scsa2usb_cmd_t *, usb_bulk_req_t *); 59 extern void scsa2usb_handle_data_done(scsa2usb_state_t *, scsa2usb_cmd_t *, 60 usb_bulk_req_t *); 61 extern usb_bulk_req_t *scsa2usb_init_bulk_req(scsa2usb_state_t *, 62 size_t, uint_t, usb_req_attrs_t, usb_flags_t); 63 extern int scsa2usb_clear_ept_stall(scsa2usb_state_t *, uint_t, 64 usb_pipe_handle_t, char *); 65 extern void scsa2usb_close_usb_pipes(scsa2usb_state_t *); 66 67 #ifdef DEBUG /* debugging information */ 68 extern void scsa2usb_print_cdb(scsa2usb_state_t *, scsa2usb_cmd_t *); 69 #endif /* DEBUG */ 70 71 72 /* 73 * scsa2usb_cbi_transport: 74 * Implements the CB/CBI state machine by these steps: 75 * a) Issues command to the device over control pipe. 76 * b) Start Data Phase if applicable 77 * c) Start Status Phase 78 * 79 * returns TRAN_* values and not USB_SUCCESS/FAILURE 80 * 81 * scsa2usb_cbi_transport() handles the normal transitions or 82 * continuation after clearing stalls or error recovery. 83 * 84 * Command Phase: 85 * prepare a valid command and transport it on default pipe 86 * if error on default-pipe: 87 * set pkt_reason to CMD_TRAN_ERR 88 * new pkt state is SCSA2USB_PKT_DO_COMP 89 * do reset recovery synchronously 90 * else 91 * proceed to data phase 92 * 93 * Data Phase: 94 * if data in: 95 * setup data in on bulkin 96 * else if data out: 97 * setup data out on bulkout 98 * 99 * data: (in) 100 * copy data transferred so far, no more data to transfer 101 * 102 * if stall on bulkin pipe 103 * terminate data transfers, set cmd_done 104 * clear stall on bulkin syncrhonously 105 * else if other exception 106 * set pkt_reason to CMD_TRAN_ERR 107 * new pkt state is SCSA2USB_PKT_DO_COMP 108 * do reset recovery synchronously 109 * else (no error) 110 * receive status 111 * 112 * data: (out) 113 * if stall on bulkout pipe 114 * terminate data transfers 115 * clear stall on bulkout synchronously USBA 116 * else if other exception 117 * set pkt_reason to CMD_TRAN_ERR 118 * new pkt state is SCSA2USB_PKT_DO_COMP 119 * do reset recovery synchronously 120 * else (no error) 121 * receive status 122 * 123 * Status Phase: (on Interrupt pipe for CBI devices only) 124 * if error 125 * if stall 126 * new pkt state is SCSA2USB_PKT_DO_COMP 127 * clear stall on interrupt pipe 128 * else 129 * set pkt_reason to CMD_TRAN_ERR 130 * new pkt state is SCSA2USB_PKT_DO_COMP 131 * do reset recovery synchronously 132 * else (no error) 133 * goto read status 134 * 135 * read status: 136 * if not OK or phase error 137 * new pkt state is SCSA2USB_PKT_DO_COMP 138 * set pkt reason CMD_TRAN_ERR 139 * reset recovery synchronously 140 * else (status ok) 141 * goto SCSA2USB_PKT_DO_COMP 142 * 143 * The reset recovery walks sequentially thru device reset, clearing 144 * stalls and pipe resets. When the reset recovery completes we return 145 * to the taskq thread. 146 * 147 * Clearing stalls clears the stall condition, resets the pipe, and 148 * then returns to the transport. 149 */ 150 int 151 scsa2usb_cbi_transport(scsa2usb_state_t *scsa2usbp, scsa2usb_cmd_t *cmd) 152 { 153 int i, rval = TRAN_ACCEPT; 154 mblk_t *data; 155 usb_cr_t completion_reason; 156 usb_cb_flags_t cb_flags; 157 usb_bulk_req_t *data_req; 158 usb_intr_req_t *status_req; 159 160 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 161 "scsa2usb_cbi_transport: cmd = 0x%p", (void *)cmd); 162 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 163 164 Cmd_Phase: 165 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 166 167 return (TRAN_FATAL_ERROR); 168 } 169 170 /* 171 * Start command phase (C - in CBI) 172 */ 173 data = allocb_wait(CBI_CLASS_CMD_LEN, BPRI_LO, STR_NOSIG, NULL); 174 175 /* Initialize the data */ 176 for (i = 0; i < CBI_CLASS_CMD_LEN; i++) { 177 *data->b_wptr++ = cmd->cmd_cdb[i]; 178 } 179 180 SCSA2USB_PRINT_CDB(scsa2usbp, cmd); /* print the CDB */ 181 182 /* Send the Command to the device */ 183 mutex_exit(&scsa2usbp->scsa2usb_mutex); 184 rval = usb_pipe_sync_ctrl_xfer(scsa2usbp->scsa2usb_dip, 185 scsa2usbp->scsa2usb_default_pipe, 186 CBI_REQUEST_TYPE, /* bmRequestType */ 187 0, /* bRequest */ 188 CBI_WVALUE, /* wValue */ 189 scsa2usbp->scsa2usb_intfc_num, /* wIndex */ 190 CBI_CLASS_CMD_LEN, /* wLength */ 191 &data, /* data */ 192 USB_ATTRS_PIPE_RESET, /* attributes */ 193 &completion_reason, &cb_flags, USB_FLAGS_SLEEP); 194 mutex_enter(&scsa2usbp->scsa2usb_mutex); 195 196 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 197 "scsa2usb_cbi_transport: sent cmd = 0x%x rval = %d", 198 cmd->cmd_cdb[SCSA2USB_OPCODE], rval); 199 200 SCSA2USB_FREE_MSG(data); /* get rid of the data */ 201 if (rval != USB_SUCCESS) { 202 scsa2usb_cbi_handle_error(scsa2usbp, rval, completion_reason); 203 204 return (TRAN_FATAL_ERROR); 205 } 206 207 /* 208 * Xferred command to the device. 209 * Start data phase (B - in CBI) 210 */ 211 212 /* 213 * we've not transferred any data yet; updated in 214 * scsa2usb_handle_data_done 215 */ 216 cmd->cmd_resid_xfercount = 0; 217 218 /* if data to be xferred ? */ 219 if (cmd->cmd_xfercount) { 220 221 /* Initialize a bulk_req_t */ 222 data_req = scsa2usb_init_bulk_req(scsa2usbp, 0, 223 cmd->cmd_timeout, USB_ATTRS_PIPE_RESET, USB_FLAGS_SLEEP); 224 225 /* start I/O to/from the device */ 226 rval = scsa2usb_handle_data_start(scsa2usbp, cmd, 227 data_req); 228 /* handle data returned */ 229 scsa2usb_handle_data_done(scsa2usbp, cmd, 230 data_req); 231 if (rval != USB_SUCCESS) { 232 /* 233 * we ran into an error and it wasn't a STALL 234 */ 235 if (data_req->bulk_completion_reason == USB_CR_STALL) { 236 if (scsa2usbp->scsa2usb_cur_pkt) { 237 scsa2usbp->scsa2usb_cur_pkt-> 238 pkt_reason = CMD_TRAN_ERR; 239 } 240 } else { 241 scsa2usb_cbi_handle_error(scsa2usbp, 242 rval, data_req->bulk_completion_reason); 243 244 /* get rid of req */ 245 SCSA2USB_FREE_BULK_REQ(data_req); 246 247 return (TRAN_FATAL_ERROR); 248 } 249 } 250 251 SCSA2USB_FREE_BULK_REQ(data_req); /* get rid of bulk_req */ 252 } 253 254 /* CB devices don't do status over interrupt pipe */ 255 if (SCSA2USB_IS_CB(scsa2usbp)) { 256 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 257 "scsa2usb_cbi_transport: CB done rval = %d", rval); 258 goto end_it; 259 } 260 261 /* 262 * Start status phase (I - in CBI) 263 */ 264 265 /* Get Status over interrupt pipe */ 266 if ((status_req = scsa2usb_cbi_start_intr_polling(scsa2usbp)) == NULL) { 267 268 return (TRAN_FATAL_ERROR); /* lack of better return code */ 269 } 270 271 rval = scsa2usb_handle_cbi_status(status_req); 272 273 usb_free_intr_req(status_req); 274 275 /* stop interrupt pipe polling (CBI only) */ 276 if (SCSA2USB_IS_CBI(scsa2usbp)) { 277 scsa2usb_cbi_stop_intr_polling(scsa2usbp); 278 } 279 280 end_it: 281 if ((rval == USB_SUCCESS) && /* CSW was ok */ 282 (scsa2usbp->scsa2usb_cur_pkt->pkt_reason == CMD_CMPLT) && 283 (cmd->cmd_xfercount != 0) && /* more data to xfer */ 284 !cmd->cmd_done) { /* we aren't done yet */ 285 scsa2usb_setup_next_xfer(scsa2usbp, cmd); 286 goto Cmd_Phase; 287 } else { 288 if (SCSA2USB_IS_CB(scsa2usbp)) { 289 cmd->cmd_done = 1; 290 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 291 } 292 } 293 294 return (rval == USB_SUCCESS ? TRAN_ACCEPT : TRAN_FATAL_ERROR); 295 } 296 297 298 /* 299 * scsa2usb_cbi_handle_error: 300 * handle errors from transport that are not STALL conditions 301 */ 302 static void 303 scsa2usb_cbi_handle_error(scsa2usb_state_t *scsa2usbp, int rval, usb_cr_t cr) 304 { 305 struct scsi_pkt *pkt = scsa2usbp->scsa2usb_cur_pkt; 306 307 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 308 "scsa2usb_cbi_handle_error: data error %d cr = %d", rval, cr); 309 310 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 311 312 /* do reset error recovery */ 313 switch (cr) { 314 case USB_CR_STALL: 315 if (pkt) { 316 pkt->pkt_reason = CMD_TRAN_ERR; 317 *(pkt->pkt_scbp) = STATUS_CHECK; 318 } 319 break; 320 case USB_CR_TIMEOUT: 321 if (pkt) { 322 pkt->pkt_reason = CMD_TIMEOUT; 323 pkt->pkt_statistics |= STAT_TIMEOUT; 324 } 325 break; 326 case USB_CR_DEV_NOT_RESP: 327 scsa2usb_cbi_stop_intr_polling(scsa2usbp); 328 if (pkt) { 329 pkt->pkt_reason = CMD_DEV_GONE; 330 /* scsi_poll relies on this */ 331 pkt->pkt_state = STATE_GOT_BUS; 332 } 333 break; 334 default: 335 if (pkt) { 336 pkt->pkt_reason = CMD_TRAN_ERR; 337 } 338 scsa2usb_cbi_reset_recovery(scsa2usbp); 339 } 340 } 341 342 343 /* 344 * scsa2usb_cbi_start_intr_polling: 345 * start polling asynchronously without notification 346 */ 347 static usb_intr_req_t * 348 scsa2usb_cbi_start_intr_polling(scsa2usb_state_t *scsa2usbp) 349 { 350 int rval; 351 usb_pipe_state_t pipe_state; 352 usb_intr_req_t *req = NULL; 353 354 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 355 "scsa2usb_cbi_start_intr_polling:"); 356 357 if (!SCSA2USB_IS_CBI(scsa2usbp)) { 358 359 return (NULL); 360 } 361 362 req = usb_alloc_intr_req(scsa2usbp->scsa2usb_dip, 0, USB_FLAGS_SLEEP); 363 req->intr_client_private = (usb_opaque_t)scsa2usbp; 364 req->intr_attributes = USB_ATTRS_ONE_XFER | USB_ATTRS_PIPE_RESET | 365 USB_ATTRS_SHORT_XFER_OK; 366 req->intr_len = scsa2usbp->scsa2usb_intr_ept.wMaxPacketSize; 367 req->intr_timeout = 20; /* arbitrary large for now */ 368 mutex_exit(&scsa2usbp->scsa2usb_mutex); 369 370 if ((rval = usb_pipe_intr_xfer(scsa2usbp->scsa2usb_intr_pipe, req, 371 USB_FLAGS_SLEEP)) != USB_SUCCESS) { 372 mutex_enter(&scsa2usbp->scsa2usb_mutex); 373 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 374 "polling failed rval: %d", rval); 375 376 /* clear stall */ 377 if (req->intr_completion_reason == USB_CR_STALL) { 378 (void) scsa2usb_clear_ept_stall(scsa2usbp, 379 scsa2usbp->scsa2usb_intr_ept.bEndpointAddress, 380 scsa2usbp->scsa2usb_intr_pipe, "intr"); 381 } 382 383 /* handle other errors here */ 384 scsa2usb_cbi_handle_error(scsa2usbp, rval, 385 req->intr_completion_reason); 386 mutex_exit(&scsa2usbp->scsa2usb_mutex); 387 388 usb_free_intr_req(req); 389 req = NULL; 390 } 391 392 rval = usb_pipe_get_state(scsa2usbp->scsa2usb_intr_pipe, 393 &pipe_state, USB_FLAGS_SLEEP); 394 if (pipe_state != USB_PIPE_STATE_ACTIVE) { 395 USB_DPRINTF_L2(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 396 "intr pipes state: %d, rval: %d", pipe_state, rval); 397 } 398 mutex_enter(&scsa2usbp->scsa2usb_mutex); 399 400 return (req); 401 } 402 403 404 /* 405 * scsa2usb_cbi_stop_intr_polling: 406 * Stop polling on interrupt pipe (for status) 407 */ 408 void 409 scsa2usb_cbi_stop_intr_polling(scsa2usb_state_t *scsa2usbp) 410 { 411 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 412 "scsa2usb_cbi_stop_intr_polling:"); 413 414 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 415 416 if (!SCSA2USB_IS_CBI(scsa2usbp)) { 417 418 return; 419 } 420 421 if (scsa2usbp->scsa2usb_intr_pipe) { 422 mutex_exit(&scsa2usbp->scsa2usb_mutex); 423 usb_pipe_stop_intr_polling(scsa2usbp->scsa2usb_intr_pipe, 424 USB_FLAGS_SLEEP); 425 mutex_enter(&scsa2usbp->scsa2usb_mutex); 426 } 427 } 428 429 430 /* 431 * scsa2usb_handle_cbi_status: 432 * Handle CBI status results 433 */ 434 static int 435 scsa2usb_handle_cbi_status(usb_intr_req_t *req) 436 { 437 int rval = USB_SUCCESS; 438 int status; 439 char *msg; 440 scsa2usb_cmd_t *cmd; 441 scsa2usb_state_t *scsa2usbp = (scsa2usb_state_t *) 442 req->intr_client_private; 443 444 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 445 "scsa2usb_handle_cbi_status: req: 0x%p", (void *)req); 446 447 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 448 ASSERT(req->intr_data != NULL); 449 450 cmd = PKT2CMD(scsa2usbp->scsa2usb_cur_pkt); 451 status = *(req->intr_data->b_rptr + 1) & CBI_STATUS_MASK; 452 453 /* 454 * CBI status contains ASC and ASCQ. 455 * SCMD_REQUEST_SENSE and SCMD_INQUIRY don't affect the sense data 456 * on CBI devices. So, we can ignore that info for these 2 commands. 457 * 458 * (See details in UFI spec section 3.5 - that says that INQUIRY, 459 * SEND_DIAG, and REQUEST_SENSE ought to be supported by any deivce 460 * irrespective). 461 */ 462 if ((cmd->cmd_cdb[SCSA2USB_OPCODE] == SCMD_REQUEST_SENSE) || 463 (cmd->cmd_cdb[SCSA2USB_OPCODE] == SCMD_INQUIRY)) { 464 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 465 "scsa2usb_handle_cbi_status: CBI STATUS = (0x%x, 0x%x)", 466 *(req->intr_data->b_rptr), *(req->intr_data->b_rptr+1)); 467 468 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 469 470 return (USB_SUCCESS); 471 } 472 473 switch (status) { 474 case CBI_STATUS_PASS: 475 msg = "PASSED"; 476 /* non-zero command completion interrupt */ 477 if (*(req->intr_data->b_rptr)) { 478 *(scsa2usbp->scsa2usb_cur_pkt->pkt_scbp) = STATUS_CHECK; 479 cmd->cmd_done = 1; 480 } 481 break; 482 case CBI_STATUS_FAILED: 483 case CBI_STATUS_PERSISTENT_FAIL: 484 msg = (status == CBI_STATUS_PERSISTENT_FAIL) ? 485 "PERSISTENT_FAILURE" : "FAILED"; 486 *(scsa2usbp->scsa2usb_cur_pkt->pkt_scbp) = STATUS_CHECK; 487 cmd->cmd_done = 1; 488 break; 489 case CBI_STATUS_PHASE_ERR: 490 msg = "PHASE_ERR"; 491 scsa2usb_cbi_reset_recovery(scsa2usbp); 492 rval = USB_FAILURE; 493 break; 494 } 495 496 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 497 "CBI STATUS = 0x%x %s (0x%x, 0x%x)", status, msg, 498 *(req->intr_data->b_rptr), *(req->intr_data->b_rptr+1)); 499 500 /* we are done and ready to callback */ 501 SCSA2USB_SET_PKT_DO_COMP_STATE(scsa2usbp); 502 503 return (rval); 504 } 505 506 507 /* 508 * scsa2usb_cbi_reset_recovery: 509 * Reset the USB device in case of errors. 510 */ 511 static void 512 scsa2usb_cbi_reset_recovery(scsa2usb_state_t *scsa2usbp) 513 { 514 int i, rval; 515 mblk_t *cdb; 516 usb_cr_t completion_reason; 517 usb_cb_flags_t cb_flags; 518 519 USB_DPRINTF_L4(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 520 "scsa2usb_cbi_reset_recovery: (0x%p)", (void *)scsa2usbp); 521 522 ASSERT(mutex_owned(&scsa2usbp->scsa2usb_mutex)); 523 524 if (!(SCSA2USB_DEVICE_ACCESS_OK(scsa2usbp))) { 525 526 return; 527 } 528 529 if (scsa2usbp->scsa2usb_cur_pkt) { 530 scsa2usbp->scsa2usb_cur_pkt->pkt_statistics |= STAT_DEV_RESET; 531 } 532 533 /* Allocate an mblk for CBR */ 534 cdb = allocb_wait(CBI_CLASS_CMD_LEN, BPRI_LO, STR_NOSIG, NULL); 535 536 *cdb->b_wptr++ = SCMD_SDIAG; /* Set it to DIAG */ 537 *cdb->b_wptr++ = CBI_SELF_TEST; /* Set it to reset */ 538 for (i = 2; i < CBI_CLASS_CMD_LEN; i++) { 539 *cdb->b_wptr++ = CBI_CBR_VALUE; /* Set it to 0xff */ 540 } 541 542 scsa2usbp->scsa2usb_pipe_state = SCSA2USB_PIPE_DEV_RESET; 543 544 /* 545 * Send a Reset request to the device 546 */ 547 mutex_exit(&scsa2usbp->scsa2usb_mutex); 548 rval = usb_pipe_sync_ctrl_xfer(scsa2usbp->scsa2usb_dip, 549 scsa2usbp->scsa2usb_default_pipe, 550 CBI_REQUEST_TYPE, /* bmRequestType */ 551 0, /* bRequest */ 552 CBI_WVALUE, /* wValue */ 553 scsa2usbp->scsa2usb_intfc_num, /* wIndex address */ 554 CBI_CLASS_CMD_LEN, /* wLength */ 555 &cdb, /* data to be sent */ 556 0, &completion_reason, &cb_flags, 0); 557 mutex_enter(&scsa2usbp->scsa2usb_mutex); 558 559 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 560 "\tCBI RESET: rval = %x cr = %x", rval, completion_reason); 561 if (rval != USB_SUCCESS) { 562 goto exc_exit; 563 } 564 565 /* reset and clear STALL on bulk-in pipe */ 566 rval = scsa2usb_clear_ept_stall(scsa2usbp, 567 scsa2usbp->scsa2usb_bulkin_ept.bEndpointAddress, 568 scsa2usbp->scsa2usb_bulkin_pipe, "bulk-in"); 569 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 570 "\tclear stall on bulk-in pipe: %d", rval); 571 if (rval != USB_SUCCESS) { 572 goto exc_exit; 573 } 574 575 /* reset and clear STALL on bulk-out pipe */ 576 rval = scsa2usb_clear_ept_stall(scsa2usbp, 577 scsa2usbp->scsa2usb_bulkout_ept.bEndpointAddress, 578 scsa2usbp->scsa2usb_bulkout_pipe, "bulk-out"); 579 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 580 "\tclear stall on bulk-out pipe: %d", rval); 581 if (rval != USB_SUCCESS) { 582 goto exc_exit; 583 } 584 585 /* reset and clear STALL on interrupt pipe */ 586 if (SCSA2USB_IS_CBI(scsa2usbp)) { 587 rval = scsa2usb_clear_ept_stall(scsa2usbp, 588 scsa2usbp->scsa2usb_intr_ept.bEndpointAddress, 589 scsa2usbp->scsa2usb_intr_pipe, "intr"); 590 591 USB_DPRINTF_L3(DPRINT_MASK_SCSA, scsa2usbp->scsa2usb_log_handle, 592 "\tclear stall on intr pipe: %d", rval); 593 } 594 595 exc_exit: 596 SCSA2USB_FREE_MSG(cdb); /* Free the data */ 597 scsa2usbp->scsa2usb_pipe_state &= ~SCSA2USB_PIPE_DEV_RESET; 598 } 599