static void irq_msi_compose_msg(struct irq_data *data, struct msi_msg *msg) { struct irq_cfg *cfg = irqd_cfg(data); msg->address_hi = MSI_ADDR_BASE_HI; if (x2apic_enabled()) msg->address_hi |= MSI_ADDR_EXT_DEST_ID(cfg->dest_apicid); msg->address_lo = MSI_ADDR_BASE_LO | ((apic->irq_dest_mode == 0) ? MSI_ADDR_DEST_MODE_PHYSICAL : MSI_ADDR_DEST_MODE_LOGICAL) | ((apic->irq_delivery_mode != dest_LowestPrio) ? MSI_ADDR_REDIRECTION_CPU : MSI_ADDR_REDIRECTION_LOWPRI) | MSI_ADDR_DEST_ID(cfg->dest_apicid); msg->data = MSI_DATA_TRIGGER_EDGE | MSI_DATA_LEVEL_ASSERT | ((apic->irq_delivery_mode != dest_LowestPrio) ? MSI_DATA_DELIVERY_FIXED : MSI_DATA_DELIVERY_LOWPRI) | MSI_DATA_VECTOR(cfg->vector); }
static int hyperv_irq_remapping_activate(struct irq_domain *domain, struct irq_data *irq_data, bool reserve) { struct irq_cfg *cfg = irqd_cfg(irq_data); struct IO_APIC_route_entry *entry = irq_data->chip_data; entry->dest = cfg->dest_apicid; entry->vector = cfg->vector; return 0; }
/* * Disable the specified MMR located on the specified blade so that MSIs are * longer allowed to be sent. */ static void uv_domain_deactivate(struct irq_domain *domain, struct irq_data *irq_data) { unsigned long mmr_value; struct uv_IO_APIC_route_entry *entry; mmr_value = 0; entry = (struct uv_IO_APIC_route_entry *)&mmr_value; entry->mask = 1; uv_program_mmr(irqd_cfg(irq_data), irq_data->chip_data); }
static int ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { struct irq_cfg *cfg = irqd_cfg(data); unsigned int dest; int ret; ret = apic_set_affinity(data, mask, &dest); if (ret) return ret; target_ht_irq(data->irq, dest, cfg->vector); return IRQ_SET_MASK_OK_NOCOPY; }
static int uv_set_irq_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { struct irq_data *parent = data->parent_data; struct irq_cfg *cfg = irqd_cfg(data); int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); if (ret >= 0) { uv_program_mmr(cfg, data->chip_data); send_cleanup_vector(cfg); } return ret; }
static void htirq_domain_activate(struct irq_domain *domain, struct irq_data *irq_data) { struct ht_irq_msg msg; struct irq_cfg *cfg = irqd_cfg(irq_data); msg.address_hi = HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid); msg.address_lo = HT_IRQ_LOW_BASE | HT_IRQ_LOW_DEST_ID(cfg->dest_apicid) | HT_IRQ_LOW_VECTOR(cfg->vector) | ((apic->irq_dest_mode == 0) ? HT_IRQ_LOW_DM_PHYSICAL : HT_IRQ_LOW_DM_LOGICAL) | HT_IRQ_LOW_RQEOI_EDGE | ((apic->irq_delivery_mode != dest_LowestPrio) ? HT_IRQ_LOW_MT_FIXED : HT_IRQ_LOW_MT_ARBITRATED) | HT_IRQ_LOW_IRQ_MASKED; write_ht_irq_msg(irq_data->irq, &msg); }
/* * Hypertransport interrupt support */ static int ht_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { struct irq_data *parent = data->parent_data; int ret; ret = parent->chip->irq_set_affinity(parent, mask, force); if (ret >= 0) { struct ht_irq_msg msg; struct irq_cfg *cfg = irqd_cfg(data); fetch_ht_irq_msg(data->irq, &msg); msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); msg.address_lo |= HT_IRQ_LOW_VECTOR(cfg->vector) | HT_IRQ_LOW_DEST_ID(cfg->dest_apicid); msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); msg.address_hi |= HT_IRQ_HIGH_DEST_ID(cfg->dest_apicid); write_ht_irq_msg(data->irq, &msg); } return ret; }
static int hyperv_ir_set_affinity(struct irq_data *data, const struct cpumask *mask, bool force) { struct irq_data *parent = data->parent_data; struct irq_cfg *cfg = irqd_cfg(data); struct IO_APIC_route_entry *entry; int ret; /* Return error If new irq affinity is out of ioapic_max_cpumask. */ if (!cpumask_subset(mask, &ioapic_max_cpumask)) return -EINVAL; ret = parent->chip->irq_set_affinity(parent, mask, force); if (ret < 0 || ret == IRQ_SET_MASK_OK_DONE) return ret; entry = data->chip_data; entry->dest = cfg->dest_apicid; entry->vector = cfg->vector; send_cleanup_vector(cfg); return 0; }
/* * Re-target the irq to the specified CPU and enable the specified MMR located * on the specified blade to allow the sending of MSIs to the specified CPU. */ static void uv_domain_activate(struct irq_domain *domain, struct irq_data *irq_data) { uv_program_mmr(irqd_cfg(irq_data), irq_data->chip_data); }