.. | .. |
---|
| 1 | +// SPDX-License-Identifier: GPL-2.0-or-later |
---|
1 | 2 | /* |
---|
2 | 3 | ** DINO manager |
---|
3 | 4 | ** |
---|
.. | .. |
---|
5 | 6 | ** (c) Copyright 1999 SuSE GmbH |
---|
6 | 7 | ** (c) Copyright 1999,2000 Hewlett-Packard Company |
---|
7 | 8 | ** (c) Copyright 2000 Grant Grundler |
---|
8 | | -** (c) Copyright 2006 Helge Deller |
---|
| 9 | +** (c) Copyright 2006-2019 Helge Deller |
---|
9 | 10 | ** |
---|
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 | 11 | ** |
---|
15 | 12 | ** This module provides access to Dino PCI bus (config/IOport spaces) |
---|
16 | 13 | ** and helps manage Dino IRQ lines. |
---|
.. | .. |
---|
59 | 56 | #include <asm/hardware.h> |
---|
60 | 57 | |
---|
61 | 58 | #include "gsc.h" |
---|
| 59 | +#include "iommu.h" |
---|
62 | 60 | |
---|
63 | 61 | #undef DINO_DEBUG |
---|
64 | 62 | |
---|
.. | .. |
---|
144 | 142 | { |
---|
145 | 143 | struct pci_hba_data hba; /* 'C' inheritance - must be first */ |
---|
146 | 144 | spinlock_t dinosaur_pen; |
---|
147 | | - unsigned long txn_addr; /* EIR addr to generate interrupt */ |
---|
148 | | - u32 txn_data; /* EIR data assign to each dino */ |
---|
149 | 145 | u32 imr; /* IRQ's which are enabled */ |
---|
| 146 | + struct gsc_irq gsc_irq; |
---|
150 | 147 | int global_irq[DINO_LOCAL_IRQS]; /* map IMR bit to global irq */ |
---|
151 | 148 | #ifdef DINO_DEBUG |
---|
152 | 149 | unsigned int dino_irr0; /* save most recent IRQ line stat */ |
---|
153 | 150 | #endif |
---|
154 | 151 | }; |
---|
155 | 152 | |
---|
156 | | -/* Looks nice and keeps the compiler happy */ |
---|
157 | | -#define DINO_DEV(d) ({ \ |
---|
158 | | - void *__pdata = d; \ |
---|
159 | | - BUG_ON(!__pdata); \ |
---|
160 | | - (struct dino_device *)__pdata; }) |
---|
161 | | - |
---|
| 153 | +static inline struct dino_device *DINO_DEV(struct pci_hba_data *hba) |
---|
| 154 | +{ |
---|
| 155 | + return container_of(hba, struct dino_device, hba); |
---|
| 156 | +} |
---|
162 | 157 | |
---|
163 | 158 | /* |
---|
164 | 159 | * Dino Configuration Space Accessor Functions |
---|
.. | .. |
---|
343 | 338 | if (tmp & DINO_MASK_IRQ(local_irq)) { |
---|
344 | 339 | DBG(KERN_WARNING "%s(): IRQ asserted! (ILR 0x%x)\n", |
---|
345 | 340 | __func__, tmp); |
---|
346 | | - gsc_writel(dino_dev->txn_data, dino_dev->txn_addr); |
---|
| 341 | + gsc_writel(dino_dev->gsc_irq.txn_data, dino_dev->gsc_irq.txn_addr); |
---|
347 | 342 | } |
---|
348 | 343 | } |
---|
| 344 | + |
---|
| 345 | +#ifdef CONFIG_SMP |
---|
| 346 | +static int dino_set_affinity_irq(struct irq_data *d, const struct cpumask *dest, |
---|
| 347 | + bool force) |
---|
| 348 | +{ |
---|
| 349 | + struct dino_device *dino_dev = irq_data_get_irq_chip_data(d); |
---|
| 350 | + struct cpumask tmask; |
---|
| 351 | + int cpu_irq; |
---|
| 352 | + u32 eim; |
---|
| 353 | + |
---|
| 354 | + if (!cpumask_and(&tmask, dest, cpu_online_mask)) |
---|
| 355 | + return -EINVAL; |
---|
| 356 | + |
---|
| 357 | + cpu_irq = cpu_check_affinity(d, &tmask); |
---|
| 358 | + if (cpu_irq < 0) |
---|
| 359 | + return cpu_irq; |
---|
| 360 | + |
---|
| 361 | + dino_dev->gsc_irq.txn_addr = txn_affinity_addr(d->irq, cpu_irq); |
---|
| 362 | + eim = ((u32) dino_dev->gsc_irq.txn_addr) | dino_dev->gsc_irq.txn_data; |
---|
| 363 | + __raw_writel(eim, dino_dev->hba.base_addr+DINO_IAR0); |
---|
| 364 | + |
---|
| 365 | + irq_data_update_effective_affinity(d, &tmask); |
---|
| 366 | + |
---|
| 367 | + return IRQ_SET_MASK_OK; |
---|
| 368 | +} |
---|
| 369 | +#endif |
---|
349 | 370 | |
---|
350 | 371 | static struct irq_chip dino_interrupt_type = { |
---|
351 | 372 | .name = "GSC-PCI", |
---|
352 | 373 | .irq_unmask = dino_unmask_irq, |
---|
353 | 374 | .irq_mask = dino_mask_irq, |
---|
| 375 | +#ifdef CONFIG_SMP |
---|
| 376 | + .irq_set_affinity = dino_set_affinity_irq, |
---|
| 377 | +#endif |
---|
354 | 378 | }; |
---|
355 | 379 | |
---|
356 | 380 | |
---|
.. | .. |
---|
382 | 406 | DBG(KERN_DEBUG "%s(%d, %p) mask 0x%x\n", |
---|
383 | 407 | __func__, irq, intr_dev, mask); |
---|
384 | 408 | generic_handle_irq(irq); |
---|
385 | | - mask &= ~(1 << local_irq); |
---|
| 409 | + mask &= ~DINO_MASK_IRQ(local_irq); |
---|
386 | 410 | } while (mask); |
---|
387 | 411 | |
---|
388 | 412 | /* Support for level triggered IRQ lines. |
---|
.. | .. |
---|
396 | 420 | if (mask) { |
---|
397 | 421 | if (--ilr_loop > 0) |
---|
398 | 422 | goto ilr_again; |
---|
399 | | - printk(KERN_ERR "Dino 0x%px: stuck interrupt %d\n", |
---|
| 423 | + pr_warn_ratelimited("Dino 0x%px: stuck interrupt %d\n", |
---|
400 | 424 | dino_dev->hba.base_addr, mask); |
---|
401 | | - return IRQ_NONE; |
---|
402 | 425 | } |
---|
403 | 426 | return IRQ_HANDLED; |
---|
404 | 427 | } |
---|
.. | .. |
---|
811 | 834 | { |
---|
812 | 835 | int status; |
---|
813 | 836 | u32 eim; |
---|
814 | | - struct gsc_irq gsc_irq; |
---|
815 | 837 | struct resource *res; |
---|
816 | 838 | |
---|
817 | 839 | pcibios_register_hba(&dino_dev->hba); |
---|
.. | .. |
---|
826 | 848 | ** still only has 11 IRQ input lines - just map some of them |
---|
827 | 849 | ** to a different processor. |
---|
828 | 850 | */ |
---|
829 | | - dev->irq = gsc_alloc_irq(&gsc_irq); |
---|
830 | | - dino_dev->txn_addr = gsc_irq.txn_addr; |
---|
831 | | - dino_dev->txn_data = gsc_irq.txn_data; |
---|
832 | | - eim = ((u32) gsc_irq.txn_addr) | gsc_irq.txn_data; |
---|
| 851 | + dev->irq = gsc_alloc_irq(&dino_dev->gsc_irq); |
---|
| 852 | + eim = ((u32) dino_dev->gsc_irq.txn_addr) | dino_dev->gsc_irq.txn_data; |
---|
833 | 853 | |
---|
834 | 854 | /* |
---|
835 | 855 | ** Dino needs a PA "IRQ" to get a processor's attention. |
---|
.. | .. |
---|
892 | 912 | #define CUJO_RAVEN_BADPAGE 0x01003000UL |
---|
893 | 913 | #define CUJO_FIREHAWK_BADPAGE 0x01607000UL |
---|
894 | 914 | |
---|
895 | | -static const char *dino_vers[] = { |
---|
| 915 | +static const char dino_vers[][4] = { |
---|
896 | 916 | "2.0", |
---|
897 | 917 | "2.1", |
---|
898 | 918 | "3.0", |
---|
899 | 919 | "3.1" |
---|
900 | 920 | }; |
---|
901 | 921 | |
---|
902 | | -static const char *cujo_vers[] = { |
---|
| 922 | +static const char cujo_vers[][4] = { |
---|
903 | 923 | "1.0", |
---|
904 | 924 | "2.0" |
---|
905 | 925 | }; |
---|
.. | .. |
---|
979 | 999 | } |
---|
980 | 1000 | |
---|
981 | 1001 | dino_dev->hba.dev = dev; |
---|
982 | | - dino_dev->hba.base_addr = ioremap_nocache(hpa, 4096); |
---|
| 1002 | + dino_dev->hba.base_addr = ioremap(hpa, 4096); |
---|
983 | 1003 | dino_dev->hba.lmmio_space_offset = PCI_F_EXTEND; |
---|
984 | 1004 | spin_lock_init(&dino_dev->dinosaur_pen); |
---|
985 | 1005 | dino_dev->hba.iommu = ccio_get_iommu(dev); |
---|