mirror of
https://github.com/genodelabs/genode.git
synced 2025-01-19 03:06:39 +00:00
usb: grab urb sizes from driver
Instead of hardcoding the values, ask the driver for the supported sizes and allocate the skb allocators accordingly.
This commit is contained in:
parent
9abf88c195
commit
c95a6c54ea
@ -47,38 +47,46 @@ struct sk_buff *_alloc_skb(unsigned int size, bool tx = true);
|
|||||||
/**
|
/**
|
||||||
* Skb-bitmap allocator
|
* Skb-bitmap allocator
|
||||||
*/
|
*/
|
||||||
template <unsigned ENTRIES, unsigned BUFFER>
|
|
||||||
class Skb
|
class Skb
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
|
||||||
enum {
|
unsigned const _entries;
|
||||||
IDX = ENTRIES / 32,
|
|
||||||
};
|
|
||||||
|
|
||||||
sk_buff _buf[ENTRIES];
|
sk_buff *_buf;
|
||||||
unsigned _free[ENTRIES / sizeof(unsigned)];
|
unsigned *_free;
|
||||||
unsigned _idx;
|
unsigned _idx;
|
||||||
bool _wait_free;
|
bool _wait_free;
|
||||||
|
|
||||||
|
enum { ENTRY_ELEMENT_SIZE = sizeof(_free[0]) * 8 };
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Skb() : _idx(0)
|
Skb(unsigned const entries, unsigned const buffer_size)
|
||||||
|
:
|
||||||
|
_entries(entries), _idx(0)
|
||||||
{
|
{
|
||||||
Genode::memset(_free, 0xff, sizeof(_free));
|
unsigned const size = _entries / sizeof(_free[0]);
|
||||||
|
|
||||||
for (unsigned i = 0; i < ENTRIES; i++)
|
_buf = new (Genode::env()->heap()) sk_buff[_entries];
|
||||||
_buf[i].start = (unsigned char *)kmalloc(BUFFER, GFP_NOIO);
|
_free = new (Genode::env()->heap()) unsigned[size];
|
||||||
|
|
||||||
|
Genode::memset(_free, 0xff, size * sizeof(_free[0]));
|
||||||
|
|
||||||
|
for (unsigned i = 0; i < _entries; i++)
|
||||||
|
_buf[i].start = (unsigned char *)kmalloc(buffer_size, GFP_NOIO);
|
||||||
}
|
}
|
||||||
|
|
||||||
sk_buff *alloc()
|
sk_buff *alloc()
|
||||||
{
|
{
|
||||||
for (register int i = 0; i < IDX; i++) {
|
unsigned const IDX = _entries / ENTRY_ELEMENT_SIZE;
|
||||||
|
|
||||||
|
for (register unsigned i = 0; i < IDX; i++) {
|
||||||
if (_free[_idx] != 0) {
|
if (_free[_idx] != 0) {
|
||||||
unsigned msb = Genode::log2(_free[_idx]);
|
unsigned msb = Genode::log2(_free[_idx]);
|
||||||
_free[_idx] ^= (1 << msb);
|
_free[_idx] ^= (1 << msb);
|
||||||
|
|
||||||
sk_buff *r = &_buf[(_idx * 32) + msb];
|
sk_buff *r = &_buf[(_idx * ENTRY_ELEMENT_SIZE) + msb];
|
||||||
r->data = r->start;
|
r->data = r->start;
|
||||||
r->phys = 0;
|
r->phys = 0;
|
||||||
r->cloned = 0;
|
r->cloned = 0;
|
||||||
@ -90,8 +98,9 @@ class Skb
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* wait until some SKBs are fred */
|
/* wait until some SKBs are freed */
|
||||||
_wait_free = false;
|
_wait_free = false;
|
||||||
|
PDBG("wait for free skbs ...");
|
||||||
_wait_event(_wait_free);
|
_wait_event(_wait_free);
|
||||||
|
|
||||||
return alloc();
|
return alloc();
|
||||||
@ -100,36 +109,28 @@ class Skb
|
|||||||
void free(sk_buff *buf)
|
void free(sk_buff *buf)
|
||||||
{
|
{
|
||||||
unsigned entry = buf - &_buf[0];
|
unsigned entry = buf - &_buf[0];
|
||||||
if (&_buf[0] > buf || entry > ENTRIES)
|
if (&_buf[0] > buf || entry > _entries)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
/* unblock waiting skb allocs */
|
/* unblock waiting skb allocs */
|
||||||
_wait_free = true;
|
_wait_free = true;
|
||||||
_idx = entry / 32;
|
_idx = entry / ENTRY_ELEMENT_SIZE;
|
||||||
_free[_idx] |= (1 << (entry % 32));
|
_free[_idx] |= (1 << (entry % ENTRY_ELEMENT_SIZE));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
/* smsc95xx.c */
|
|
||||||
enum { DEFAULT_HS_BURST_CAP_SIZE = 18944 };
|
|
||||||
|
|
||||||
/* send/receive skb type */
|
|
||||||
typedef Skb<50,DEFAULT_HS_BURST_CAP_SIZE> Tx_skb;
|
|
||||||
typedef Skb<32, DEFAULT_HS_BURST_CAP_SIZE> Rx_skb;
|
|
||||||
|
|
||||||
|
|
||||||
/* send/receive skb allocators */
|
/* send/receive skb allocators */
|
||||||
static Tx_skb *skb_tx()
|
static Skb *skb_tx(unsigned const elements = 0, unsigned const buffer_size = 0)
|
||||||
{
|
{
|
||||||
static Tx_skb _skb;
|
static Skb _skb(elements, buffer_size);
|
||||||
return &_skb;
|
return &_skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
static Rx_skb *skb_rx()
|
static Skb *skb_rx(unsigned const elements = 0, unsigned const buffer_size = 0)
|
||||||
{
|
{
|
||||||
static Rx_skb _skb;
|
static Skb _skb(elements, buffer_size);
|
||||||
return &_skb;
|
return &_skb;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -149,18 +150,31 @@ class Nic_device : public Nic::Device
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
struct net_device *_ndev; /* Linux-net device */
|
struct net_device *_ndev; /* Linux-net device */
|
||||||
fixup_t _tx_fixup;
|
fixup_t _tx_fixup;
|
||||||
|
bool const _burst;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
Nic_device(struct net_device *ndev) : _ndev(ndev)
|
Nic_device(struct net_device *ndev)
|
||||||
|
:
|
||||||
|
_ndev(ndev),
|
||||||
|
/* XXX should be configurable instead of guessing burst mode */
|
||||||
|
_burst(((usbnet *)netdev_priv(ndev))->rx_urb_size > 2048)
|
||||||
{
|
{
|
||||||
|
struct usbnet *dev = (usbnet *)netdev_priv(_ndev);
|
||||||
|
|
||||||
|
/* initialize skb allocators */
|
||||||
|
skb_rx(64, dev->rx_urb_size);
|
||||||
|
skb_tx(32, dev->rx_urb_size);
|
||||||
|
|
||||||
|
if (!burst()) return;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Retrieve 'tx_fixup' funcion from driver and set it to zero, so it
|
* Retrieve 'tx_fixup' function from driver and set it to zero,
|
||||||
* cannot be called by the actual driver.
|
* so it cannot be called by the actual driver. Required for
|
||||||
|
* burst mode.
|
||||||
*/
|
*/
|
||||||
struct usbnet *dev = (usbnet *)netdev_priv(ndev);
|
|
||||||
_tx_fixup = dev->driver_info->tx_fixup;
|
_tx_fixup = dev->driver_info->tx_fixup;
|
||||||
dev->driver_info->tx_fixup = 0;
|
dev->driver_info->tx_fixup = 0;
|
||||||
}
|
}
|
||||||
@ -194,7 +208,8 @@ class Nic_device : public Nic::Device
|
|||||||
*/
|
*/
|
||||||
sk_buff *alloc_skb()
|
sk_buff *alloc_skb()
|
||||||
{
|
{
|
||||||
sk_buff *skb = _alloc_skb(18944);
|
struct usbnet *dev = (usbnet *)netdev_priv(_ndev);
|
||||||
|
sk_buff *skb = _alloc_skb(dev->rx_urb_size);
|
||||||
skb->len = 0;
|
skb->len = 0;
|
||||||
return skb;
|
return skb;
|
||||||
}
|
}
|
||||||
@ -259,7 +274,7 @@ class Nic_device : public Nic::Device
|
|||||||
return m;
|
return m;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool burst() { return true; }
|
bool burst() { return _burst; }
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user