usb_disk: Retry actions after reset_recovery.
This is mostly important for B_GET_MEDIA_STATUS, which actually will retry actions if the err_act is set appropriately. Following this change, stalls are now fully recoverable without causing the file descriptors of the mounted partition to be cleared, and the system can resume normal operation without a problem. Fixes part of #15569. May help with #16745, #18185, #17543, #18421.
This commit is contained in:
@@ -585,13 +585,18 @@ usb_disk_clear_halt(usb_pipe pipe)
|
|||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
usb_disk_reset_recovery(disk_device *device)
|
usb_disk_reset_recovery(disk_device *device, err_act *_action)
|
||||||
{
|
{
|
||||||
|
TRACE("reset recovery\n");
|
||||||
|
|
||||||
usb_disk_mass_storage_reset(device);
|
usb_disk_mass_storage_reset(device);
|
||||||
usb_disk_clear_halt(device->bulk_in);
|
usb_disk_clear_halt(device->bulk_in);
|
||||||
usb_disk_clear_halt(device->bulk_out);
|
usb_disk_clear_halt(device->bulk_out);
|
||||||
if (device->is_ufi)
|
if (device->is_ufi)
|
||||||
usb_disk_clear_halt(device->interrupt);
|
usb_disk_clear_halt(device->interrupt);
|
||||||
|
|
||||||
|
if (_action != NULL)
|
||||||
|
*_action = err_act_retry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -735,8 +740,8 @@ usb_disk_operation_interrupt(device_lun *lun, uint8* operation,
|
|||||||
usb_disk_clear_halt(directionIn ? device->bulk_in : device->bulk_out);
|
usb_disk_clear_halt(directionIn ? device->bulk_in : device->bulk_out);
|
||||||
} else {
|
} else {
|
||||||
TRACE_ALWAYS("sending or receiving of the data failed\n");
|
TRACE_ALWAYS("sending or receiving of the data failed\n");
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return B_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -755,7 +760,7 @@ usb_disk_operation_interrupt(device_lun *lun, uint8* operation,
|
|||||||
|
|
||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE_ALWAYS("receiving the command status interrupt failed\n");
|
TRACE_ALWAYS("receiving the command status interrupt failed\n");
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,8 +804,8 @@ usb_disk_operation_bulk(device_lun *lun, uint8* operation,
|
|||||||
// sending the command block wrapper failed
|
// sending the command block wrapper failed
|
||||||
TRACE_ALWAYS("sending the command block wrapper failed: %s\n",
|
TRACE_ALWAYS("sending the command block wrapper failed: %s\n",
|
||||||
strerror(device->status));
|
strerror(device->status));
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return B_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t transferedData = 0;
|
size_t transferedData = 0;
|
||||||
@@ -820,8 +825,8 @@ usb_disk_operation_bulk(device_lun *lun, uint8* operation,
|
|||||||
} else {
|
} else {
|
||||||
TRACE_ALWAYS("sending or receiving of the data failed: %s\n",
|
TRACE_ALWAYS("sending or receiving of the data failed: %s\n",
|
||||||
strerror(device->status));
|
strerror(device->status));
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return B_ERROR;
|
return B_IO_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -837,7 +842,7 @@ usb_disk_operation_bulk(device_lun *lun, uint8* operation,
|
|||||||
if (result != B_OK) {
|
if (result != B_OK) {
|
||||||
TRACE_ALWAYS("receiving the command status wrapper failed: %s\n",
|
TRACE_ALWAYS("receiving the command status wrapper failed: %s\n",
|
||||||
strerror(result));
|
strerror(result));
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -846,7 +851,7 @@ usb_disk_operation_bulk(device_lun *lun, uint8* operation,
|
|||||||
// the command status wrapper is not valid
|
// the command status wrapper is not valid
|
||||||
TRACE_ALWAYS("command status wrapper is not valid: %#" B_PRIx32 "\n",
|
TRACE_ALWAYS("command status wrapper is not valid: %#" B_PRIx32 "\n",
|
||||||
status.signature);
|
status.signature);
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -891,7 +896,7 @@ usb_disk_operation_bulk(device_lun *lun, uint8* operation,
|
|||||||
// a protocol or device error occured
|
// a protocol or device error occured
|
||||||
TRACE_ALWAYS("phase error in operation %#" B_PRIx8 "\n",
|
TRACE_ALWAYS("phase error in operation %#" B_PRIx8 "\n",
|
||||||
operation[0]);
|
operation[0]);
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -899,7 +904,7 @@ usb_disk_operation_bulk(device_lun *lun, uint8* operation,
|
|||||||
{
|
{
|
||||||
// command status wrapper is not meaningful
|
// command status wrapper is not meaningful
|
||||||
TRACE_ALWAYS("command status wrapper has invalid status\n");
|
TRACE_ALWAYS("command status wrapper has invalid status\n");
|
||||||
usb_disk_reset_recovery(device);
|
usb_disk_reset_recovery(device, _action);
|
||||||
return B_ERROR;
|
return B_ERROR;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user