| .. | .. |
|---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Interrupt management for most GSC and related devices. |
|---|
| 3 | 4 | * |
|---|
| .. | .. |
|---|
| 6 | 7 | * (c) Copyright 1999 Matthew Wilcox |
|---|
| 7 | 8 | * (c) Copyright 2000 Helge Deller |
|---|
| 8 | 9 | * (c) Copyright 2001 Matthew Wilcox for Hewlett-Packard |
|---|
| 9 | | - * |
|---|
| 10 | | - * This program is free software; you can redistribute it and/or modify |
|---|
| 11 | | - * it under the terms of the GNU General Public License as published by |
|---|
| 12 | | - * the Free Software Foundation; either version 2 of the License, or |
|---|
| 13 | | - * (at your option) any later version. |
|---|
| 14 | 10 | */ |
|---|
| 15 | 11 | |
|---|
| 16 | 12 | #include <linux/bitops.h> |
|---|
| .. | .. |
|---|
| 139 | 135 | */ |
|---|
| 140 | 136 | } |
|---|
| 141 | 137 | |
|---|
| 138 | +#ifdef CONFIG_SMP |
|---|
| 139 | +static int gsc_set_affinity_irq(struct irq_data *d, const struct cpumask *dest, |
|---|
| 140 | + bool force) |
|---|
| 141 | +{ |
|---|
| 142 | + struct gsc_asic *gsc_dev = irq_data_get_irq_chip_data(d); |
|---|
| 143 | + struct cpumask tmask; |
|---|
| 144 | + int cpu_irq; |
|---|
| 145 | + |
|---|
| 146 | + if (!cpumask_and(&tmask, dest, cpu_online_mask)) |
|---|
| 147 | + return -EINVAL; |
|---|
| 148 | + |
|---|
| 149 | + cpu_irq = cpu_check_affinity(d, &tmask); |
|---|
| 150 | + if (cpu_irq < 0) |
|---|
| 151 | + return cpu_irq; |
|---|
| 152 | + |
|---|
| 153 | + gsc_dev->gsc_irq.txn_addr = txn_affinity_addr(d->irq, cpu_irq); |
|---|
| 154 | + gsc_dev->eim = ((u32) gsc_dev->gsc_irq.txn_addr) | gsc_dev->gsc_irq.txn_data; |
|---|
| 155 | + |
|---|
| 156 | + /* switch IRQ's for devices below LASI/WAX to other CPU */ |
|---|
| 157 | + gsc_writel(gsc_dev->eim, gsc_dev->hpa + OFFSET_IAR); |
|---|
| 158 | + |
|---|
| 159 | + irq_data_update_effective_affinity(d, &tmask); |
|---|
| 160 | + |
|---|
| 161 | + return IRQ_SET_MASK_OK; |
|---|
| 162 | +} |
|---|
| 163 | +#endif |
|---|
| 164 | + |
|---|
| 165 | + |
|---|
| 142 | 166 | static struct irq_chip gsc_asic_interrupt_type = { |
|---|
| 143 | 167 | .name = "GSC-ASIC", |
|---|
| 144 | 168 | .irq_unmask = gsc_asic_unmask_irq, |
|---|
| 145 | 169 | .irq_mask = gsc_asic_mask_irq, |
|---|
| 170 | +#ifdef CONFIG_SMP |
|---|
| 171 | + .irq_set_affinity = gsc_set_affinity_irq, |
|---|
| 172 | +#endif |
|---|
| 146 | 173 | }; |
|---|
| 147 | 174 | |
|---|
| 148 | 175 | int gsc_assign_irq(struct irq_chip *type, void *data) |
|---|