aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/usb
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/usb')
-rw-r--r--drivers/usb/storage/uas.c36
1 files changed, 30 insertions, 6 deletions
diff --git a/drivers/usb/storage/uas.c b/drivers/usb/storage/uas.c
index 9ff9404f99d7..44b096c1737b 100644
--- a/drivers/usb/storage/uas.c
+++ b/drivers/usb/storage/uas.c
@@ -246,6 +246,29 @@ static void uas_xfer_data(struct urb *urb, struct scsi_cmnd *cmnd,
246 } 246 }
247} 247}
248 248
249static bool uas_evaluate_response_iu(struct response_iu *riu, struct scsi_cmnd *cmnd)
250{
251 u8 response_code = riu->response_code;
252
253 switch (response_code) {
254 case RC_INCORRECT_LUN:
255 cmnd->result = DID_BAD_TARGET << 16;
256 break;
257 case RC_TMF_SUCCEEDED:
258 cmnd->result = DID_OK << 16;
259 break;
260 case RC_TMF_NOT_SUPPORTED:
261 cmnd->result = DID_TARGET_FAILURE << 16;
262 break;
263 default:
264 uas_log_cmd_state(cmnd, "response iu", response_code);
265 cmnd->result = DID_ERROR << 16;
266 break;
267 }
268
269 return response_code == RC_TMF_SUCCEEDED;
270}
271
249static void uas_stat_cmplt(struct urb *urb) 272static void uas_stat_cmplt(struct urb *urb)
250{ 273{
251 struct iu *iu = urb->transfer_buffer; 274 struct iu *iu = urb->transfer_buffer;
@@ -258,6 +281,7 @@ static void uas_stat_cmplt(struct urb *urb)
258 unsigned long flags; 281 unsigned long flags;
259 unsigned int idx; 282 unsigned int idx;
260 int status = urb->status; 283 int status = urb->status;
284 bool success;
261 285
262 spin_lock_irqsave(&devinfo->lock, flags); 286 spin_lock_irqsave(&devinfo->lock, flags);
263 287
@@ -313,13 +337,13 @@ static void uas_stat_cmplt(struct urb *urb)
313 uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB); 337 uas_xfer_data(urb, cmnd, SUBMIT_DATA_OUT_URB);
314 break; 338 break;
315 case IU_ID_RESPONSE: 339 case IU_ID_RESPONSE:
316 uas_log_cmd_state(cmnd, "unexpected response iu",
317 ((struct response_iu *)iu)->response_code);
318 /* Error, cancel data transfers */
319 data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
320 data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
321 cmdinfo->state &= ~COMMAND_INFLIGHT; 340 cmdinfo->state &= ~COMMAND_INFLIGHT;
322 cmnd->result = DID_ERROR << 16; 341 success = uas_evaluate_response_iu((struct response_iu *)iu, cmnd);
342 if (!success) {
343 /* Error, cancel data transfers */
344 data_in_urb = usb_get_urb(cmdinfo->data_in_urb);
345 data_out_urb = usb_get_urb(cmdinfo->data_out_urb);
346 }
323 uas_try_complete(cmnd, __func__); 347 uas_try_complete(cmnd, __func__);
324 break; 348 break;
325 default: 349 default: