/* * Hypertransport interrupt support */ static void target_ht_irq(unsigned int irq, unsigned int dest, u8 vector) { struct ht_irq_msg msg; fetch_ht_irq_msg(irq, &msg); msg.address_lo &= ~(HT_IRQ_LOW_VECTOR_MASK | HT_IRQ_LOW_DEST_ID_MASK); msg.address_hi &= ~(HT_IRQ_HIGH_DEST_ID_MASK); msg.address_lo |= HT_IRQ_LOW_VECTOR(vector) | HT_IRQ_LOW_DEST_ID(dest); msg.address_hi |= HT_IRQ_HIGH_DEST_ID(dest); write_ht_irq_msg(irq, &msg); }
int arch_setup_ht_irq(unsigned int irq, struct pci_dev *dev) { struct irq_cfg *cfg; struct ht_irq_msg msg; unsigned dest; int err; if (disable_apic) return -ENXIO; cfg = irq_cfg(irq); err = assign_irq_vector(irq, cfg, apic->target_cpus()); if (err) return err; err = apic->cpu_mask_to_apicid_and(cfg->domain, apic->target_cpus(), &dest); if (err) return err; msg.address_hi = HT_IRQ_HIGH_DEST_ID(dest); msg.address_lo = HT_IRQ_LOW_BASE | HT_IRQ_LOW_DEST_ID(dest) | 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, &msg); irq_set_chip_and_handler_name(irq, &ht_irq_chip, handle_edge_irq, "edge"); dev_dbg(&dev->dev, "irq %d for HT\n", irq); return 0; }
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; }