mirror of
https://github.com/genodelabs/genode.git
synced 2024-12-24 15:56:41 +00:00
usb_drv: raw session fixes
- use the correct memory free functions on errors - report packet submit errors - rename 'Usb::Packet_descriptor::transfer.timeout' as 'Usb::Packet_descriptor::transfer.polling_interval' Fixes #2135
This commit is contained in:
parent
44d4bf7a1b
commit
82e228a715
@ -297,7 +297,8 @@ class Usb::Worker
|
|||||||
urb *bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
|
urb *bulk_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
if (!bulk_urb) {
|
if (!bulk_urb) {
|
||||||
error("Failed to allocate bulk URB");
|
error("Failed to allocate bulk URB");
|
||||||
kfree(buf);
|
dma_free(buf);
|
||||||
|
p.error = Usb::Packet_descriptor::SUBMIT_ERROR;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -308,8 +309,15 @@ class Usb::Worker
|
|||||||
usb_fill_bulk_urb(bulk_urb, _device->udev, pipe, buf, p.size(),
|
usb_fill_bulk_urb(bulk_urb, _device->udev, pipe, buf, p.size(),
|
||||||
_async_complete, data);
|
_async_complete, data);
|
||||||
|
|
||||||
if (usb_submit_urb(bulk_urb, GFP_KERNEL))
|
int ret = usb_submit_urb(bulk_urb, GFP_KERNEL);
|
||||||
error("Failed to submit URB");
|
if (ret != 0) {
|
||||||
|
error("Failed to submit URB, error: ", ret);
|
||||||
|
p.error = Usb::Packet_descriptor::SUBMIT_ERROR;
|
||||||
|
kfree(data);
|
||||||
|
usb_free_urb(bulk_urb);
|
||||||
|
dma_free(buf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -332,7 +340,8 @@ class Usb::Worker
|
|||||||
urb *irq_urb = usb_alloc_urb(0, GFP_KERNEL);
|
urb *irq_urb = usb_alloc_urb(0, GFP_KERNEL);
|
||||||
if (!irq_urb) {
|
if (!irq_urb) {
|
||||||
error("Failed to allocate interrupt URB");
|
error("Failed to allocate interrupt URB");
|
||||||
kfree(buf);
|
dma_free(buf);
|
||||||
|
p.error = Usb::Packet_descriptor::SUBMIT_ERROR;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -340,11 +349,29 @@ class Usb::Worker
|
|||||||
data->packet = p;
|
data->packet = p;
|
||||||
data->worker = this;
|
data->worker = this;
|
||||||
|
|
||||||
usb_fill_int_urb(irq_urb, _device->udev, pipe, buf, p.size(),
|
int polling_interval;
|
||||||
_async_complete, data, p.transfer.timeout);
|
|
||||||
|
|
||||||
if (usb_submit_urb(irq_urb, GFP_KERNEL))
|
if (p.transfer.polling_interval == Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL) {
|
||||||
error("Failed to submit URB");
|
|
||||||
|
usb_host_endpoint *ep = read ? _device->udev->ep_in[p.transfer.ep & 0x0f]
|
||||||
|
: _device->udev->ep_out[p.transfer.ep & 0x0f];
|
||||||
|
polling_interval = ep->desc.bInterval;
|
||||||
|
|
||||||
|
} else
|
||||||
|
polling_interval = p.transfer.polling_interval;
|
||||||
|
|
||||||
|
usb_fill_int_urb(irq_urb, _device->udev, pipe, buf, p.size(),
|
||||||
|
_async_complete, data, polling_interval);
|
||||||
|
|
||||||
|
int ret = usb_submit_urb(irq_urb, GFP_KERNEL);
|
||||||
|
if (ret != 0) {
|
||||||
|
error("Failed to submit URB, error: ", ret);
|
||||||
|
p.error = Usb::Packet_descriptor::SUBMIT_ERROR;
|
||||||
|
kfree(data);
|
||||||
|
usb_free_urb(irq_urb);
|
||||||
|
dma_free(buf);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -436,10 +463,12 @@ class Usb::Worker
|
|||||||
case Packet_descriptor::BULK:
|
case Packet_descriptor::BULK:
|
||||||
if (_bulk(p, !!(p.transfer.ep & USB_DIR_IN)))
|
if (_bulk(p, !!(p.transfer.ep & USB_DIR_IN)))
|
||||||
continue;
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
case Packet_descriptor::IRQ:
|
case Packet_descriptor::IRQ:
|
||||||
if (_irq(p, !!(p.transfer.ep & USB_DIR_IN)))
|
if (_irq(p, !!(p.transfer.ep & USB_DIR_IN)))
|
||||||
continue;
|
continue;
|
||||||
|
break;
|
||||||
|
|
||||||
case Packet_descriptor::ALT_SETTING:
|
case Packet_descriptor::ALT_SETTING:
|
||||||
_alt_setting(p);
|
_alt_setting(p);
|
||||||
|
@ -139,7 +139,7 @@ struct Usb::Pl2303_driver : Completion
|
|||||||
Packet_descriptor p = iface.alloc(num_bytes);
|
Packet_descriptor p = iface.alloc(num_bytes);
|
||||||
|
|
||||||
memcpy(iface.content(p), dst, num_bytes);
|
memcpy(iface.content(p), dst, num_bytes);
|
||||||
iface.bulk_transfer(p, ep, 0, false, this);
|
iface.bulk_transfer(p, ep, false, this);
|
||||||
|
|
||||||
return num_bytes;
|
return num_bytes;
|
||||||
}
|
}
|
||||||
@ -196,7 +196,7 @@ struct Usb::Pl2303_driver : Completion
|
|||||||
Usb::Endpoint &ep = iface.endpoint(IN);
|
Usb::Endpoint &ep = iface.endpoint(IN);
|
||||||
for (int i = 0; i < PACKET_BUFFER; i++) {
|
for (int i = 0; i < PACKET_BUFFER; i++) {
|
||||||
p = iface.alloc(ep.max_packet_size);
|
p = iface.alloc(ep.max_packet_size);
|
||||||
iface.bulk_transfer(p, ep, 0, false, this);
|
iface.bulk_transfer(p, ep, false, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* send signal to terminal client */
|
/* send signal to terminal client */
|
||||||
|
@ -401,7 +401,6 @@ static void usb_host_handle_data(USBDevice *udev, USBPacket *p)
|
|||||||
Usb_host_device *dev = (Usb_host_device *)d->data;
|
Usb_host_device *dev = (Usb_host_device *)d->data;
|
||||||
|
|
||||||
Genode::size_t size = 0;
|
Genode::size_t size = 0;
|
||||||
unsigned timeout = 0;
|
|
||||||
Usb::Packet_descriptor::Type type = Usb::Packet_descriptor::BULK;
|
Usb::Packet_descriptor::Type type = Usb::Packet_descriptor::BULK;
|
||||||
|
|
||||||
switch (usb_ep_get_type(udev, p->pid, p->ep->nr)) {
|
switch (usb_ep_get_type(udev, p->pid, p->ep->nr)) {
|
||||||
@ -412,21 +411,6 @@ static void usb_host_handle_data(USBDevice *udev, USBPacket *p)
|
|||||||
case USB_ENDPOINT_XFER_INT:
|
case USB_ENDPOINT_XFER_INT:
|
||||||
type = Usb::Packet_descriptor::IRQ;
|
type = Usb::Packet_descriptor::IRQ;
|
||||||
size = p->iov.size;
|
size = p->iov.size;
|
||||||
|
|
||||||
/* values match usb_drv */
|
|
||||||
switch (udev->speed) {
|
|
||||||
case USB_SPEED_SUPER:
|
|
||||||
timeout = 1<<15;
|
|
||||||
break;
|
|
||||||
case USB_SPEED_HIGH:
|
|
||||||
timeout = 1<<13;
|
|
||||||
break;
|
|
||||||
case USB_SPEED_FULL:
|
|
||||||
case USB_SPEED_LOW:
|
|
||||||
timeout = 1<<7;
|
|
||||||
break;
|
|
||||||
default: break;
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
error("not supported data request");
|
error("not supported data request");
|
||||||
@ -436,9 +420,9 @@ static void usb_host_handle_data(USBDevice *udev, USBPacket *p)
|
|||||||
bool const in = p->pid == USB_TOKEN_IN;
|
bool const in = p->pid == USB_TOKEN_IN;
|
||||||
|
|
||||||
Usb::Packet_descriptor packet = dev->alloc_packet(size);
|
Usb::Packet_descriptor packet = dev->alloc_packet(size);
|
||||||
packet.type = type;
|
packet.type = type;
|
||||||
packet.transfer.ep = p->ep->nr | (in ? USB_DIR_IN : 0);
|
packet.transfer.ep = p->ep->nr | (in ? USB_DIR_IN : 0);
|
||||||
packet.transfer.timeout = timeout;
|
packet.transfer.polling_interval = Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL;
|
||||||
|
|
||||||
if (!in) {
|
if (!in) {
|
||||||
char * const content = dev->usb_raw.source()->packet_content(packet);
|
char * const content = dev->usb_raw.source()->packet_content(packet);
|
||||||
|
@ -320,7 +320,7 @@ class Usb::Interface : public Meta_data
|
|||||||
else _handler.submit(p);
|
else _handler.submit(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void bulk_transfer(Packet_descriptor &p, Endpoint &ep, int timeout,
|
void bulk_transfer(Packet_descriptor &p, Endpoint &ep,
|
||||||
bool block = true, Completion *c = nullptr)
|
bool block = true, Completion *c = nullptr)
|
||||||
{
|
{
|
||||||
_check();
|
_check();
|
||||||
@ -331,14 +331,15 @@ class Usb::Interface : public Meta_data
|
|||||||
p.type = Usb::Packet_descriptor::BULK;
|
p.type = Usb::Packet_descriptor::BULK;
|
||||||
p.succeded = false;
|
p.succeded = false;
|
||||||
p.transfer.ep = ep.address;
|
p.transfer.ep = ep.address;
|
||||||
p.transfer.timeout = timeout;
|
|
||||||
p.completion = c;
|
p.completion = c;
|
||||||
|
|
||||||
if(block) Sync_completion sync(_handler, p);
|
if(block) Sync_completion sync(_handler, p);
|
||||||
else _handler.submit(p);
|
else _handler.submit(p);
|
||||||
}
|
}
|
||||||
|
|
||||||
void interrupt_transfer(Packet_descriptor &p, Endpoint &ep, int timeout,
|
void interrupt_transfer(Packet_descriptor &p, Endpoint &ep,
|
||||||
|
int polling_interval =
|
||||||
|
Usb::Packet_descriptor::DEFAULT_POLLING_INTERVAL,
|
||||||
bool block = true, Completion *c = nullptr)
|
bool block = true, Completion *c = nullptr)
|
||||||
{
|
{
|
||||||
_check();
|
_check();
|
||||||
@ -346,11 +347,11 @@ class Usb::Interface : public Meta_data
|
|||||||
if (!ep.is_interrupt())
|
if (!ep.is_interrupt())
|
||||||
throw Session::Invalid_endpoint();
|
throw Session::Invalid_endpoint();
|
||||||
|
|
||||||
p.type = Usb::Packet_descriptor::IRQ;
|
p.type = Usb::Packet_descriptor::IRQ;
|
||||||
p.succeded = false;
|
p.succeded = false;
|
||||||
p.transfer.ep = ep.address;
|
p.transfer.ep = ep.address;
|
||||||
p.transfer.timeout = timeout;
|
p.transfer.polling_interval = polling_interval;
|
||||||
p.completion = c;
|
p.completion = c;
|
||||||
|
|
||||||
if(block) Sync_completion sync(_handler, p);
|
if(block) Sync_completion sync(_handler, p);
|
||||||
else _handler.submit(p);
|
else _handler.submit(p);
|
||||||
|
@ -35,6 +35,9 @@ struct Usb::Packet_descriptor : Genode::Packet_descriptor
|
|||||||
{
|
{
|
||||||
enum Type { STRING, CTRL, BULK, IRQ, ALT_SETTING, CONFIG, RELEASE_IF };
|
enum Type { STRING, CTRL, BULK, IRQ, ALT_SETTING, CONFIG, RELEASE_IF };
|
||||||
|
|
||||||
|
/* use the polling interval stated in the endpoint descriptor */
|
||||||
|
enum { DEFAULT_POLLING_INTERVAL = -1 };
|
||||||
|
|
||||||
Type type;
|
Type type;
|
||||||
bool succeded = false;
|
bool succeded = false;
|
||||||
Completion *completion = nullptr;
|
Completion *completion = nullptr;
|
||||||
@ -61,7 +64,7 @@ struct Usb::Packet_descriptor : Genode::Packet_descriptor
|
|||||||
{
|
{
|
||||||
uint8_t ep;
|
uint8_t ep;
|
||||||
int actual_size; /* returned */
|
int actual_size; /* returned */
|
||||||
int timeout;
|
int polling_interval; /* for interrupt transfers */
|
||||||
} transfer;
|
} transfer;
|
||||||
|
|
||||||
struct
|
struct
|
||||||
@ -76,7 +79,7 @@ struct Usb::Packet_descriptor : Genode::Packet_descriptor
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
enum Error { NO_ERROR, STALL_ERROR };
|
enum Error { NO_ERROR, STALL_ERROR, SUBMIT_ERROR };
|
||||||
|
|
||||||
Error error = NO_ERROR;
|
Error error = NO_ERROR;
|
||||||
|
|
||||||
|
@ -304,7 +304,7 @@ struct Usb::Block_driver : Usb::Completion,
|
|||||||
Usb::Endpoint &ep = iface.endpoint(OUT);
|
Usb::Endpoint &ep = iface.endpoint(OUT);
|
||||||
Usb::Packet_descriptor p = iface.alloc(CBW_VALID_SIZE);
|
Usb::Packet_descriptor p = iface.alloc(CBW_VALID_SIZE);
|
||||||
memcpy(iface.content(p), cb, CBW_VALID_SIZE);
|
memcpy(iface.content(p), cb, CBW_VALID_SIZE);
|
||||||
iface.bulk_transfer(p, ep, 0, block, &c);
|
iface.bulk_transfer(p, ep, block, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -316,7 +316,7 @@ struct Usb::Block_driver : Usb::Completion,
|
|||||||
Usb::Interface &iface = device.interface(active_interface);
|
Usb::Interface &iface = device.interface(active_interface);
|
||||||
Usb::Endpoint &ep = iface.endpoint(IN);
|
Usb::Endpoint &ep = iface.endpoint(IN);
|
||||||
Usb::Packet_descriptor p = iface.alloc(CSW_VALID_SIZE);
|
Usb::Packet_descriptor p = iface.alloc(CSW_VALID_SIZE);
|
||||||
iface.bulk_transfer(p, ep, 0, block, &c);
|
iface.bulk_transfer(p, ep, block, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -327,7 +327,7 @@ struct Usb::Block_driver : Usb::Completion,
|
|||||||
Usb::Interface &iface = device.interface(active_interface);
|
Usb::Interface &iface = device.interface(active_interface);
|
||||||
Usb::Endpoint &ep = iface.endpoint(IN);
|
Usb::Endpoint &ep = iface.endpoint(IN);
|
||||||
Usb::Packet_descriptor p = iface.alloc(size);
|
Usb::Packet_descriptor p = iface.alloc(size);
|
||||||
iface.bulk_transfer(p, ep, 0, block, &c);
|
iface.bulk_transfer(p, ep, block, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -548,7 +548,7 @@ struct Usb::Block_driver : Usb::Completion,
|
|||||||
|
|
||||||
if (!req.read) memcpy(iface.content(p), req.buffer, req.size);
|
if (!req.read) memcpy(iface.content(p), req.buffer, req.size);
|
||||||
|
|
||||||
iface.bulk_transfer(p, ep, 0, false, this);
|
iface.bulk_transfer(p, ep, false, this);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user