static int uv_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *arg) { struct uv_irq_2_mmr_pnode *chip_data; struct irq_alloc_info *info = arg; struct irq_data *irq_data = irq_domain_get_irq_data(domain, virq); int ret; if (nr_irqs > 1 || !info || info->type != X86_IRQ_ALLOC_TYPE_UV) return -EINVAL; chip_data = kmalloc_node(sizeof(*chip_data), GFP_KERNEL, irq_data_get_node(irq_data)); if (!chip_data) return -ENOMEM; ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, arg); if (ret >= 0) { if (info->uv_limit == UV_AFFINITY_CPU) irq_set_status_flags(virq, IRQ_NO_BALANCING); else irq_set_status_flags(virq, IRQ_MOVE_PCNTXT); chip_data->pnode = uv_blade_to_pnode(info->uv_blade); chip_data->offset = info->uv_offset; irq_domain_set_info(domain, virq, virq, &uv_irq_chip, chip_data, handle_percpu_irq, NULL, info->uv_name); } else { kfree(chip_data); } return ret; }
static int dmar_msi_init(struct irq_domain *domain, struct msi_domain_info *info, unsigned int virq, irq_hw_number_t hwirq, msi_alloc_info_t *arg) { irq_domain_set_info(domain, virq, arg->dmar_id, info->chip, NULL, handle_edge_irq, arg->dmar_data, "edge"); return 0; }
static int hpet_msi_init(struct irq_domain *domain, struct msi_domain_info *info, unsigned int virq, irq_hw_number_t hwirq, msi_alloc_info_t *arg) { irq_set_status_flags(virq, IRQ_MOVE_PCNTXT); irq_domain_set_info(domain, virq, arg->hpet_index, info->chip, NULL, handle_edge_irq, arg->hpet_data, "edge"); return 0; }
static int htirq_domain_alloc(struct irq_domain *domain, unsigned int virq, unsigned int nr_irqs, void *arg) { struct ht_irq_cfg *ht_cfg; struct irq_alloc_info *info = arg; struct pci_dev *dev; irq_hw_number_t hwirq; int ret; if (nr_irqs > 1 || !info) return -EINVAL; dev = info->ht_dev; hwirq = (info->ht_idx & 0xFF) | PCI_DEVID(dev->bus->number, dev->devfn) << 8 | (pci_domain_nr(dev->bus) & 0xFFFFFFFF) << 24; if (irq_find_mapping(domain, hwirq) > 0) return -EEXIST; ht_cfg = kmalloc(sizeof(*ht_cfg), GFP_KERNEL); if (!ht_cfg) return -ENOMEM; ret = irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, info); if (ret < 0) { kfree(ht_cfg); return ret; } /* Initialize msg to a value that will never match the first write. */ ht_cfg->msg.address_lo = 0xffffffff; ht_cfg->msg.address_hi = 0xffffffff; ht_cfg->dev = info->ht_dev; ht_cfg->update = info->ht_update; ht_cfg->pos = info->ht_pos; ht_cfg->idx = 0x10 + (info->ht_idx * 2); irq_domain_set_info(domain, virq, hwirq, &ht_irq_chip, ht_cfg, handle_edge_irq, ht_cfg, "edge"); return 0; }