in ambassador.c [1495:1607]
static int create_queues(amb_dev *dev, unsigned int cmds, unsigned int txs,
unsigned int *rxs, unsigned int *rx_buffer_sizes)
{
unsigned char pool;
size_t total = 0;
void * memory;
void * limit;
PRINTD (DBG_FLOW, "create_queues %p", dev);
total += cmds * sizeof(command);
total += txs * (sizeof(tx_in) + sizeof(tx_out));
for (pool = 0; pool < NUM_RX_POOLS; ++pool)
total += rxs[pool] * (sizeof(rx_in) + sizeof(rx_out));
memory = kmalloc (total, GFP_KERNEL);
if (!memory) {
PRINTK (KERN_ERR, "could not allocate queues");
return -ENOMEM;
}
if (check_area (memory, total)) {
PRINTK (KERN_ERR, "queues allocated in nasty area");
kfree (memory);
return -ENOMEM;
}
limit = memory + total;
PRINTD (DBG_INIT, "queues from %p to %p", memory, limit);
PRINTD (DBG_CMD, "command queue at %p", memory);
{
command * cmd = memory;
amb_cq * cq = &dev->cq;
cq->pending = 0;
cq->high = 0;
cq->maximum = cmds - 1;
cq->ptrs.start = cmd;
cq->ptrs.in = cmd;
cq->ptrs.out = cmd;
cq->ptrs.limit = cmd + cmds;
memory = cq->ptrs.limit;
}
PRINTD (DBG_TX, "TX queue pair at %p", memory);
{
tx_in * in = memory;
tx_out * out;
amb_txq * txq = &dev->txq;
txq->pending = 0;
txq->high = 0;
txq->filled = 0;
txq->maximum = txs - 1;
txq->in.start = in;
txq->in.ptr = in;
txq->in.limit = in + txs;
memory = txq->in.limit;
out = memory;
txq->out.start = out;
txq->out.ptr = out;
txq->out.limit = out + txs;
memory = txq->out.limit;
}
PRINTD (DBG_RX, "RX queue pairs at %p", memory);
for (pool = 0; pool < NUM_RX_POOLS; ++pool) {
rx_in * in = memory;
rx_out * out;
amb_rxq * rxq = &dev->rxq[pool];
rxq->buffer_size = rx_buffer_sizes[pool];
rxq->buffers_wanted = 0;
rxq->pending = 0;
rxq->low = rxs[pool] - 1;
rxq->emptied = 0;
rxq->maximum = rxs[pool] - 1;
rxq->in.start = in;
rxq->in.ptr = in;
rxq->in.limit = in + rxs[pool];
memory = rxq->in.limit;
out = memory;
rxq->out.start = out;
rxq->out.ptr = out;
rxq->out.limit = out + rxs[pool];
memory = rxq->out.limit;
}
if (memory == limit) {
return 0;
} else {
PRINTK (KERN_ERR, "bad queue alloc %p != %p (tell maintainer)", memory, limit);
kfree (limit - total);
return -ENOMEM;
}
}