in ti/knav_qmss_queue.c [1211:1306]
static int knav_setup_queue_range(struct knav_device *kdev,
struct device_node *node)
{
struct device *dev = kdev->dev;
struct knav_range_info *range;
struct knav_qmgr_info *qmgr;
u32 temp[2], start, end, id, index;
int ret, i;
range = devm_kzalloc(dev, sizeof(*range), GFP_KERNEL);
if (!range) {
dev_err(dev, "out of memory allocating range\n");
return -ENOMEM;
}
range->kdev = kdev;
range->name = knav_queue_find_name(node);
ret = of_property_read_u32_array(node, "qrange", temp, 2);
if (!ret) {
range->queue_base = temp[0] - kdev->base_id;
range->num_queues = temp[1];
} else {
dev_err(dev, "invalid queue range %s\n", range->name);
devm_kfree(dev, range);
return -EINVAL;
}
for (i = 0; i < RANGE_MAX_IRQS; i++) {
struct of_phandle_args oirq;
if (of_irq_parse_one(node, i, &oirq))
break;
range->irqs[i].irq = irq_create_of_mapping(&oirq);
if (range->irqs[i].irq == IRQ_NONE)
break;
range->num_irqs++;
if (IS_ENABLED(CONFIG_SMP) && oirq.args_count == 3) {
unsigned long mask;
int bit;
range->irqs[i].cpu_mask = devm_kzalloc(dev,
cpumask_size(), GFP_KERNEL);
if (!range->irqs[i].cpu_mask)
return -ENOMEM;
mask = (oirq.args[2] & 0x0000ff00) >> 8;
for_each_set_bit(bit, &mask, BITS_PER_LONG)
cpumask_set_cpu(bit, range->irqs[i].cpu_mask);
}
}
range->num_irqs = min(range->num_irqs, range->num_queues);
if (range->num_irqs)
range->flags |= RANGE_HAS_IRQ;
if (of_get_property(node, "qalloc-by-id", NULL))
range->flags |= RANGE_RESERVED;
if (of_get_property(node, "accumulator", NULL)) {
ret = knav_init_acc_range(kdev, node, range);
if (ret < 0) {
devm_kfree(dev, range);
return ret;
}
} else {
range->ops = &knav_gp_range_ops;
}
/* set threshold to 1, and flush out the queues */
for_each_qmgr(kdev, qmgr) {
start = max(qmgr->start_queue, range->queue_base);
end = min(qmgr->start_queue + qmgr->num_queues,
range->queue_base + range->num_queues);
for (id = start; id < end; id++) {
index = id - qmgr->start_queue;
writel_relaxed(THRESH_GTE | 1,
&qmgr->reg_peek[index].ptr_size_thresh);
writel_relaxed(0,
&qmgr->reg_push[index].ptr_size_thresh);
}
}
list_add_tail(&range->list, &kdev->queue_ranges);
dev_dbg(dev, "added range %s: %d-%d, %d irqs%s%s%s\n",
range->name, range->queue_base,
range->queue_base + range->num_queues - 1,
range->num_irqs,
(range->flags & RANGE_HAS_IRQ) ? ", has irq" : "",
(range->flags & RANGE_RESERVED) ? ", reserved" : "",
(range->flags & RANGE_HAS_ACCUMULATOR) ? ", acc" : "");
kdev->num_queues_in_use += range->num_queues;
return 0;
}