irqchip/gic-v3-its: Add its_vlpi_map helpers
Obtaining the mapping information for a VLPI is something quite common, and the GICv4.1 code is going to make even more use of it. Expose it as a separate set of helpers. Signed-off-by: Marc Zyngier <maz@kernel.org> Reviewed-by: Zenghui Yu <yuzenghui@huawei.com> Link: https://lore.kernel.org/r/20191027144234.8395-8-maz@kernel.org Link: https://lore.kernel.org/r/20191108165805.3071-8-maz@kernel.org
This commit is contained in:
Родитель
576a834297
Коммит
c1d4d5cd20
|
@ -207,6 +207,15 @@ static struct its_collection *dev_event_to_col(struct its_device *its_dev,
|
||||||
return its->collections + its_dev->event_map.col_map[event];
|
return its->collections + its_dev->event_map.col_map[event];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static struct its_vlpi_map *dev_event_to_vlpi_map(struct its_device *its_dev,
|
||||||
|
u32 event)
|
||||||
|
{
|
||||||
|
if (WARN_ON_ONCE(event >= its_dev->event_map.nr_lpis))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return &its_dev->event_map.vlpi_maps[event];
|
||||||
|
}
|
||||||
|
|
||||||
static struct its_collection *irq_to_col(struct irq_data *d)
|
static struct its_collection *irq_to_col(struct irq_data *d)
|
||||||
{
|
{
|
||||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||||
|
@ -971,7 +980,7 @@ static void its_send_invall(struct its_node *its, struct its_collection *col)
|
||||||
|
|
||||||
static void its_send_vmapti(struct its_device *dev, u32 id)
|
static void its_send_vmapti(struct its_device *dev, u32 id)
|
||||||
{
|
{
|
||||||
struct its_vlpi_map *map = &dev->event_map.vlpi_maps[id];
|
struct its_vlpi_map *map = dev_event_to_vlpi_map(dev, id);
|
||||||
struct its_cmd_desc desc;
|
struct its_cmd_desc desc;
|
||||||
|
|
||||||
desc.its_vmapti_cmd.vpe = map->vpe;
|
desc.its_vmapti_cmd.vpe = map->vpe;
|
||||||
|
@ -985,7 +994,7 @@ static void its_send_vmapti(struct its_device *dev, u32 id)
|
||||||
|
|
||||||
static void its_send_vmovi(struct its_device *dev, u32 id)
|
static void its_send_vmovi(struct its_device *dev, u32 id)
|
||||||
{
|
{
|
||||||
struct its_vlpi_map *map = &dev->event_map.vlpi_maps[id];
|
struct its_vlpi_map *map = dev_event_to_vlpi_map(dev, id);
|
||||||
struct its_cmd_desc desc;
|
struct its_cmd_desc desc;
|
||||||
|
|
||||||
desc.its_vmovi_cmd.vpe = map->vpe;
|
desc.its_vmovi_cmd.vpe = map->vpe;
|
||||||
|
@ -1063,20 +1072,26 @@ static void its_send_vinvall(struct its_node *its, struct its_vpe *vpe)
|
||||||
/*
|
/*
|
||||||
* irqchip functions - assumes MSI, mostly.
|
* irqchip functions - assumes MSI, mostly.
|
||||||
*/
|
*/
|
||||||
|
static struct its_vlpi_map *get_vlpi_map(struct irq_data *d)
|
||||||
|
{
|
||||||
|
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||||
|
u32 event = its_get_event_id(d);
|
||||||
|
|
||||||
|
if (!irqd_is_forwarded_to_vcpu(d))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return dev_event_to_vlpi_map(its_dev, event);
|
||||||
|
}
|
||||||
|
|
||||||
static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
|
static void lpi_write_config(struct irq_data *d, u8 clr, u8 set)
|
||||||
{
|
{
|
||||||
|
struct its_vlpi_map *map = get_vlpi_map(d);
|
||||||
irq_hw_number_t hwirq;
|
irq_hw_number_t hwirq;
|
||||||
void *va;
|
void *va;
|
||||||
u8 *cfg;
|
u8 *cfg;
|
||||||
|
|
||||||
if (irqd_is_forwarded_to_vcpu(d)) {
|
if (map) {
|
||||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
va = page_address(map->vm->vprop_page);
|
||||||
u32 event = its_get_event_id(d);
|
|
||||||
struct its_vlpi_map *map;
|
|
||||||
|
|
||||||
va = page_address(its_dev->event_map.vm->vprop_page);
|
|
||||||
map = &its_dev->event_map.vlpi_maps[event];
|
|
||||||
hwirq = map->vintid;
|
hwirq = map->vintid;
|
||||||
|
|
||||||
/* Remember the updated property */
|
/* Remember the updated property */
|
||||||
|
@ -1136,11 +1151,14 @@ static void its_vlpi_set_doorbell(struct irq_data *d, bool enable)
|
||||||
{
|
{
|
||||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||||
u32 event = its_get_event_id(d);
|
u32 event = its_get_event_id(d);
|
||||||
|
struct its_vlpi_map *map;
|
||||||
|
|
||||||
if (its_dev->event_map.vlpi_maps[event].db_enabled == enable)
|
map = dev_event_to_vlpi_map(its_dev, event);
|
||||||
|
|
||||||
|
if (map->db_enabled == enable)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
its_dev->event_map.vlpi_maps[event].db_enabled = enable;
|
map->db_enabled = enable;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* More fun with the architecture:
|
* More fun with the architecture:
|
||||||
|
@ -1369,19 +1387,18 @@ out:
|
||||||
static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
|
static int its_vlpi_get(struct irq_data *d, struct its_cmd_info *info)
|
||||||
{
|
{
|
||||||
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
struct its_device *its_dev = irq_data_get_irq_chip_data(d);
|
||||||
u32 event = its_get_event_id(d);
|
struct its_vlpi_map *map = get_vlpi_map(d);
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
mutex_lock(&its_dev->event_map.vlpi_lock);
|
mutex_lock(&its_dev->event_map.vlpi_lock);
|
||||||
|
|
||||||
if (!its_dev->event_map.vm ||
|
if (!its_dev->event_map.vm || !map->vm) {
|
||||||
!its_dev->event_map.vlpi_maps[event].vm) {
|
|
||||||
ret = -EINVAL;
|
ret = -EINVAL;
|
||||||
goto out;
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Copy our mapping information to the incoming request */
|
/* Copy our mapping information to the incoming request */
|
||||||
*info->map = its_dev->event_map.vlpi_maps[event];
|
*info->map = *map;
|
||||||
|
|
||||||
out:
|
out:
|
||||||
mutex_unlock(&its_dev->event_map.vlpi_lock);
|
mutex_unlock(&its_dev->event_map.vlpi_lock);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче