static int create_queues()

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;
  }
  
}