mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-18 10:46:25 +00:00
drivers/usb_block: treat SYNC as barrier
The commit implements the SYNC and TRIM as successful NOP, while the former is handled as an barrier to all other out-standing requests. Fixes #4825.
This commit is contained in:
parent
280724e6b5
commit
bcc454aa89
@ -64,7 +64,7 @@ struct Usb::Block_driver : Usb::Completion
|
||||
size_t size { 0 };
|
||||
bool completed { false };
|
||||
|
||||
Block_request(Request &request, Request_stream::Payload const &payload)
|
||||
Block_request(Request const &request, Request_stream::Payload const &payload)
|
||||
: block_request(request)
|
||||
{
|
||||
payload.with_content(request, [&](void *addr, size_t sz) {
|
||||
@ -902,12 +902,20 @@ struct Usb::Block_driver : Usb::Completion
|
||||
.writeable = _writeable };
|
||||
}
|
||||
|
||||
Response submit(Request &block_request,
|
||||
Response submit(Request const &block_request,
|
||||
Request_stream::Payload const &payload)
|
||||
{
|
||||
if (device_plugged == false)
|
||||
return Response::REJECTED;
|
||||
|
||||
/*
|
||||
* Check if there is already a request pending and wait
|
||||
* until it has finished. We do this check here to implement
|
||||
* 'SYNC' as barrier that waits for out-standing requests.
|
||||
*/
|
||||
if (request_pending())
|
||||
return Response::RETRY;
|
||||
|
||||
Operation const &op = block_request.operation;
|
||||
|
||||
/* read only */
|
||||
@ -924,12 +932,16 @@ struct Usb::Block_driver : Usb::Completion
|
||||
if (!force_cmd_16 && last >= ~0U)
|
||||
return Response::REJECTED;
|
||||
|
||||
/* check if request is pending */
|
||||
if (request_pending())
|
||||
return Response::RETRY;
|
||||
|
||||
request.construct(block_request, payload);
|
||||
|
||||
/* operations currently handled as successful NOP */
|
||||
if (request->block_request.operation.type == Operation::Type::TRIM
|
||||
|| request->block_request.operation.type == Operation::Type::SYNC) {
|
||||
request->block_request.success = true;
|
||||
request->completed = true;
|
||||
return Response::ACCEPTED;
|
||||
}
|
||||
|
||||
/* execute */
|
||||
send_cbw(op.block_number, op.count, request->read());
|
||||
|
||||
@ -1000,28 +1012,31 @@ struct Usb::Main : Rpc_object<Typed_root<Block::Session>>
|
||||
{
|
||||
if (!block_session.constructed()) return;
|
||||
|
||||
bool progress;
|
||||
do {
|
||||
progress = false;
|
||||
|
||||
/* ack and release possibly pending packet */
|
||||
block_session->try_acknowledge([&] (Block_session_component::Ack &ack) {
|
||||
driver.with_completed([&] (Block::Request &request) {
|
||||
driver.with_completed([&] (Block::Request const &request) {
|
||||
ack.submit(request);
|
||||
progress = true;
|
||||
});
|
||||
});
|
||||
|
||||
block_session->with_requests([&] (Request request) {
|
||||
|
||||
/* only read/write for now */
|
||||
if (Operation::has_payload(request.operation.type) == false) {
|
||||
request.success = true;
|
||||
return Response::REJECTED;
|
||||
}
|
||||
block_session->with_requests([&] (Request const request) {
|
||||
|
||||
Response response = Response::RETRY;
|
||||
|
||||
block_session->with_payload([&] (Request_stream::Payload const &payload) {
|
||||
response = driver.submit(request, payload);
|
||||
});
|
||||
if (response != Response::RETRY)
|
||||
progress = true;
|
||||
|
||||
return response;
|
||||
});
|
||||
} while (progress);
|
||||
|
||||
block_session->wakeup_client_if_needed();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user