Merge branch 'linus' into irq/core
Pull in upstream fixes before applying conflicting changes
This commit is contained in:
@@ -74,6 +74,13 @@ struct its_node {
|
||||
|
||||
#define ITS_ITT_ALIGN SZ_256
|
||||
|
||||
struct event_lpi_map {
|
||||
unsigned long *lpi_map;
|
||||
u16 *col_map;
|
||||
irq_hw_number_t lpi_base;
|
||||
int nr_lpis;
|
||||
};
|
||||
|
||||
/*
|
||||
* The ITS view of a device - belongs to an ITS, a collection, owns an
|
||||
* interrupt translation table, and a list of interrupts.
|
||||
@@ -81,11 +88,8 @@ struct its_node {
|
||||
struct its_device {
|
||||
struct list_head entry;
|
||||
struct its_node *its;
|
||||
struct its_collection *collection;
|
||||
struct event_lpi_map event_map;
|
||||
void *itt;
|
||||
unsigned long *lpi_map;
|
||||
irq_hw_number_t lpi_base;
|
||||
int nr_lpis;
|
||||
u32 nr_ites;
|
||||
u32 device_id;
|
||||
};
|
||||
@@ -98,6 +102,14 @@ static struct rdists *gic_rdists;
|
||||
#define gic_data_rdist() (raw_cpu_ptr(gic_rdists->rdist))
|
||||
#define gic_data_rdist_rd_base() (gic_data_rdist()->rd_base)
|
||||
|
||||
static struct its_collection *dev_event_to_col(struct its_device *its_dev,
|
||||
u32 event)
|
||||
{
|
||||
struct its_node *its = its_dev->its;
|
||||
|
||||
return its->collections + its_dev->event_map.col_map[event];
|
||||
}
|
||||
|
||||
/*
|
||||
* ITS command descriptors - parameters to be encoded in a command
|
||||
* block.
|
||||
@@ -133,7 +145,7 @@ struct its_cmd_desc {
|
||||
struct {
|
||||
struct its_device *dev;
|
||||
struct its_collection *col;
|
||||
u32 id;
|
||||
u32 event_id;
|
||||
} its_movi_cmd;
|
||||
|
||||
struct {
|
||||
@@ -240,7 +252,7 @@ static struct its_collection *its_build_mapd_cmd(struct its_cmd_block *cmd,
|
||||
|
||||
its_fixup_cmd(cmd);
|
||||
|
||||
return desc->its_mapd_cmd.dev->collection;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct its_collection *its_build_mapc_cmd(struct its_cmd_block *cmd,
|
||||
@@ -259,52 +271,72 @@ static struct its_collection *its_build_mapc_cmd(struct its_cmd_block *cmd,
|
||||
static struct its_collection *its_build_mapvi_cmd(struct its_cmd_block *cmd,
|
||||
struct its_cmd_desc *desc)
|
||||
{
|
||||
struct its_collection *col;
|
||||
|
||||
col = dev_event_to_col(desc->its_mapvi_cmd.dev,
|
||||
desc->its_mapvi_cmd.event_id);
|
||||
|
||||
its_encode_cmd(cmd, GITS_CMD_MAPVI);
|
||||
its_encode_devid(cmd, desc->its_mapvi_cmd.dev->device_id);
|
||||
its_encode_event_id(cmd, desc->its_mapvi_cmd.event_id);
|
||||
its_encode_phys_id(cmd, desc->its_mapvi_cmd.phys_id);
|
||||
its_encode_collection(cmd, desc->its_mapvi_cmd.dev->collection->col_id);
|
||||
its_encode_collection(cmd, col->col_id);
|
||||
|
||||
its_fixup_cmd(cmd);
|
||||
|
||||
return desc->its_mapvi_cmd.dev->collection;
|
||||
return col;
|
||||
}
|
||||
|
||||
static struct its_collection *its_build_movi_cmd(struct its_cmd_block *cmd,
|
||||
struct its_cmd_desc *desc)
|
||||
{
|
||||
struct its_collection *col;
|
||||
|
||||
col = dev_event_to_col(desc->its_movi_cmd.dev,
|
||||
desc->its_movi_cmd.event_id);
|
||||
|
||||
its_encode_cmd(cmd, GITS_CMD_MOVI);
|
||||
its_encode_devid(cmd, desc->its_movi_cmd.dev->device_id);
|
||||
its_encode_event_id(cmd, desc->its_movi_cmd.id);
|
||||
its_encode_event_id(cmd, desc->its_movi_cmd.event_id);
|
||||
its_encode_collection(cmd, desc->its_movi_cmd.col->col_id);
|
||||
|
||||
its_fixup_cmd(cmd);
|
||||
|
||||
return desc->its_movi_cmd.dev->collection;
|
||||
return col;
|
||||
}
|
||||
|
||||
static struct its_collection *its_build_discard_cmd(struct its_cmd_block *cmd,
|
||||
struct its_cmd_desc *desc)
|
||||
{
|
||||
struct its_collection *col;
|
||||
|
||||
col = dev_event_to_col(desc->its_discard_cmd.dev,
|
||||
desc->its_discard_cmd.event_id);
|
||||
|
||||
its_encode_cmd(cmd, GITS_CMD_DISCARD);
|
||||
its_encode_devid(cmd, desc->its_discard_cmd.dev->device_id);
|
||||
its_encode_event_id(cmd, desc->its_discard_cmd.event_id);
|
||||
|
||||
its_fixup_cmd(cmd);
|
||||
|
||||
return desc->its_discard_cmd.dev->collection;
|
||||
return col;
|
||||
}
|
||||
|
||||
static struct its_collection *its_build_inv_cmd(struct its_cmd_block *cmd,
|
||||
struct its_cmd_desc *desc)
|
||||
{
|
||||
struct its_collection *col;
|
||||
|
||||
col = dev_event_to_col(desc->its_inv_cmd.dev,
|
||||
desc->its_inv_cmd.event_id);
|
||||
|
||||
its_encode_cmd(cmd, GITS_CMD_INV);
|
||||
its_encode_devid(cmd, desc->its_inv_cmd.dev->device_id);
|
||||
its_encode_event_id(cmd, desc->its_inv_cmd.event_id);
|
||||
|
||||
its_fixup_cmd(cmd);
|
||||
|
||||
return desc->its_inv_cmd.dev->collection;
|
||||
return col;
|
||||
}
|
||||
|
||||
static struct its_collection *its_build_invall_cmd(struct its_cmd_block *cmd,
|
||||
@@ -496,7 +528,7 @@ static void its_send_movi(struct its_device *dev,
|
||||
|
||||
desc.its_movi_cmd.dev = dev;
|
||||
desc.its_movi_cmd.col = col;
|
||||
desc.its_movi_cmd.id = id;
|
||||
desc.its_movi_cmd.event_id = id;
|
||||
|
||||
its_send_single_command(dev->its, its_build_movi_cmd, &desc);
|
||||
}
|
||||
@@ -527,7 +559,7 @@ static void its_send_invall(struct its_node *its, struct its_collection *col)
|
||||
static inline u32 its_get_event_id(struct irq_data *d)
|
||||
{
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
return d->hwirq - its_dev->lpi_base;
|
||||
return d->hwirq - its_dev->event_map.lpi_base;
|
||||
}
|
||||
|
||||
static void lpi_set_config(struct irq_data *d, bool enable)
|
||||
@@ -582,7 +614,7 @@ static int its_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
|
||||
|
||||
target_col = &its_dev->its->collections[cpu];
|
||||
its_send_movi(its_dev, target_col, id);
|
||||
its_dev->collection = target_col;
|
||||
its_dev->event_map.col_map[id] = cpu;
|
||||
|
||||
return IRQ_SET_MASK_OK_DONE;
|
||||
}
|
||||
@@ -712,8 +744,10 @@ out:
|
||||
return bitmap;
|
||||
}
|
||||
|
||||
static void its_lpi_free(unsigned long *bitmap, int base, int nr_ids)
|
||||
static void its_lpi_free(struct event_lpi_map *map)
|
||||
{
|
||||
int base = map->lpi_base;
|
||||
int nr_ids = map->nr_lpis;
|
||||
int lpi;
|
||||
|
||||
spin_lock(&lpi_lock);
|
||||
@@ -730,7 +764,8 @@ static void its_lpi_free(unsigned long *bitmap, int base, int nr_ids)
|
||||
|
||||
spin_unlock(&lpi_lock);
|
||||
|
||||
kfree(bitmap);
|
||||
kfree(map->lpi_map);
|
||||
kfree(map->col_map);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -1098,11 +1133,11 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
|
||||
struct its_device *dev;
|
||||
unsigned long *lpi_map;
|
||||
unsigned long flags;
|
||||
u16 *col_map = NULL;
|
||||
void *itt;
|
||||
int lpi_base;
|
||||
int nr_lpis;
|
||||
int nr_ites;
|
||||
int cpu;
|
||||
int sz;
|
||||
|
||||
dev = kzalloc(sizeof(*dev), GFP_KERNEL);
|
||||
@@ -1116,20 +1151,24 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
|
||||
sz = max(sz, ITS_ITT_ALIGN) + ITS_ITT_ALIGN - 1;
|
||||
itt = kzalloc(sz, GFP_KERNEL);
|
||||
lpi_map = its_lpi_alloc_chunks(nvecs, &lpi_base, &nr_lpis);
|
||||
if (lpi_map)
|
||||
col_map = kzalloc(sizeof(*col_map) * nr_lpis, GFP_KERNEL);
|
||||
|
||||
if (!dev || !itt || !lpi_map) {
|
||||
if (!dev || !itt || !lpi_map || !col_map) {
|
||||
kfree(dev);
|
||||
kfree(itt);
|
||||
kfree(lpi_map);
|
||||
kfree(col_map);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
dev->its = its;
|
||||
dev->itt = itt;
|
||||
dev->nr_ites = nr_ites;
|
||||
dev->lpi_map = lpi_map;
|
||||
dev->lpi_base = lpi_base;
|
||||
dev->nr_lpis = nr_lpis;
|
||||
dev->event_map.lpi_map = lpi_map;
|
||||
dev->event_map.col_map = col_map;
|
||||
dev->event_map.lpi_base = lpi_base;
|
||||
dev->event_map.nr_lpis = nr_lpis;
|
||||
dev->device_id = dev_id;
|
||||
INIT_LIST_HEAD(&dev->entry);
|
||||
|
||||
@@ -1137,10 +1176,6 @@ static struct its_device *its_create_device(struct its_node *its, u32 dev_id,
|
||||
list_add(&dev->entry, &its->its_device_list);
|
||||
raw_spin_unlock_irqrestore(&its->lock, flags);
|
||||
|
||||
/* Bind the device to the first possible CPU */
|
||||
cpu = cpumask_first(cpu_online_mask);
|
||||
dev->collection = &its->collections[cpu];
|
||||
|
||||
/* Map device to its ITT */
|
||||
its_send_mapd(dev, 1);
|
||||
|
||||
@@ -1162,12 +1197,13 @@ static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
|
||||
{
|
||||
int idx;
|
||||
|
||||
idx = find_first_zero_bit(dev->lpi_map, dev->nr_lpis);
|
||||
if (idx == dev->nr_lpis)
|
||||
idx = find_first_zero_bit(dev->event_map.lpi_map,
|
||||
dev->event_map.nr_lpis);
|
||||
if (idx == dev->event_map.nr_lpis)
|
||||
return -ENOSPC;
|
||||
|
||||
*hwirq = dev->lpi_base + idx;
|
||||
set_bit(idx, dev->lpi_map);
|
||||
*hwirq = dev->event_map.lpi_base + idx;
|
||||
set_bit(idx, dev->event_map.lpi_map);
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -1287,7 +1323,8 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
|
||||
irq_domain_set_hwirq_and_chip(domain, virq + i,
|
||||
hwirq, &its_irq_chip, its_dev);
|
||||
dev_dbg(info->scratchpad[1].ptr, "ID:%d pID:%d vID:%d\n",
|
||||
(int)(hwirq - its_dev->lpi_base), (int)hwirq, virq + i);
|
||||
(int)(hwirq - its_dev->event_map.lpi_base),
|
||||
(int)hwirq, virq + i);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -1299,6 +1336,9 @@ static void its_irq_domain_activate(struct irq_domain *domain,
|
||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||
u32 event = its_get_event_id(d);
|
||||
|
||||
/* Bind the LPI to the first possible CPU */
|
||||
its_dev->event_map.col_map[event] = cpumask_first(cpu_online_mask);
|
||||
|
||||
/* Map the GIC IRQ and event to the device */
|
||||
its_send_mapvi(its_dev, d->hwirq, event);
|
||||
}
|
||||
@@ -1326,17 +1366,16 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
|
||||
u32 event = its_get_event_id(data);
|
||||
|
||||
/* Mark interrupt index as unused */
|
||||
clear_bit(event, its_dev->lpi_map);
|
||||
clear_bit(event, its_dev->event_map.lpi_map);
|
||||
|
||||
/* Nuke the entry in the domain */
|
||||
irq_domain_reset_irq_data(data);
|
||||
}
|
||||
|
||||
/* If all interrupts have been freed, start mopping the floor */
|
||||
if (bitmap_empty(its_dev->lpi_map, its_dev->nr_lpis)) {
|
||||
its_lpi_free(its_dev->lpi_map,
|
||||
its_dev->lpi_base,
|
||||
its_dev->nr_lpis);
|
||||
if (bitmap_empty(its_dev->event_map.lpi_map,
|
||||
its_dev->event_map.nr_lpis)) {
|
||||
its_lpi_free(&its_dev->event_map);
|
||||
|
||||
/* Unmap device/itt */
|
||||
its_send_mapd(its_dev, 0);
|
||||
|
Reference in New Issue
Block a user