usb_drv: Remove signal dispatching from storage
Do not call 'wait_and_dispatch_one_signal' in storage back end. This causes a race of the EP with the main thread.
This commit is contained in:
parent
60ba210a6b
commit
64f39c9a42
|
@ -27,7 +27,6 @@ CC_WARN = -Wall -Wno-unused-variable -Wno-uninitialized \
|
||||||
|
|
||||||
CC_C_OPT += -Wno-unused-but-set-variable -Wno-pointer-sign -Wno-unused-label
|
CC_C_OPT += -Wno-unused-but-set-variable -Wno-pointer-sign -Wno-unused-label
|
||||||
|
|
||||||
CXX_OPT = -fpermissive
|
|
||||||
CC_CXX_OPT = -fpermissive
|
CC_CXX_OPT = -fpermissive
|
||||||
|
|
||||||
#
|
#
|
||||||
|
|
|
@ -109,7 +109,7 @@ catch { exec sh -c $cmd }
|
||||||
#
|
#
|
||||||
append qemu_args "-drive if=none,id=disk,file=$disk_image"
|
append qemu_args "-drive if=none,id=disk,file=$disk_image"
|
||||||
append qemu_args { \
|
append qemu_args { \
|
||||||
-m 64 -nographic -M pc \
|
-m 128 -nographic -M pc \
|
||||||
-device usb-ehci,id=ehci \
|
-device usb-ehci,id=ehci \
|
||||||
-device usb-storage,bus=ehci.0,drive=disk \
|
-device usb-storage,bus=ehci.0,drive=disk \
|
||||||
-boot order=d }
|
-boot order=d }
|
||||||
|
|
|
@ -1156,6 +1156,7 @@ struct work_struct {
|
||||||
work_func_t func;
|
work_func_t func;
|
||||||
struct list_head entry;
|
struct list_head entry;
|
||||||
unsigned pending;
|
unsigned pending;
|
||||||
|
void *data;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct delayed_work {
|
struct delayed_work {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include <extern_c_begin.h>
|
#include <extern_c_begin.h>
|
||||||
#include <lx_emul.h>
|
#include <lx_emul.h>
|
||||||
#include <storage/scsi.h>
|
#include <storage/scsi.h>
|
||||||
|
#include <drivers/usb/storage/usb.h>
|
||||||
#include <extern_c_end.h>
|
#include <extern_c_end.h>
|
||||||
|
|
||||||
#include <platform/lx_mem.h>
|
#include <platform/lx_mem.h>
|
||||||
|
@ -88,6 +89,11 @@ class Storage_device : public Genode::List<Storage_device>::Element,
|
||||||
PDBG("PACKET: phys: %lx block: %llu count: %zu %s",
|
PDBG("PACKET: phys: %lx block: %llu count: %zu %s",
|
||||||
phys, block_nr, block_count, read ? "read" : "write");
|
phys, block_nr, block_count, read ? "read" : "write");
|
||||||
|
|
||||||
|
/* check if we can call queuecommand */
|
||||||
|
struct us_data *us = (struct us_data *) _sdev->host->hostdata;
|
||||||
|
if (us->srb != NULL)
|
||||||
|
throw Request_congestion();
|
||||||
|
|
||||||
struct scsi_cmnd *cmnd = _scsi_alloc_command();
|
struct scsi_cmnd *cmnd = _scsi_alloc_command();
|
||||||
|
|
||||||
cmnd->cmnd[0] = read ? READ_10 : WRITE_10;
|
cmnd->cmnd[0] = read ? READ_10 : WRITE_10;
|
||||||
|
@ -118,10 +124,7 @@ class Storage_device : public Genode::List<Storage_device>::Element,
|
||||||
cmnd->request = &req;
|
cmnd->request = &req;
|
||||||
|
|
||||||
/* send command to host driver */
|
/* send command to host driver */
|
||||||
while((_sdev->host->hostt->queuecommand(_sdev->host, cmnd)) != 0) {
|
_sdev->host->hostt->queuecommand(_sdev->host, cmnd);
|
||||||
Server::wait_and_dispatch_one_signal();
|
|
||||||
__wait_event();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
@ -182,6 +185,20 @@ struct Factory : Block::Driver_factory
|
||||||
|
|
||||||
|
|
||||||
static Storage_device *device = nullptr;
|
static Storage_device *device = nullptr;
|
||||||
|
static work_struct delayed;
|
||||||
|
|
||||||
|
|
||||||
|
extern "C" void ack_packet(work_struct *work)
|
||||||
|
{
|
||||||
|
Block::Packet_descriptor *packet =
|
||||||
|
static_cast<Block::Packet_descriptor *>(work->data);
|
||||||
|
|
||||||
|
if (verbose)
|
||||||
|
PDBG("ACK packet for block: %llu", packet->block_number());
|
||||||
|
|
||||||
|
device->ack_packet(*packet);
|
||||||
|
Genode::destroy(Genode::env()->heap(), packet);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void scsi_add_device(struct scsi_device *sdev)
|
void scsi_add_device(struct scsi_device *sdev)
|
||||||
|
@ -196,6 +213,7 @@ void scsi_add_device(struct scsi_device *sdev)
|
||||||
* XXX move to 'main'
|
* XXX move to 'main'
|
||||||
*/
|
*/
|
||||||
if (!announce) {
|
if (!announce) {
|
||||||
|
PREPARE_WORK(&delayed, ack_packet);
|
||||||
static Block::Root root(_signal->ep(), env()->heap(), factory);
|
static Block::Root root(_signal->ep(), env()->heap(), factory);
|
||||||
env()->parent()->announce(_signal->ep().rpc_ep().manage(&root));
|
env()->parent()->announce(_signal->ep().rpc_ep().manage(&root));
|
||||||
announce = true;
|
announce = true;
|
||||||
|
@ -205,15 +223,15 @@ void scsi_add_device(struct scsi_device *sdev)
|
||||||
|
|
||||||
void Storage_device::_async_done(struct scsi_cmnd *cmnd)
|
void Storage_device::_async_done(struct scsi_cmnd *cmnd)
|
||||||
{
|
{
|
||||||
Block::Packet_descriptor *packet =
|
/*
|
||||||
static_cast<Block::Packet_descriptor *>(cmnd->packet);
|
* Schedule packet ack, because we are called here in USB storage thread
|
||||||
|
* context, the from code that will clear the command queue later, so we
|
||||||
|
* cannot send the next packet from here
|
||||||
|
*/
|
||||||
|
delayed.data = cmnd->packet;
|
||||||
|
schedule_work(&delayed);
|
||||||
|
|
||||||
if (verbose)
|
|
||||||
PDBG("ACK packet for block: %llu status: %d",
|
|
||||||
packet->block_number(), cmnd->result);
|
|
||||||
|
|
||||||
device->ack_packet(*packet);
|
|
||||||
Genode::destroy(Genode::env()->heap(), packet);
|
|
||||||
scsi_free_buffer(cmnd);
|
scsi_free_buffer(cmnd);
|
||||||
_scsi_free_command(cmnd);
|
_scsi_free_command(cmnd);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user