* [PATCH 14/23] kernel: generic counter for interrupt errors
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
We currently have counters for spurious interrupt spread over all the
individual architectures. Mostly done in the arch's ack_bad_irq(),
sometimes also in arch specific drivers.
It's time to consolidate this code duplication:
* introduce a global counter and inlined accessors
* increase the counter in all call sites of ack_bad_irq()
* subsequent patches will transform the individual archs one by one
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
include/asm-generic/irq-err.h | 17 +++++++++++++++++
kernel/irq/dummychip.c | 2 ++
kernel/irq/handle.c | 4 ++++
kernel/irq/irqdesc.c | 2 ++
4 files changed, 25 insertions(+)
create mode 100644 include/asm-generic/irq-err.h
diff --git a/include/asm-generic/irq-err.h b/include/asm-generic/irq-err.h
new file mode 100644
index 000000000000..33c75eb50c10
--- /dev/null
+++ b/include/asm-generic/irq-err.h
@@ -0,0 +1,17 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef __ASM_GENERIC_IRQ_ERR_H
+#define __ASM_GENERIC_IRQ_ERR_H
+
+extern atomic_t irq_err_counter;
+
+static inline void irq_err_inc(void)
+{
+ atomic_inc(&irq_err_counter);
+}
+
+static inline int irq_err_get(void)
+{
+ return atomic_read(&irq_err_counter);
+}
+
+#endif /* __ASM_GENERIC_IRQ_ERR_H */
diff --git a/kernel/irq/dummychip.c b/kernel/irq/dummychip.c
index 0b0cdf206dc4..93585dab9bd0 100644
--- a/kernel/irq/dummychip.c
+++ b/kernel/irq/dummychip.c
@@ -8,6 +8,7 @@
#include <linux/interrupt.h>
#include <linux/irq.h>
#include <linux/export.h>
+#include <asm-generic/irq-err.h>
#include "internals.h"
@@ -20,6 +21,7 @@ static void ack_bad(struct irq_data *data)
struct irq_desc *desc = irq_data_to_desc(data);
print_irq_desc(data->irq, desc);
+ irq_err_inc();
ack_bad_irq(data->irq);
}
diff --git a/kernel/irq/handle.c b/kernel/irq/handle.c
index 762a928e18f9..ad90f5a56c3a 100644
--- a/kernel/irq/handle.c
+++ b/kernel/irq/handle.c
@@ -13,11 +13,14 @@
#include <linux/sched.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
+#include <asm-generic/irq-err.h>
#include <trace/events/irq.h>
#include "internals.h"
+atomic_t irq_err_counter;
+
#ifdef CONFIG_GENERIC_IRQ_MULTI_HANDLER
void (*handle_arch_irq)(struct pt_regs *) __ro_after_init;
#endif
@@ -34,6 +37,7 @@ void handle_bad_irq(struct irq_desc *desc)
print_irq_desc(irq, desc);
kstat_incr_irqs_this_cpu(desc);
+ irq_err_inc();
ack_bad_irq(irq);
}
EXPORT_SYMBOL_GPL(handle_bad_irq);
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 62a381351775..6192672be4d2 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -16,6 +16,7 @@
#include <linux/bitmap.h>
#include <linux/irqdomain.h>
#include <linux/sysfs.h>
+#include <asm-generic/irq-err.h>
#include "internals.h"
@@ -684,6 +685,7 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
if (printk_ratelimit())
pr_warn("spurious IRQ: irq=%d hwirq=%d nr_irqs=%d\n",
irq, hwirq, nr_irqs);
+ irq_err_inc();
ack_bad_irq(irq);
ret = -EINVAL;
} else {
--
2.11.0
^ permalink raw reply related
* [PATCH 11/23] arch: sparc: drop misleading warning on spurious IRQ
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
The warning in ack_bad_irq() is misleading in several ways:
* the term "vector" isn't quite correct
* the printing format isn't consistent across the archs: some print decimal,
some hex, some hex w/o 0x prefix.
* the printed linux irq isn't meaningful in all cases - we actually would
want it to print the hw irq.
Since all call sites already print out more detailed and correct information,
we just don't need to duplicate this in each single arch. So just drop it.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/sparc/include/asm/hardirq_64.h | 2 +-
arch/sparc/kernel/irq_64.c | 5 -----
2 files changed, 1 insertion(+), 6 deletions(-)
diff --git a/arch/sparc/include/asm/hardirq_64.h b/arch/sparc/include/asm/hardirq_64.h
index 75b92bfe04b5..874151f520de 100644
--- a/arch/sparc/include/asm/hardirq_64.h
+++ b/arch/sparc/include/asm/hardirq_64.h
@@ -14,6 +14,6 @@
#define local_softirq_pending_ref \
__cpu_data.__softirq_pending
-void ack_bad_irq(unsigned int irq);
+#define ack_bad_irq(irq)
#endif /* !(__SPARC64_HARDIRQ_H) */
diff --git a/arch/sparc/kernel/irq_64.c b/arch/sparc/kernel/irq_64.c
index 3ec9f1402aad..ea2a52f7fe53 100644
--- a/arch/sparc/kernel/irq_64.c
+++ b/arch/sparc/kernel/irq_64.c
@@ -284,11 +284,6 @@ static unsigned int sysino_exists(u32 devhandle, unsigned int devino)
return irq;
}
-void ack_bad_irq(unsigned int irq)
-{
- pr_crit("BAD IRQ ack %d\n", irq);
-}
-
void irq_install_pre_handler(int irq,
void (*func)(unsigned int, void *, void *),
void *arg1, void *arg2)
--
2.11.0
^ permalink raw reply related
* [PATCH 13/23] arch: generic: drop misleading warning on spurious IRQ
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
The warning in ack_bad_irq() is misleading in several ways:
* the term "vector" isn't quite correct
* the printing format isn't consistent across the archs: some print decimal,
some hex, some hex w/o 0x prefix.
* the printed linux irq isn't meaningful in all cases - we actually would
want it to print the hw irq.
Since all call sites already print out more detailed and correct information,
we just don't need to duplicate this in each single arch. So just drop it.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
include/asm-generic/hardirq.h | 1 -
1 file changed, 1 deletion(-)
diff --git a/include/asm-generic/hardirq.h b/include/asm-generic/hardirq.h
index 7317e8258b48..f5a0240cbf52 100644
--- a/include/asm-generic/hardirq.h
+++ b/include/asm-generic/hardirq.h
@@ -19,7 +19,6 @@ DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
#ifndef ack_bad_irq
static inline void ack_bad_irq(unsigned int irq)
{
- printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
}
#endif
--
2.11.0
^ permalink raw reply related
* [PATCH 16/23] arch: alpha: use generic irq error counter
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
Use the newly introduced irq error counter, that's already maintained
by all callers of ack_bad_irq(), in order to remove duplicate code.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/alpha/include/asm/hardirq.h | 3 ---
arch/alpha/include/asm/hw_irq.h | 2 --
arch/alpha/kernel/irq.c | 12 +++---------
arch/alpha/kernel/irq_alpha.c | 5 +++--
arch/alpha/kernel/perf_event.c | 6 +++---
5 files changed, 9 insertions(+), 19 deletions(-)
diff --git a/arch/alpha/include/asm/hardirq.h b/arch/alpha/include/asm/hardirq.h
index 5ce5b34e8a1a..0bbc9947e364 100644
--- a/arch/alpha/include/asm/hardirq.h
+++ b/arch/alpha/include/asm/hardirq.h
@@ -2,9 +2,6 @@
#ifndef _ALPHA_HARDIRQ_H
#define _ALPHA_HARDIRQ_H
-void ack_bad_irq(unsigned int irq);
-#define ack_bad_irq ack_bad_irq
-
#include <asm-generic/hardirq.h>
#endif /* _ALPHA_HARDIRQ_H */
diff --git a/arch/alpha/include/asm/hw_irq.h b/arch/alpha/include/asm/hw_irq.h
index e2d81ac0d934..0be79f3a6cae 100644
--- a/arch/alpha/include/asm/hw_irq.h
+++ b/arch/alpha/include/asm/hw_irq.h
@@ -2,8 +2,6 @@
#ifndef _ALPHA_HW_IRQ_H
#define _ALPHA_HW_IRQ_H
-
-extern volatile unsigned long irq_err_count;
DECLARE_PER_CPU(unsigned long, irq_pmi_count);
#ifdef CONFIG_ALPHA_GENERIC
diff --git a/arch/alpha/kernel/irq.c b/arch/alpha/kernel/irq.c
index c1980eea75a6..2b7dad83e0dc 100644
--- a/arch/alpha/kernel/irq.c
+++ b/arch/alpha/kernel/irq.c
@@ -25,18 +25,12 @@
#include <linux/seq_file.h>
#include <linux/profile.h>
#include <linux/bitops.h>
-
+#include <asm-generic/irq-err.h>
#include <asm/io.h>
#include <linux/uaccess.h>
-volatile unsigned long irq_err_count;
DEFINE_PER_CPU(unsigned long, irq_pmi_count);
-void ack_bad_irq(unsigned int irq)
-{
- irq_err_count++;
-}
-
#ifdef CONFIG_SMP
static char irq_user_affinity[NR_IRQS];
@@ -79,7 +73,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
for_each_online_cpu(j)
seq_printf(p, "%10lu ", per_cpu(irq_pmi_count, j));
seq_puts(p, " Performance Monitoring\n");
- seq_printf(p, "ERR: %10lu\n", irq_err_count);
+ seq_printf(p, "ERR: %10lu\n", irq_err_get());
return 0;
}
@@ -109,7 +103,7 @@ handle_irq(int irq)
if (!desc || ((unsigned) irq > ACTUAL_NR_IRQS &&
illegal_count < MAX_ILLEGAL_IRQS)) {
- irq_err_count++;
+ irq_err_inc();
illegal_count++;
printk(KERN_CRIT "device_interrupt: invalid interrupt %d\n",
irq);
diff --git a/arch/alpha/kernel/irq_alpha.c b/arch/alpha/kernel/irq_alpha.c
index d17e44c99df9..3b6373cf73d9 100644
--- a/arch/alpha/kernel/irq_alpha.c
+++ b/arch/alpha/kernel/irq_alpha.c
@@ -13,6 +13,7 @@
#include <asm/dma.h>
#include <asm/perf_event.h>
#include <asm/mce.h>
+#include <asm-generic/irq-err.h>
#include "proto.h"
#include "irq_impl.h"
@@ -30,7 +31,7 @@ EXPORT_SYMBOL(__min_ipl);
static void
dummy_perf(unsigned long vector, struct pt_regs *regs)
{
- irq_err_count++;
+ irq_err_inc();
printk(KERN_CRIT "Performance counter interrupt!\n");
}
@@ -60,7 +61,7 @@ do_entInt(unsigned long type, unsigned long vector,
handle_ipi(regs);
return;
#else
- irq_err_count++;
+ irq_err_inc();
printk(KERN_CRIT "Interprocessor interrupt? "
"You must be kidding!\n");
#endif
diff --git a/arch/alpha/kernel/perf_event.c b/arch/alpha/kernel/perf_event.c
index e7a59d927d78..d855cece7bb1 100644
--- a/arch/alpha/kernel/perf_event.c
+++ b/arch/alpha/kernel/perf_event.c
@@ -16,7 +16,7 @@
#include <linux/kdebug.h>
#include <linux/mutex.h>
#include <linux/init.h>
-
+#include <asm-generic/irq-err.h>
#include <asm/hwrpb.h>
#include <linux/atomic.h>
#include <asm/irq.h>
@@ -823,7 +823,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
/* la_ptr is the counter that overflowed. */
if (unlikely(la_ptr >= alpha_pmu->num_pmcs)) {
/* This should never occur! */
- irq_err_count++;
+ irq_err_inc();
pr_warn("PMI: silly index %ld\n", la_ptr);
wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
return;
@@ -846,7 +846,7 @@ static void alpha_perf_event_irq_handler(unsigned long la_ptr,
if (unlikely(!event)) {
/* This should never occur! */
- irq_err_count++;
+ irq_err_inc();
pr_warn("PMI: No event at index %d!\n", idx);
wrperfmon(PERFMON_CMD_ENABLE, cpuc->idx_mask);
return;
--
2.11.0
^ permalink raw reply related
* [PATCH 15/23] arch: mips: use generic irq error counter
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
Use the newly introduced irq error counter, that's already maintained
by all callers of ack_bad_irq(), in order to remove duplicate code.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/mips/include/asm/hw_irq.h | 4 ----
arch/mips/kernel/irq-gt641xx.c | 3 ++-
arch/mips/kernel/irq.c | 7 +++----
arch/mips/sni/rm200.c | 3 ++-
arch/mips/vr41xx/common/icu.c | 3 ++-
arch/mips/vr41xx/common/irq.c | 5 +++--
drivers/gpio/gpio-vr41xx.c | 4 ++--
7 files changed, 14 insertions(+), 15 deletions(-)
diff --git a/arch/mips/include/asm/hw_irq.h b/arch/mips/include/asm/hw_irq.h
index 9e8ef5994c9c..b75fe2c4377f 100644
--- a/arch/mips/include/asm/hw_irq.h
+++ b/arch/mips/include/asm/hw_irq.h
@@ -8,10 +8,6 @@
#ifndef __ASM_HW_IRQ_H
#define __ASM_HW_IRQ_H
-#include <linux/atomic.h>
-
-extern atomic_t irq_err_count;
-
/*
* interrupt-retrigger: NOP for now. This may not be appropriate for all
* machines, we'll see ...
diff --git a/arch/mips/kernel/irq-gt641xx.c b/arch/mips/kernel/irq-gt641xx.c
index 93bcf5736a6f..e2c877287bee 100644
--- a/arch/mips/kernel/irq-gt641xx.c
+++ b/arch/mips/kernel/irq-gt641xx.c
@@ -11,6 +11,7 @@
#include <linux/types.h>
#include <asm/gt64120.h>
+#include <asm-generic/irq-err.h>
#define GT641XX_IRQ_TO_BIT(irq) (1U << (irq - GT641XX_IRQ_BASE))
@@ -97,7 +98,7 @@ void gt641xx_irq_dispatch(void)
}
}
- atomic_inc(&irq_err_count);
+ irq_err_inc();
}
void __init gt641xx_irq_init(void)
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index c98be305fab6..3ea3e4280648 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -8,6 +8,7 @@
* Copyright (C) 1992 Linus Torvalds
* Copyright (C) 1994 - 2000 Ralf Baechle
*/
+#include <asm-generic/irq-err.h>
#include <linux/kernel.h>
#include <linux/delay.h>
#include <linux/init.h>
@@ -27,17 +28,15 @@
void *irq_stack[NR_CPUS];
-atomic_t irq_err_count;
-
int arch_show_interrupts(struct seq_file *p, int prec)
{
- seq_printf(p, "%*s: %10u\n", prec, "ERR", atomic_read(&irq_err_count));
+ seq_printf(p, "%*s: %10u\n", prec, "ERR", irq_err_get());
return 0;
}
asmlinkage void spurious_interrupt(void)
{
- atomic_inc(&irq_err_count);
+ irq_err_inc();
}
void __init init_IRQ(void)
diff --git a/arch/mips/sni/rm200.c b/arch/mips/sni/rm200.c
index d84744ca871d..c61d60a4dcc5 100644
--- a/arch/mips/sni/rm200.c
+++ b/arch/mips/sni/rm200.c
@@ -21,6 +21,7 @@
#include <asm/sni.h>
#include <asm/time.h>
#include <asm/irq_cpu.h>
+#include <asm-generic/irq-err.h>
#define RM200_I8259A_IRQ_BASE 32
@@ -270,7 +271,7 @@ void sni_rm200_mask_and_ack_8259A(struct irq_data *d)
"spurious RM200 8259A interrupt: IRQ%d.\n", irq);
spurious_irq_mask |= irqmask;
}
- atomic_inc(&irq_err_count);
+ irq_err_inc();
/*
* Theoretically we do not have to handle this IRQ,
* but in Linux this does not cause problems and is
diff --git a/arch/mips/vr41xx/common/icu.c b/arch/mips/vr41xx/common/icu.c
index 7b7f25b4b057..462f559ad978 100644
--- a/arch/mips/vr41xx/common/icu.c
+++ b/arch/mips/vr41xx/common/icu.c
@@ -27,6 +27,7 @@
#include <asm/io.h>
#include <asm/vr41xx/irq.h>
#include <asm/vr41xx/vr41xx.h>
+#include <asm-generic/irq-err.h>
static void __iomem *icu1_base;
static void __iomem *icu2_base;
@@ -640,7 +641,7 @@ static int icu_get_irq(unsigned int irq)
printk(KERN_ERR "spurious ICU interrupt: %04x,%04x\n", pend1, pend2);
- atomic_inc(&irq_err_count);
+ irq_err_inc();
return -1;
}
diff --git a/arch/mips/vr41xx/common/irq.c b/arch/mips/vr41xx/common/irq.c
index 8f68446ff2d9..b2580de08e25 100644
--- a/arch/mips/vr41xx/common/irq.c
+++ b/arch/mips/vr41xx/common/irq.c
@@ -10,6 +10,7 @@
#include <asm/irq_cpu.h>
#include <asm/vr41xx/irq.h>
+#include <asm-generic/irq-err.h>
typedef struct irq_cascade {
int (*get_irq)(unsigned int);
@@ -46,7 +47,7 @@ static void irq_dispatch(unsigned int irq)
irq_cascade_t *cascade;
if (irq >= NR_IRQS) {
- atomic_inc(&irq_err_count);
+ irq_err_inc();
return;
}
@@ -66,7 +67,7 @@ static void irq_dispatch(unsigned int irq)
ret = cascade->get_irq(irq);
irq = ret;
if (ret < 0)
- atomic_inc(&irq_err_count);
+ irq_err_inc();
else
irq_dispatch(irq);
if (!irqd_irq_disabled(idata) && chip->irq_unmask)
diff --git a/drivers/gpio/gpio-vr41xx.c b/drivers/gpio/gpio-vr41xx.c
index 98cd715ccc33..c1dbd933d291 100644
--- a/drivers/gpio/gpio-vr41xx.c
+++ b/drivers/gpio/gpio-vr41xx.c
@@ -18,7 +18,7 @@
#include <linux/platform_device.h>
#include <linux/spinlock.h>
#include <linux/types.h>
-
+#include <asm-generic/irq-err.h>
#include <asm/vr41xx/giu.h>
#include <asm/vr41xx/irq.h>
#include <asm/vr41xx/vr41xx.h>
@@ -217,7 +217,7 @@ static int giu_get_irq(unsigned int irq)
printk(KERN_ERR "spurious GIU interrupt: %04x(%04x),%04x(%04x)\n",
maskl, pendl, maskh, pendh);
- atomic_inc(&irq_err_count);
+ irq_err_inc();
return -EINVAL;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 19/23] arch: c6x: use generic irq error counter
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
Use the newly introduced irq error counter, that's already maintained
by all callers of ack_bad_irq(), in order to remove duplicate code.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/c6x/include/asm/hardirq.h | 3 ---
arch/c6x/include/asm/irq.h | 2 --
arch/c6x/kernel/irq.c | 11 ++---------
3 files changed, 2 insertions(+), 14 deletions(-)
diff --git a/arch/c6x/include/asm/hardirq.h b/arch/c6x/include/asm/hardirq.h
index f37d07d31040..f70f6113e53a 100644
--- a/arch/c6x/include/asm/hardirq.h
+++ b/arch/c6x/include/asm/hardirq.h
@@ -9,9 +9,6 @@
#ifndef _ASM_C6X_HARDIRQ_H
#define _ASM_C6X_HARDIRQ_H
-extern void ack_bad_irq(int irq);
-#define ack_bad_irq ack_bad_irq
-
#include <asm-generic/hardirq.h>
#endif /* _ASM_C6X_HARDIRQ_H */
diff --git a/arch/c6x/include/asm/irq.h b/arch/c6x/include/asm/irq.h
index 9da4d1afd0d7..f42c5747c3ee 100644
--- a/arch/c6x/include/asm/irq.h
+++ b/arch/c6x/include/asm/irq.h
@@ -45,6 +45,4 @@ struct pt_regs;
extern asmlinkage void c6x_do_IRQ(unsigned int prio, struct pt_regs *regs);
-extern unsigned long irq_err_count;
-
#endif /* _ASM_C6X_IRQ_H */
diff --git a/arch/c6x/kernel/irq.c b/arch/c6x/kernel/irq.c
index b9f7cfa2ed21..9f9d798925de 100644
--- a/arch/c6x/kernel/irq.c
+++ b/arch/c6x/kernel/irq.c
@@ -21,12 +21,10 @@
#include <linux/of_irq.h>
#include <linux/interrupt.h>
#include <linux/kernel_stat.h>
-
+#include <asm-generic/irq-err.h>
#include <asm/megamod-pic.h>
#include <asm/special_insns.h>
-unsigned long irq_err_count;
-
static DEFINE_RAW_SPINLOCK(core_irq_lock);
static void mask_core_irq(struct irq_data *data)
@@ -114,13 +112,8 @@ void __init init_IRQ(void)
set_creg(ICR, 0xfff0);
}
-void ack_bad_irq(int irq)
-{
- irq_err_count++;
-}
-
int arch_show_interrupts(struct seq_file *p, int prec)
{
- seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
+ seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_get());
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 18/23] arch: arm64: use generic irq error counter
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
Use the newly introduced irq error counter, that's already maintained
by all callers of ack_bad_irq(), in order to remove duplicate code.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/arm64/include/asm/hardirq.h | 9 ++-------
arch/arm64/kernel/smp.c | 6 ++----
2 files changed, 4 insertions(+), 11 deletions(-)
diff --git a/arch/arm64/include/asm/hardirq.h b/arch/arm64/include/asm/hardirq.h
index cbfa7b6f2e09..760922571084 100644
--- a/arch/arm64/include/asm/hardirq.h
+++ b/arch/arm64/include/asm/hardirq.h
@@ -13,7 +13,8 @@
#include <asm/kvm_arm.h>
#include <asm/sysreg.h>
-#define ack_bad_irq ack_bad_irq
+#define ack_bad_irq(irq)
+
#include <asm-generic/hardirq.h>
#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1
@@ -85,10 +86,4 @@ do { \
write_sysreg(___hcr, hcr_el2); \
} while (0)
-static inline void ack_bad_irq(unsigned int irq)
-{
- extern unsigned long irq_err_count;
- irq_err_count++;
-}
-
#endif /* __ASM_HARDIRQ_H */
diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
index 2499b895efea..0edc565ea735 100644
--- a/arch/arm64/kernel/smp.c
+++ b/arch/arm64/kernel/smp.c
@@ -33,7 +33,7 @@
#include <linux/kernel_stat.h>
#include <linux/kexec.h>
#include <linux/kvm_host.h>
-
+#include <asm-generic/irq-err.h>
#include <asm/alternative.h>
#include <asm/atomic.h>
#include <asm/cacheflush.h>
@@ -798,8 +798,6 @@ static const char *ipi_types[NR_IPI] __tracepoint_string = {
static void smp_cross_call(const struct cpumask *target, unsigned int ipinr);
-unsigned long irq_err_count;
-
int arch_show_interrupts(struct seq_file *p, int prec)
{
unsigned int cpu, i;
@@ -813,7 +811,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
seq_printf(p, " %s\n", ipi_types[i]);
}
- seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
+ seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_get());
return 0;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 17/23] arch: arm: use generic irq error counter
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
Use the newly introduced irq error counter, that's already maintained
by all callers of ack_bad_irq(), in order to remove duplicate code.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/arm/include/asm/hardirq.h | 2 +-
arch/arm/include/asm/hw_irq.h | 6 ------
arch/arm/kernel/irq.c | 6 ++----
drivers/irqchip/irq-omap-intc.c | 5 ++---
4 files changed, 5 insertions(+), 14 deletions(-)
diff --git a/arch/arm/include/asm/hardirq.h b/arch/arm/include/asm/hardirq.h
index 706efafbf972..d9ae8998240d 100644
--- a/arch/arm/include/asm/hardirq.h
+++ b/arch/arm/include/asm/hardirq.h
@@ -5,7 +5,7 @@
#include <asm/irq.h>
#define __ARCH_IRQ_EXIT_IRQS_DISABLED 1
-#define ack_bad_irq ack_bad_irq
+#define ack_bad_irq(irq)
#include <asm-generic/hardirq.h>
diff --git a/arch/arm/include/asm/hw_irq.h b/arch/arm/include/asm/hw_irq.h
index 5305c7e33aee..adbbeb11b930 100644
--- a/arch/arm/include/asm/hw_irq.h
+++ b/arch/arm/include/asm/hw_irq.h
@@ -5,12 +5,6 @@
#ifndef _ARCH_ARM_HW_IRQ_H
#define _ARCH_ARM_HW_IRQ_H
-static inline void ack_bad_irq(int irq)
-{
- extern unsigned long irq_err_count;
- irq_err_count++;
-}
-
#define ARCH_IRQ_INIT_FLAGS (IRQ_NOREQUEST | IRQ_NOPROBE)
#endif
diff --git a/arch/arm/kernel/irq.c b/arch/arm/kernel/irq.c
index 698b6f636156..72c3b8ce74db 100644
--- a/arch/arm/kernel/irq.c
+++ b/arch/arm/kernel/irq.c
@@ -32,7 +32,7 @@
#include <linux/kallsyms.h>
#include <linux/proc_fs.h>
#include <linux/export.h>
-
+#include <asm-generic/irq-err.h>
#include <asm/hardware/cache-l2x0.h>
#include <asm/hardware/cache-uniphier.h>
#include <asm/outercache.h>
@@ -41,8 +41,6 @@
#include <asm/mach/irq.h>
#include <asm/mach/time.h>
-unsigned long irq_err_count;
-
int arch_show_interrupts(struct seq_file *p, int prec)
{
#ifdef CONFIG_FIQ
@@ -51,7 +49,7 @@ int arch_show_interrupts(struct seq_file *p, int prec)
#ifdef CONFIG_SMP
show_ipi_list(p, prec);
#endif
- seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_count);
+ seq_printf(p, "%*s: %10lu\n", prec, "Err", irq_err_get());
return 0;
}
diff --git a/drivers/irqchip/irq-omap-intc.c b/drivers/irqchip/irq-omap-intc.c
index d360a6eddd6d..2682c6e814c2 100644
--- a/drivers/irqchip/irq-omap-intc.c
+++ b/drivers/irqchip/irq-omap-intc.c
@@ -15,7 +15,7 @@
#include <linux/init.h>
#include <linux/interrupt.h>
#include <linux/io.h>
-
+#include <asm-generic/irq-err.h>
#include <asm/exception.h>
#include <linux/irqchip.h>
#include <linux/irqdomain.h>
@@ -328,7 +328,6 @@ static int __init omap_init_irq(u32 base, struct device_node *node)
static asmlinkage void __exception_irq_entry
omap_intc_handle_irq(struct pt_regs *regs)
{
- extern unsigned long irq_err_count;
u32 irqnr;
irqnr = intc_readl(INTC_SIR);
@@ -351,7 +350,7 @@ omap_intc_handle_irq(struct pt_regs *regs)
*/
if (unlikely((irqnr & SPURIOUSIRQ_MASK) == SPURIOUSIRQ_MASK)) {
pr_err_once("%s: spurious irq!\n", __func__);
- irq_err_count++;
+ irq_err_inc();
omap_ack_irq(NULL);
return;
}
--
2.11.0
^ permalink raw reply related
* [PATCH 09/23] arch: s390: drop misleading warning on spurious IRQ
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
The warning in ack_bad_irq() is misleading in several ways:
* the term "vector" isn't quite correct
* the printing format isn't consistent across the archs: some print decimal,
some hex, some hex w/o 0x prefix.
* the printed linux irq isn't meaningful in all cases - we actually would
want it to print the hw irq.
Since all call sites already print out more detailed and correct information,
we just don't need to duplicate this in each single arch. So just drop it.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/s390/include/asm/hardirq.h | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
diff --git a/arch/s390/include/asm/hardirq.h b/arch/s390/include/asm/hardirq.h
index dfbc3c6c0674..56d95fcb310a 100644
--- a/arch/s390/include/asm/hardirq.h
+++ b/arch/s390/include/asm/hardirq.h
@@ -21,9 +21,6 @@
#define __ARCH_HAS_DO_SOFTIRQ
#define __ARCH_IRQ_EXIT_IRQS_DISABLED
-static inline void ack_bad_irq(unsigned int irq)
-{
- printk(KERN_CRIT "unexpected IRQ trap at vector %02x\n", irq);
-}
+#define ack_bad_irq(irq)
#endif /* __ASM_HARDIRQ_H */
--
2.11.0
^ permalink raw reply related
* [PATCH 06/23] arch: mips: drop misleading warning on spurious IRQ
From: Enrico Weigelt, metux IT consult @ 2020-12-18 14:57 UTC (permalink / raw)
To: linux-kernel
Cc: mark.rutland, dalias, linux-ia64, linux-sh, alexander.shishkin,
linus.walleij, James.Bottomley, paulus, hpa, sparclinux, will,
gerg, linux-arch, linux-s390, linux-c6x-dev, ysato, jolsa, deller,
x86, bgolaszewski, tony, geert, catalin.marinas, linux-alpha,
arnd, msalter, jacquiot.aurelien, linux-gpio, linux-m68k, bp,
namhyung, tglx, linux-omap, tsbogend, linux-parisc, linux-mips,
maz, linuxppc-dev, davem
In-Reply-To: <20201218145746.24205-1-info@metux.net>
The warning in ack_bad_irq() is misleading in several ways:
* the term "vector" isn't quite correct
* the printing format isn't consistent across the archs: some print decimal,
some hex, some hex w/o 0x prefix.
* the printed linux irq isn't meaningful in all cases - we actually would
want it to print the hw irq.
Since all call sites already print out more detailed and correct information,
we just don't need to duplicate this in each single arch. So just drop it.
Signed-off-by: Enrico Weigelt, metux IT consult <info@metux.net>
---
arch/mips/include/asm/hardirq.h | 3 +--
arch/mips/kernel/irq.c | 9 ---------
2 files changed, 1 insertion(+), 11 deletions(-)
diff --git a/arch/mips/include/asm/hardirq.h b/arch/mips/include/asm/hardirq.h
index c977a86c2c65..75444120e6cb 100644
--- a/arch/mips/include/asm/hardirq.h
+++ b/arch/mips/include/asm/hardirq.h
@@ -10,8 +10,7 @@
#ifndef _ASM_HARDIRQ_H
#define _ASM_HARDIRQ_H
-extern void ack_bad_irq(unsigned int irq);
-#define ack_bad_irq ack_bad_irq
+#define ack_bad_irq(irq)
#include <asm-generic/hardirq.h>
diff --git a/arch/mips/kernel/irq.c b/arch/mips/kernel/irq.c
index 85b6c60f285d..c98be305fab6 100644
--- a/arch/mips/kernel/irq.c
+++ b/arch/mips/kernel/irq.c
@@ -27,15 +27,6 @@
void *irq_stack[NR_CPUS];
-/*
- * 'what should we do if we get a hw irq event on an illegal vector'.
- * each architecture has to answer this themselves.
- */
-void ack_bad_irq(unsigned int irq)
-{
- printk("unexpected IRQ # %d\n", irq);
-}
-
atomic_t irq_err_count;
int arch_show_interrupts(struct seq_file *p, int prec)
--
2.11.0
^ permalink raw reply related
* Re: [PATCH] powerpc: fix alignment bug whithin the init sections
From: Christophe Leroy @ 2020-12-18 15:38 UTC (permalink / raw)
To: Ariel Marcovitch, mpe
Cc: linuxppc-dev, paulus, linux-kernel, Ariel Marcovitch
In-Reply-To: <20201213183556.16976-1-ariel.marcovitch@gmail.com>
Le 13/12/2020 à 19:35, Ariel Marcovitch a écrit :
> This is a bug that can cause early crashes in configurations with a
> .exit.text section smaller than a page and a .init.text section that
> ends in the beginning of a physical page (this is kinda random, which
> might explain why this wasn't really encountered before).
It can cause, or it causes ? Did you encounter the issue ?
>
> The init sections are ordered like this:
> .init.text
> .exit.text
> .init.data
>
> Currently, these sections aren't page aligned.
>
> Because the init code is mapped read-only at runtime and because the
> .init.text section can potentially reside on the same physical page as
> .init.data, the beginning of .init.data might be mapped read-only along
> with .init.text.
init code is mapped PAGE_KERNEL_TEXT.
Whether PAGE_KERNEL_TEXT is read-only or not depends on the selected options.
>
> Then when the kernel tries to modify a variable in .init.data (like
> kthreadd_done, used in kernel_init()) the kernel panics.
>
> To avoid this, I made these sections page aligned.
Should write this unpersonal, something like "To avoid this, make these sections page aligned"
>
> Fixes: 060ef9d89d18 ("powerpc32: PAGE_EXEC required for inittext")
> Signed-off-by: Ariel Marcovitch <ariel.marcovitch@gmail.com>
> ---
> arch/powerpc/kernel/vmlinux.lds.S | 7 +++++++
> 1 file changed, 7 insertions(+)
>
> diff --git a/arch/powerpc/kernel/vmlinux.lds.S b/arch/powerpc/kernel/vmlinux.lds.S
> index 326e113d2e45..e3a7c90c03f4 100644
> --- a/arch/powerpc/kernel/vmlinux.lds.S
> +++ b/arch/powerpc/kernel/vmlinux.lds.S
> @@ -179,6 +179,11 @@ SECTIONS
> #endif
> } :text
>
> + /* .init.text is made RO and .exit.text is not, so we must
> + * ensure these sections reside in separate physical pages.
> + */
> + . = ALIGN(PAGE_SIZE);
> +
In principle, as it is text, it should be made RO as well. But what happens at the begining doesn't
really matter, anyway .exit.text should never be executed and is discarded together with init text.
So, I think it is OK the live with it as is for the time being.
Making it page aligned makes sense anyway.
Should we make _einittext page aligned instead, just like _etext ?
> /* .exit.text is discarded at runtime, not link time,
> * to deal with references from __bug_table
> */
> @@ -186,6 +191,8 @@ SECTIONS
> EXIT_TEXT
> }
>
> + . = ALIGN(PAGE_SIZE);
> +
Here for sure, as you explain in the coming log, this needs to be separated from init text. So
making it aligned is a must.
> .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
> INIT_DATA
> }
>
> base-commit: 1398820fee515873379809a6415930ad0764b2f6
>
Christophe
^ permalink raw reply
* Re: [PATCH 01/23] kernel: irq: irqdescs: warn on spurious IRQ
From: Andy Shevchenko @ 2020-12-18 15:55 UTC (permalink / raw)
To: Enrico Weigelt, metux IT consult
Cc: Mark Rutland, Rich Felker, linux-ia64, Linux-SH,
Alexander Shishkin, Linus Walleij, linux-mips, James Bottomley,
Paul Mackerras, H. Peter Anvin, sparclinux, Will Deacon, gerg,
Linux-Arch, linux-s390, linux-c6x-dev, Yoshinori Sato, Jiri Olsa,
Helge Deller, maintainer:X86 ARCHITECTURE (32-BIT AND 64-BIT),
Bartosz Golaszewski, Tony Lindgren, Geert Uytterhoeven,
Catalin Marinas, linux-alpha, Arnd Bergmann, msalter,
jacquiot.aurelien, open list:GPIO SUBSYSTEM, linux-m68k,
Borislav Petkov, Namhyung Kim, Thomas Gleixner,
Linux OMAP Mailing List, Thomas Bogendoerfer, linux-parisc,
Linux Kernel Mailing List, Marc Zyngier,
open list:LINUX FOR POWERPC PA SEMI PWRFICIENT, David S. Miller
In-Reply-To: <20201218143122.19459-2-info@metux.net>
On Fri, Dec 18, 2020 at 4:37 PM Enrico Weigelt, metux IT consult
<info@metux.net> wrote:
> + if (printk_ratelimit())
> + pr_warn("spurious IRQ: irq=%d hwirq=%d nr_irqs=%d\n",
> + irq, hwirq, nr_irqs);
Perhaps you missed pr_warn_ratelimit() macro which is already in the
kernel for a long time.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply
* GIT kernel with the PowerPC updates 5.11-1 doesn't boot on a FSL P5040 board and in a virtual e5500 QEMU machine
From: Christian Zigotzky @ 2020-12-18 17:45 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Darren Stevens, mad skateman, R.T.Dickinson
Hello,
I compiled the latest Git kernel with the new PowerPC updates 5.11-1 [1]
today. Unfortunately this kernel doesn't boot on my FSL P5040 board [2]
and in a virtual e5500 QEMU machine [3].
I was able to revert the new PowerPC updates 5.11-1 [4] and after a new
compiling, the kernel boots without any problems on my FSL P5040 board.
Please check the new PowerPC updates 5.11-1.
Thanks,
Christian
[1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8a5be36b9303ae167468d4f5e1b3c090b9981396
[2] http://wiki.amiga.org/index.php?title=X5000
[3] qemu-system-ppc64 -M ppce500 -cpu e5500 -m 1024 -kernel uImage
-drive format=raw,file=MintPPC32-X5000.img,index=0,if=virtio -netdev
user,id=mynet0 -device virtio-net-pci,netdev=mynet0 -append "rw
root=/dev/vda" -device virtio-vga -usb -device usb-ehci,id=ehci -device
usb-tablet -device virtio-keyboard-pci -smp 4 -vnc :1
[4] git revert 8a5be36b9303ae167468d4f5e1b3c090b9981396 -m 1
^ permalink raw reply
* Re: [RFC PATCH v1 7/7] powerpc/bpf: Implement extended BPF on PPC32
From: Andrii Nakryiko @ 2020-12-18 19:33 UTC (permalink / raw)
To: Christophe Leroy
Cc: Song Liu, Martin Lau, Daniel Borkmann, john fastabend,
Alexei Starovoitov, Andrii Nakryiko, naveen.n.rao, Networking,
Paul Mackerras, sandipan, KP Singh, Yonghong Song, bpf,
linuxppc-dev, Alexei Starovoitov, open list
In-Reply-To: <854404a0-1951-91d9-2ebb-208390a64c77@csgroup.eu>
On Thu, Dec 17, 2020 at 1:54 AM Christophe Leroy
<christophe.leroy@csgroup.eu> wrote:
>
>
>
> Le 17/12/2020 à 07:11, Alexei Starovoitov a écrit :
> > On Wed, Dec 16, 2020 at 10:07:37AM +0000, Christophe Leroy wrote:
> >> Implement Extended Berkeley Packet Filter on Powerpc 32
> >>
> >> Test result with test_bpf module:
> >>
> >> test_bpf: Summary: 378 PASSED, 0 FAILED, [354/366 JIT'ed]
> >
> > nice!
> >
> >> Registers mapping:
> >>
> >> [BPF_REG_0] = r11-r12
> >> /* function arguments */
> >> [BPF_REG_1] = r3-r4
> >> [BPF_REG_2] = r5-r6
> >> [BPF_REG_3] = r7-r8
> >> [BPF_REG_4] = r9-r10
> >> [BPF_REG_5] = r21-r22 (Args 9 and 10 come in via the stack)
> >> /* non volatile registers */
> >> [BPF_REG_6] = r23-r24
> >> [BPF_REG_7] = r25-r26
> >> [BPF_REG_8] = r27-r28
> >> [BPF_REG_9] = r29-r30
> >> /* frame pointer aka BPF_REG_10 */
> >> [BPF_REG_FP] = r31
> >> /* eBPF jit internal registers */
> >> [BPF_REG_AX] = r19-r20
> >> [TMP_REG] = r18
> >>
> >> As PPC32 doesn't have a redzone in the stack,
> >> use r17 as tail call counter.
> >>
> >> r0 is used as temporary register as much as possible. It is referenced
> >> directly in the code in order to avoid misuse of it, because some
> >> instructions interpret it as value 0 instead of register r0
> >> (ex: addi, addis, stw, lwz, ...)
> >>
> >> The following operations are not implemented:
> >>
> >> case BPF_ALU64 | BPF_DIV | BPF_X: /* dst /= src */
> >> case BPF_ALU64 | BPF_MOD | BPF_X: /* dst %= src */
> >> case BPF_STX | BPF_XADD | BPF_DW: /* *(u64 *)(dst + off) += src */
> >>
> >> The following operations are only implemented for power of two constants:
> >>
> >> case BPF_ALU64 | BPF_MOD | BPF_K: /* dst %= imm */
> >> case BPF_ALU64 | BPF_DIV | BPF_K: /* dst /= imm */
> >
> > Those are sensible limitations. MOD and DIV are rare, but XADD is common.
> > Please consider doing it as a cmpxchg loop in the future.
> >
> > Also please run test_progs. It will give a lot better coverage than test_bpf.ko
> >
>
> I'm having hard time cross building test_progs:
>
> ~/linux-powerpc/tools/testing/selftests/bpf/$ make CROSS_COMPILE=ppc-linux-
> ...
> GEN
> /home/chr/linux-powerpc/tools/testing/selftests/bpf/tools/build/bpftool/Documentation/bpf-helpers.7
> INSTALL eBPF_helpers-manpage
> INSTALL Documentation-man
> GEN vmlinux.h
> /bin/sh: /home/chr/linux-powerpc/tools/testing/selftests/bpf/tools/sbin/bpftool: cannot execute
> binary file
> make: *** [/home/chr/linux-powerpc/tools/testing/selftests/bpf/tools/include/vmlinux.h] Error 126
> make: *** Deleting file `/home/chr/linux-powerpc/tools/testing/selftests/bpf/tools/include/vmlinux.h'
>
> Looks like it builds bpftool for powerpc and tries to run it on my x86.
> How should I proceed ?
The best way would be to fix whatever needs to be fixed in
selftests/bpf and/or bpftool Makefiles to support cross-compilation.
There was some work already for bpftool to support that (with building
bpftool-bootstrap separately for a host architecture, etc). Please
check what's broken and let's try to fix it.
>
> Thanks
> Christophe
^ permalink raw reply
* Re: [PATCH] powerpc: fix alignment bug whithin the init sections
From: ariel marcovitch @ 2020-12-18 20:35 UTC (permalink / raw)
To: Christophe Leroy; +Cc: paulus, linuxppc-dev, linux-kernel
In-Reply-To: <4716e80b-db6f-7669-684f-398971ed5f2e@csgroup.eu>
[-- Attachment #1: Type: text/plain, Size: 3263 bytes --]
On Fri, Dec 18, 2020 at 5:39 PM Christophe Leroy <
christophe.leroy@csgroup.eu> wrote:
> It can cause, or it causes ? Did you encounter the issue ?
>
Yes, in configs that result in the section layout I described, the crush is
consistent.
>
> > The init sections are ordered like this:
> > .init.text
> > .exit.text
> > .init.data
> >
> > Currently, these sections aren't page aligned.
> >
> > Because the init code is mapped read-only at runtime and because the
> > .init.text section can potentially reside on the same physical page as
> > .init.data, the beginning of .init.data might be mapped read-only along
> > with .init.text.
>
> init code is mapped PAGE_KERNEL_TEXT.
>
> Whether PAGE_KERNEL_TEXT is read-only or not depends on the selected
> options.
>
You are right, of course. Should I change the commit message to 'might be
mapped' or something?
>
> > Then when the kernel tries to modify a variable in .init.data (like
> > kthreadd_done, used in kernel_init()) the kernel panics.
> >
> > To avoid this, I made these sections page aligned.
>
> Should write this unpersonal, something like "To avoid this, make these
> sections page aligned"
>
Noted, thanks.
>
> >
> > Fixes: 060ef9d89d18 ("powerpc32: PAGE_EXEC required for inittext")
> > Signed-off-by: Ariel Marcovitch <ariel.marcovitch@gmail.com>
> > ---
> > arch/powerpc/kernel/vmlinux.lds.S | 7 +++++++
> > 1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/powerpc/kernel/vmlinux.lds.S
> b/arch/powerpc/kernel/vmlinux.lds.S
> > index 326e113d2e45..e3a7c90c03f4 100644
> > --- a/arch/powerpc/kernel/vmlinux.lds.S
> > +++ b/arch/powerpc/kernel/vmlinux.lds.S
> > @@ -179,6 +179,11 @@ SECTIONS
> > #endif
> > } :text
> >
> > + /* .init.text is made RO and .exit.text is not, so we must
> > + * ensure these sections reside in separate physical pages.
> > + */
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> In principle, as it is text, it should be made RO as well. But what
> happens at the begining doesn't
> really matter, anyway .exit.text should never be executed and is discarded
> together with init text.
> So, I think it is OK the live with it as is for the time being.
> Making it page aligned makes sense anyway.
>
> Should we make _einittext page aligned instead, just like _etext ?
Yes, this will probably be better (because when _einittext is not aligned,
the part of the page after _einittext is mapped RO implicitly, and it's
hard to notice from the code). I suppose you mean something like this:
_sinittext = .;
INIT_TEXT
+
+ . = ALIGN(.);
_einittext = .;
> /* .exit.text is discarded at runtime, not link time,
> > * to deal with references from __bug_table
> > */
> > @@ -186,6 +191,8 @@ SECTIONS
> > EXIT_TEXT
> > }
> >
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> Here for sure, as you explain in the coming log, this needs to be
> separated from init text. So
> making it aligned is a must.
> > .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
> > INIT_DATA
> > }
> >
> > base-commit: 1398820fee515873379809a6415930ad0764b2f6
> >
>
> Christophe
>
Thanks for your time,
Ariel Marcovitch
[-- Attachment #2: Type: text/html, Size: 5140 bytes --]
^ permalink raw reply
* Re: [PATCH] powerpc: fix alignment bug whithin the init sections
From: ariel marcovitch @ 2020-12-18 20:43 UTC (permalink / raw)
To: Christophe Leroy; +Cc: paulus, linuxppc-dev, linux-kernel
In-Reply-To: <4716e80b-db6f-7669-684f-398971ed5f2e@csgroup.eu>
On Fri, Dec 18, 2020 at 5:39 PM Christophe Leroy <
christophe.leroy@csgroup.eu> wrote:
> It can cause, or it causes ? Did you encounter the issue ?
>
Yes, in configs that result in the section layout I described, the crush is
consistent.
>
> > The init sections are ordered like this:
> > .init.text
> > .exit.text
> > .init.data
> >
> > Currently, these sections aren't page aligned.
> >
> > Because the init code is mapped read-only at runtime and because the
> > .init.text section can potentially reside on the same physical page as
> > .init.data, the beginning of .init.data might be mapped read-only along
> > with .init.text.
>
> init code is mapped PAGE_KERNEL_TEXT.
>
> Whether PAGE_KERNEL_TEXT is read-only or not depends on the selected
> options.
>
You are right, of course. Should I change the commit message to 'might be
mapped' or something?
>
> > Then when the kernel tries to modify a variable in .init.data (like
> > kthreadd_done, used in kernel_init()) the kernel panics.
> >
> > To avoid this, I made these sections page aligned.
>
> Should write this unpersonal, something like "To avoid this, make these
> sections page aligned"
>
Noted, thanks.
>
> >
> > Fixes: 060ef9d89d18 ("powerpc32: PAGE_EXEC required for inittext")
> > Signed-off-by: Ariel Marcovitch <ariel.marcovitch@gmail.com>
> > ---
> > arch/powerpc/kernel/vmlinux.lds.S | 7 +++++++
> > 1 file changed, 7 insertions(+)
> >
> > diff --git a/arch/powerpc/kernel/vmlinux.lds.S
> b/arch/powerpc/kernel/vmlinux.lds.S
> > index 326e113d2e45..e3a7c90c03f4 100644
> > --- a/arch/powerpc/kernel/vmlinux.lds.S
> > +++ b/arch/powerpc/kernel/vmlinux.lds.S
> > @@ -179,6 +179,11 @@ SECTIONS
> > #endif
> > } :text
> >
> > + /* .init.text is made RO and .exit.text is not, so we must
> > + * ensure these sections reside in separate physical pages.
> > + */
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> In principle, as it is text, it should be made RO as well. But what
> happens at the begining doesn't
> really matter, anyway .exit.text should never be executed and is discarded
> together with init text.
> So, I think it is OK the live with it as is for the time being.
> Making it page aligned makes sense anyway.
>
> Should we make _einittext page aligned instead, just like _etext ?
Yes, this will probably be better (because when _einittext is not aligned,
the part of the page after _einittext is mapped RO implicitly, and it's
hard to notice from the code). I suppose you mean something like this:
_sinittext = .;
INIT_TEXT
+
+ . = ALIGN(.);
_einittext = .;
> /* .exit.text is discarded at runtime, not link time,
> > * to deal with references from __bug_table
> > */
> > @@ -186,6 +191,8 @@ SECTIONS
> > EXIT_TEXT
> > }
> >
> > + . = ALIGN(PAGE_SIZE);
> > +
>
> Here for sure, as you explain in the coming log, this needs to be
> separated from init text. So
> making it aligned is a must.
> > .init.data : AT(ADDR(.init.data) - LOAD_OFFSET) {
> > INIT_DATA
> > }
> >
> > base-commit: 1398820fee515873379809a6415930ad0764b2f6
> >
>
> Christophe
>
Thanks for your time,
Ariel Marcovitch
^ permalink raw reply
* Re: GIT kernel with the PowerPC updates 5.11-1 doesn't boot on a FSL P5040 board and in a virtual e5500 QEMU machine
From: Denis Kirjanov @ 2020-12-18 21:25 UTC (permalink / raw)
To: Christian Zigotzky
Cc: Darren Stevens, linuxppc-dev, R.T.Dickinson, mad skateman
In-Reply-To: <a546bc22-1e18-8e71-e973-65cf7095594a@xenosoft.de>
[-- Attachment #1: Type: text/plain, Size: 1127 bytes --]
On Friday, December 18, 2020, Christian Zigotzky <chzigotzky@xenosoft.de>
wrote:
> Hello,
>
> I compiled the latest Git kernel with the new PowerPC updates 5.11-1 [1]
> today. Unfortunately this kernel doesn't boot on my FSL P5040 board [2] and
> in a virtual e5500 QEMU machine [3].
>
> I was able to revert the new PowerPC updates 5.11-1 [4] and after a new
> compiling, the kernel boots without any problems on my FSL P5040 board.
>
> Please check the new PowerPC updates 5.11-1.
Can you bisect the bad commit?
>
> Thanks,
> Christian
>
>
> [1] https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/lin
> ux.git/commit/?id=8a5be36b9303ae167468d4f5e1b3c090b9981396
> [2] http://wiki.amiga.org/index.php?title=X5000
> [3] qemu-system-ppc64 -M ppce500 -cpu e5500 -m 1024 -kernel uImage -drive
> format=raw,file=MintPPC32-X5000.img,index=0,if=virtio -netdev
> user,id=mynet0 -device virtio-net-pci,netdev=mynet0 -append "rw
> root=/dev/vda" -device virtio-vga -usb -device usb-ehci,id=ehci -device
> usb-tablet -device virtio-keyboard-pci -smp 4 -vnc :1
> [4] git revert 8a5be36b9303ae167468d4f5e1b3c090b9981396 -m 1
>
[-- Attachment #2: Type: text/html, Size: 1765 bytes --]
^ permalink raw reply
* Re: GIT kernel with the PowerPC updates 5.11-1 doesn't boot on a FSL P5040 board and in a virtual e5500 QEMU machine
From: Christian Zigotzky @ 2020-12-18 22:49 UTC (permalink / raw)
To: Denis Kirjanov; +Cc: Darren Stevens, mad skateman, R.T.Dickinson, linuxppc-dev
In-Reply-To: <CAOJe8K3+j3kGHYhSfjyywXcSQFca0Y370LiAa2uVsW5znUPsAA@mail.gmail.com>
On 18 December 2020 at 10:25pm, Denis Kirjanov wrote:
>
>
> On Friday, December 18, 2020, Christian Zigotzky
<chzigotzky@xenosoft.de> wrote:
>
> Hello,
>
> I compiled the latest Git kernel with the new PowerPC updates
5.11-1 [1] today. Unfortunately this kernel doesn't boot on my FSL P5040
board [2] and in a virtual e5500 QEMU machine [3].
>
> I was able to revert the new PowerPC updates 5.11-1 [4] and after
a new compiling, the kernel boots without any problems on my FSL P5040
board.
>
> Please check the new PowerPC updates 5.11-1.
>
>
> Can you bisect the bad commit?
>
Hello Denis,
I have bisected [5] and d0e3fc69d00d1f50d22d6b6acfc555ccda80ad1e
(powerpc/vdso: Provide __kernel_clock_gettime64() on vdso32) [6] is the
first bad commit.
I was able to revert this bad commit and after a new compiling, the
kernel boots without any problems.
Thanks,
Christian
[5] https://forum.hyperion-entertainment.com/viewtopic.php?p=52077#p52077
[6]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d0e3fc69d00d1f50d22d6b6acfc555ccda80ad1e
>
>
>
> Thanks,
> Christian
>
>
> [1]
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8a5be36b9303ae167468d4f5e1b3c090b9981396
> [2] http://wiki.amiga.org/index.php?title=X5000
> [3] qemu-system-ppc64 -M ppce500 -cpu e5500 -m 1024 -kernel
uImage -drive format=raw,file=MintPPC32-X5000.img,index=0,if=virtio
-netdev user,id=mynet0 -device virtio-net-pci,netdev=mynet0 -append "rw
root=/dev/vda" -device virtio-vga -usb -device usb-ehci,id=ehci -device
usb-tablet -device virtio-keyboard-pci -smp 4 -vnc :1
> [4] git revert 8a5be36b9303ae167468d4f5e1b3c090b9981396 -m 1
>
^ permalink raw reply
* [PATCH 2/5] ibmvfc: make command event pool queue specific
From: Tyrel Datwyler @ 2020-12-18 23:19 UTC (permalink / raw)
To: james.bottomley
Cc: Tyrel Datwyler, martin.petersen, linux-scsi, linux-kernel,
Brian King, brking, linuxppc-dev
In-Reply-To: <20201218231916.279833-1-tyreld@linux.ibm.com>
There is currently a single command event pool per host. In anticipation
of providing multiple queues add a per-queue event pool definition and
reimplement the existing CRQ to use its queue defined event pool for
command submission and completion.
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 95 ++++++++++++++++++----------------
drivers/scsi/ibmvscsi/ibmvfc.h | 10 ++--
2 files changed, 55 insertions(+), 50 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index c8e7c4701ac4..8de2a25b05ee 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -852,12 +852,11 @@ static int ibmvfc_valid_event(struct ibmvfc_event_pool *pool,
**/
static void ibmvfc_free_event(struct ibmvfc_event *evt)
{
- struct ibmvfc_host *vhost = evt->vhost;
- struct ibmvfc_event_pool *pool = &vhost->pool;
+ struct ibmvfc_event_pool *pool = &evt->queue->evt_pool;
BUG_ON(!ibmvfc_valid_event(pool, evt));
BUG_ON(atomic_inc_return(&evt->free) != 1);
- list_add_tail(&evt->queue, &vhost->free);
+ list_add_tail(&evt->queue_list, &evt->queue->free);
}
/**
@@ -898,7 +897,7 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
} else
evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED);
- list_del(&evt->queue);
+ list_del(&evt->queue_list);
del_timer(&evt->timer);
ibmvfc_trc_end(evt);
evt->done(evt);
@@ -917,7 +916,7 @@ static void ibmvfc_purge_requests(struct ibmvfc_host *vhost, int error_code)
struct ibmvfc_event *evt, *pos;
ibmvfc_dbg(vhost, "Purging all requests\n");
- list_for_each_entry_safe(evt, pos, &vhost->sent, queue)
+ list_for_each_entry_safe(evt, pos, &vhost->crq.sent, queue_list)
ibmvfc_fail_request(evt, error_code);
}
@@ -1292,10 +1291,11 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
*
* Returns zero on success.
**/
-static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost)
+static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
+ struct ibmvfc_queue *queue)
{
int i;
- struct ibmvfc_event_pool *pool = &vhost->pool;
+ struct ibmvfc_event_pool *pool = &queue->evt_pool;
ENTER;
pool->size = max_requests + IBMVFC_NUM_INTERNAL_REQ;
@@ -1312,6 +1312,9 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost)
return -ENOMEM;
}
+ INIT_LIST_HEAD(&queue->sent);
+ INIT_LIST_HEAD(&queue->free);
+
for (i = 0; i < pool->size; ++i) {
struct ibmvfc_event *evt = &pool->events[i];
atomic_set(&evt->free, 1);
@@ -1319,8 +1322,9 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost)
evt->crq.ioba = cpu_to_be64(pool->iu_token + (sizeof(*evt->xfer_iu) * i));
evt->xfer_iu = pool->iu_storage + i;
evt->vhost = vhost;
+ evt->queue = queue;
evt->ext_list = NULL;
- list_add_tail(&evt->queue, &vhost->free);
+ list_add_tail(&evt->queue_list, &queue->free);
}
LEAVE;
@@ -1332,14 +1336,15 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost)
* @vhost: ibmvfc host who owns the event pool
*
**/
-static void ibmvfc_free_event_pool(struct ibmvfc_host *vhost)
+static void ibmvfc_free_event_pool(struct ibmvfc_host *vhost,
+ struct ibmvfc_queue *queue)
{
int i;
- struct ibmvfc_event_pool *pool = &vhost->pool;
+ struct ibmvfc_event_pool *pool = &queue->evt_pool;
ENTER;
for (i = 0; i < pool->size; ++i) {
- list_del(&pool->events[i].queue);
+ list_del(&pool->events[i].queue_list);
BUG_ON(atomic_read(&pool->events[i].free) != 1);
if (pool->events[i].ext_list)
dma_pool_free(vhost->sg_pool,
@@ -1360,14 +1365,14 @@ static void ibmvfc_free_event_pool(struct ibmvfc_host *vhost)
*
* Returns a free event from the pool.
**/
-static struct ibmvfc_event *ibmvfc_get_event(struct ibmvfc_host *vhost)
+static struct ibmvfc_event *ibmvfc_get_event(struct ibmvfc_queue *queue)
{
struct ibmvfc_event *evt;
- BUG_ON(list_empty(&vhost->free));
- evt = list_entry(vhost->free.next, struct ibmvfc_event, queue);
+ BUG_ON(list_empty(&queue->free));
+ evt = list_entry(queue->free.next, struct ibmvfc_event, queue_list);
atomic_set(&evt->free, 0);
- list_del(&evt->queue);
+ list_del(&evt->queue_list);
return evt;
}
@@ -1512,7 +1517,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
else
BUG();
- list_add_tail(&evt->queue, &vhost->sent);
+ list_add_tail(&evt->queue_list, &evt->queue->sent);
timer_setup(&evt->timer, ibmvfc_timeout, 0);
if (timeout) {
@@ -1524,7 +1529,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]),
be64_to_cpu(crq_as_u64[1])))) {
- list_del(&evt->queue);
+ list_del(&evt->queue_list);
del_timer(&evt->timer);
/* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY.
@@ -1747,7 +1752,7 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
}
cmnd->result = (DID_OK << 16);
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT);
evt->cmnd = cmnd;
cmnd->scsi_done = done;
@@ -1836,7 +1841,7 @@ static int ibmvfc_bsg_timeout(struct bsg_job *job)
}
vhost->aborting_passthru = 1;
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_bsg_timeout_done, IBMVFC_MAD_FORMAT);
tmf = &evt->iu.tmf;
@@ -1894,7 +1899,7 @@ static int ibmvfc_bsg_plogi(struct ibmvfc_host *vhost, unsigned int port_id)
if (unlikely((rc = ibmvfc_host_chkready(vhost))))
goto unlock_out;
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
plogi = &evt->iu.plogi;
memset(plogi, 0, sizeof(*plogi));
@@ -2012,7 +2017,7 @@ static int ibmvfc_bsg_request(struct bsg_job *job)
goto out;
}
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
mad = &evt->iu.passthru;
@@ -2096,7 +2101,7 @@ static int ibmvfc_reset_device(struct scsi_device *sdev, int type, char *desc)
spin_lock_irqsave(vhost->host->host_lock, flags);
if (vhost->state == IBMVFC_ACTIVE) {
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
tmf = ibmvfc_init_vfc_cmd(evt, sdev);
iu = ibmvfc_get_fcp_iu(vhost, tmf);
@@ -2215,7 +2220,7 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
do {
wait = 0;
spin_lock_irqsave(vhost->host->host_lock, flags);
- list_for_each_entry(evt, &vhost->sent, queue) {
+ list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (match(evt, device)) {
evt->eh_comp = ∁
wait++;
@@ -2229,7 +2234,7 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
if (!timeout) {
wait = 0;
spin_lock_irqsave(vhost->host->host_lock, flags);
- list_for_each_entry(evt, &vhost->sent, queue) {
+ list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (match(evt, device)) {
evt->eh_comp = NULL;
wait++;
@@ -2274,7 +2279,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
ENTER;
spin_lock_irqsave(vhost->host->host_lock, flags);
found_evt = NULL;
- list_for_each_entry(evt, &vhost->sent, queue) {
+ list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (evt->cmnd && evt->cmnd->device == sdev) {
found_evt = evt;
break;
@@ -2289,7 +2294,7 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
}
if (vhost->logged_in) {
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_MAD_FORMAT);
tmf = &evt->iu.tmf;
@@ -2411,7 +2416,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
spin_lock_irqsave(vhost->host->host_lock, flags);
found_evt = NULL;
- list_for_each_entry(evt, &vhost->sent, queue) {
+ list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (evt->cmnd && evt->cmnd->device == sdev) {
found_evt = evt;
break;
@@ -2426,7 +2431,7 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
}
if (vhost->state == IBMVFC_ACTIVE) {
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_sync_completion, IBMVFC_CMD_FORMAT);
tmf = ibmvfc_init_vfc_cmd(evt, sdev);
iu = ibmvfc_get_fcp_iu(vhost, tmf);
@@ -2917,7 +2922,7 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
* things we send. Make sure this response is to something we
* actually sent
*/
- if (unlikely(!ibmvfc_valid_event(&vhost->pool, evt))) {
+ if (unlikely(!ibmvfc_valid_event(&vhost->crq.evt_pool, evt))) {
dev_err(vhost->dev, "Returned correlation_token 0x%08llx is invalid!\n",
crq->ioba);
return;
@@ -2930,7 +2935,7 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
}
del_timer(&evt->timer);
- list_del(&evt->queue);
+ list_del(&evt->queue_list);
ibmvfc_trc_end(evt);
evt->done(evt);
}
@@ -3508,7 +3513,7 @@ static void ibmvfc_tgt_send_prli(struct ibmvfc_target *tgt)
return;
kref_get(&tgt->kref);
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
vhost->discovery_threads++;
ibmvfc_init_event(evt, ibmvfc_tgt_prli_done, IBMVFC_MAD_FORMAT);
evt->tgt = tgt;
@@ -3615,7 +3620,7 @@ static void ibmvfc_tgt_send_plogi(struct ibmvfc_target *tgt)
kref_get(&tgt->kref);
tgt->logo_rcvd = 0;
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
vhost->discovery_threads++;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
ibmvfc_init_event(evt, ibmvfc_tgt_plogi_done, IBMVFC_MAD_FORMAT);
@@ -3690,7 +3695,7 @@ static struct ibmvfc_event *__ibmvfc_tgt_get_implicit_logout_evt(struct ibmvfc_t
struct ibmvfc_event *evt;
kref_get(&tgt->kref);
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, done, IBMVFC_MAD_FORMAT);
evt->tgt = tgt;
mad = &evt->iu.implicit_logout;
@@ -3855,7 +3860,7 @@ static void ibmvfc_tgt_move_login(struct ibmvfc_target *tgt)
return;
kref_get(&tgt->kref);
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
vhost->discovery_threads++;
ibmvfc_set_tgt_action(tgt, IBMVFC_TGT_ACTION_INIT_WAIT);
ibmvfc_init_event(evt, ibmvfc_tgt_move_login_done, IBMVFC_MAD_FORMAT);
@@ -4021,7 +4026,7 @@ static void ibmvfc_adisc_timeout(struct timer_list *t)
vhost->abort_threads++;
kref_get(&tgt->kref);
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_tgt_adisc_cancel_done, IBMVFC_MAD_FORMAT);
evt->tgt = tgt;
@@ -4071,7 +4076,7 @@ static void ibmvfc_tgt_adisc(struct ibmvfc_target *tgt)
return;
kref_get(&tgt->kref);
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
vhost->discovery_threads++;
ibmvfc_init_event(evt, ibmvfc_tgt_adisc_done, IBMVFC_MAD_FORMAT);
evt->tgt = tgt;
@@ -4174,7 +4179,7 @@ static void ibmvfc_tgt_query_target(struct ibmvfc_target *tgt)
return;
kref_get(&tgt->kref);
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
vhost->discovery_threads++;
evt->tgt = tgt;
ibmvfc_init_event(evt, ibmvfc_tgt_query_target_done, IBMVFC_MAD_FORMAT);
@@ -4341,7 +4346,7 @@ static void ibmvfc_discover_targets_done(struct ibmvfc_event *evt)
static void ibmvfc_discover_targets(struct ibmvfc_host *vhost)
{
struct ibmvfc_discover_targets *mad;
- struct ibmvfc_event *evt = ibmvfc_get_event(vhost);
+ struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_discover_targets_done, IBMVFC_MAD_FORMAT);
mad = &evt->iu.discover_targets;
@@ -4454,7 +4459,7 @@ static void ibmvfc_npiv_login_done(struct ibmvfc_event *evt)
static void ibmvfc_npiv_login(struct ibmvfc_host *vhost)
{
struct ibmvfc_npiv_login_mad *mad;
- struct ibmvfc_event *evt = ibmvfc_get_event(vhost);
+ struct ibmvfc_event *evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_gather_partition_info(vhost);
ibmvfc_set_login_info(vhost);
@@ -4491,7 +4496,7 @@ static void ibmvfc_npiv_logout_done(struct ibmvfc_event *evt)
switch (mad_status) {
case IBMVFC_MAD_SUCCESS:
- if (list_empty(&vhost->sent) &&
+ if (list_empty(&vhost->crq.sent) &&
vhost->action == IBMVFC_HOST_ACTION_LOGO_WAIT) {
ibmvfc_init_host(vhost);
return;
@@ -4519,7 +4524,7 @@ static void ibmvfc_npiv_logout(struct ibmvfc_host *vhost)
struct ibmvfc_npiv_logout_mad *mad;
struct ibmvfc_event *evt;
- evt = ibmvfc_get_event(vhost);
+ evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_npiv_logout_done, IBMVFC_MAD_FORMAT);
mad = &evt->iu.npiv_logout;
@@ -5208,8 +5213,6 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
shost->unique_id = shost->host_no;
vhost = shost_priv(shost);
- INIT_LIST_HEAD(&vhost->sent);
- INIT_LIST_HEAD(&vhost->free);
INIT_LIST_HEAD(&vhost->targets);
sprintf(vhost->name, IBMVFC_NAME);
vhost->host = shost;
@@ -5241,7 +5244,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
goto kill_kthread;
}
- if ((rc = ibmvfc_init_event_pool(vhost))) {
+ if ((rc = ibmvfc_init_event_pool(vhost, &vhost->crq))) {
dev_err(dev, "Couldn't initialize event pool. rc=%d\n", rc);
goto release_crq;
}
@@ -5271,7 +5274,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
remove_shost:
scsi_remove_host(shost);
release_event_pool:
- ibmvfc_free_event_pool(vhost);
+ ibmvfc_free_event_pool(vhost, &vhost->crq);
release_crq:
ibmvfc_release_crq_queue(vhost);
kill_kthread:
@@ -5313,7 +5316,7 @@ static int ibmvfc_remove(struct vio_dev *vdev)
spin_lock_irqsave(vhost->host->host_lock, flags);
ibmvfc_purge_requests(vhost, DID_ERROR);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
- ibmvfc_free_event_pool(vhost);
+ ibmvfc_free_event_pool(vhost, &vhost->crq);
ibmvfc_free_mem(vhost);
spin_lock(&ibmvfc_driver_lock);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 5bf1621223d6..61c73b6f7a77 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -726,8 +726,9 @@ struct ibmvfc_target {
/* a unit of work for the hosting partition */
struct ibmvfc_event {
- struct list_head queue;
+ struct list_head queue_list;
struct ibmvfc_host *vhost;
+ struct ibmvfc_queue *queue;
struct ibmvfc_target *tgt;
struct scsi_cmnd *cmnd;
atomic_t free;
@@ -767,6 +768,10 @@ struct ibmvfc_queue {
dma_addr_t msg_token;
enum ibmvfc_msg_fmt fmt;
int size, cur;
+
+ struct ibmvfc_event_pool evt_pool;
+ struct list_head sent;
+ struct list_head free;
};
enum ibmvfc_host_action {
@@ -808,10 +813,7 @@ struct ibmvfc_host {
u32 trace_index:IBMVFC_NUM_TRACE_INDEX_BITS;
int num_targets;
struct list_head targets;
- struct list_head sent;
- struct list_head free;
struct device *dev;
- struct ibmvfc_event_pool pool;
struct dma_pool *sg_pool;
mempool_t *tgt_pool;
struct ibmvfc_queue crq;
--
2.27.0
^ permalink raw reply related
* [PATCH 3/5] ibmvfc: define per-queue state/list locks
From: Tyrel Datwyler @ 2020-12-18 23:19 UTC (permalink / raw)
To: james.bottomley
Cc: Tyrel Datwyler, martin.petersen, linux-scsi, linux-kernel,
Brian King, brking, linuxppc-dev
In-Reply-To: <20201218231916.279833-1-tyreld@linux.ibm.com>
Define per-queue locks for protecting queue state and event pool
sent/free lists. The evt list lock is initially redundant but it allows
the driver to be modified in the follow-up patches to relax the queue
locking around submissions and completions.
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 93 +++++++++++++++++++++++++++-------
drivers/scsi/ibmvscsi/ibmvfc.h | 7 ++-
2 files changed, 80 insertions(+), 20 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 8de2a25b05ee..69a6401ca504 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -176,8 +176,9 @@ static void ibmvfc_trc_start(struct ibmvfc_event *evt)
struct ibmvfc_mad_common *mad = &evt->iu.mad_common;
struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd);
struct ibmvfc_trace_entry *entry;
+ int index = atomic_inc_return(&vhost->trace_index) & IBMVFC_TRACE_INDEX_MASK;
- entry = &vhost->trace[vhost->trace_index++];
+ entry = &vhost->trace[index];
entry->evt = evt;
entry->time = jiffies;
entry->fmt = evt->crq.format;
@@ -211,8 +212,10 @@ static void ibmvfc_trc_end(struct ibmvfc_event *evt)
struct ibmvfc_mad_common *mad = &evt->xfer_iu->mad_common;
struct ibmvfc_fcp_cmd_iu *iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd);
struct ibmvfc_fcp_rsp *rsp = ibmvfc_get_fcp_rsp(vhost, vfc_cmd);
- struct ibmvfc_trace_entry *entry = &vhost->trace[vhost->trace_index++];
+ struct ibmvfc_trace_entry *entry;
+ int index = atomic_inc_return(&vhost->trace_index) & IBMVFC_TRACE_INDEX_MASK;
+ entry = &vhost->trace[index];
entry->evt = evt;
entry->time = jiffies;
entry->fmt = evt->crq.format;
@@ -805,6 +808,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
spin_lock_irqsave(vhost->host->host_lock, flags);
+ spin_lock(vhost->crq.q_lock);
vhost->state = IBMVFC_NO_CRQ;
vhost->logged_in = 0;
@@ -821,6 +825,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
dev_warn(vhost->dev, "Partner adapter not ready\n");
else if (rc != 0)
dev_warn(vhost->dev, "Couldn't register crq (rc=%d)\n", rc);
+ spin_unlock(vhost->crq.q_lock);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
return rc;
@@ -853,10 +858,16 @@ static int ibmvfc_valid_event(struct ibmvfc_event_pool *pool,
static void ibmvfc_free_event(struct ibmvfc_event *evt)
{
struct ibmvfc_event_pool *pool = &evt->queue->evt_pool;
+ unsigned long flags;
BUG_ON(!ibmvfc_valid_event(pool, evt));
BUG_ON(atomic_inc_return(&evt->free) != 1);
+
+ spin_lock_irqsave(&evt->queue->l_lock, flags);
list_add_tail(&evt->queue_list, &evt->queue->free);
+ if (evt->eh_comp)
+ complete(evt->eh_comp);
+ spin_unlock_irqrestore(&evt->queue->l_lock, flags);
}
/**
@@ -875,12 +886,27 @@ static void ibmvfc_scsi_eh_done(struct ibmvfc_event *evt)
cmnd->scsi_done(cmnd);
}
- if (evt->eh_comp)
- complete(evt->eh_comp);
-
ibmvfc_free_event(evt);
}
+/**
+ * ibmvfc_complete_purge - Complete failed command list
+ * @purge_list: list head of failed commands
+ *
+ * This function runs completions on commands to fail as a result of a
+ * host reset or platform migration. Caller must hold host_lock.
+ **/
+static void ibmvfc_complete_purge(struct list_head *purge_list)
+{
+ struct ibmvfc_event *evt, *pos;
+
+ list_for_each_entry_safe(evt, pos, purge_list, queue_list) {
+ list_del(&evt->queue_list);
+ ibmvfc_trc_end(evt);
+ evt->done(evt);
+ }
+}
+
/**
* ibmvfc_fail_request - Fail request with specified error code
* @evt: ibmvfc event struct
@@ -897,10 +923,7 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
} else
evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_DRIVER_FAILED);
- list_del(&evt->queue_list);
del_timer(&evt->timer);
- ibmvfc_trc_end(evt);
- evt->done(evt);
}
/**
@@ -914,10 +937,14 @@ static void ibmvfc_fail_request(struct ibmvfc_event *evt, int error_code)
static void ibmvfc_purge_requests(struct ibmvfc_host *vhost, int error_code)
{
struct ibmvfc_event *evt, *pos;
+ unsigned long flags;
ibmvfc_dbg(vhost, "Purging all requests\n");
+ spin_lock_irqsave(&vhost->crq.l_lock, flags);
list_for_each_entry_safe(evt, pos, &vhost->crq.sent, queue_list)
ibmvfc_fail_request(evt, error_code);
+ list_splice_init(&vhost->crq.sent, &vhost->purge);
+ spin_unlock_irqrestore(&vhost->crq.l_lock, flags);
}
/**
@@ -1314,6 +1341,7 @@ static int ibmvfc_init_event_pool(struct ibmvfc_host *vhost,
INIT_LIST_HEAD(&queue->sent);
INIT_LIST_HEAD(&queue->free);
+ spin_lock_init(&queue->l_lock);
for (i = 0; i < pool->size; ++i) {
struct ibmvfc_event *evt = &pool->events[i];
@@ -1368,11 +1396,14 @@ static void ibmvfc_free_event_pool(struct ibmvfc_host *vhost,
static struct ibmvfc_event *ibmvfc_get_event(struct ibmvfc_queue *queue)
{
struct ibmvfc_event *evt;
+ unsigned long flags;
+ spin_lock_irqsave(&queue->l_lock, flags);
BUG_ON(list_empty(&queue->free));
evt = list_entry(queue->free.next, struct ibmvfc_event, queue_list);
atomic_set(&evt->free, 0);
list_del(&evt->queue_list);
+ spin_unlock_irqrestore(&queue->l_lock, flags);
return evt;
}
@@ -1506,6 +1537,7 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
struct ibmvfc_host *vhost, unsigned long timeout)
{
__be64 *crq_as_u64 = (__be64 *) &evt->crq;
+ unsigned long flags;
int rc;
/* Copy the IU into the transfer area */
@@ -1517,7 +1549,6 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
else
BUG();
- list_add_tail(&evt->queue_list, &evt->queue->sent);
timer_setup(&evt->timer, ibmvfc_timeout, 0);
if (timeout) {
@@ -1525,11 +1556,15 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
add_timer(&evt->timer);
}
+ spin_lock_irqsave(&evt->queue->l_lock, flags);
+ list_add_tail(&evt->queue_list, &evt->queue->sent);
+
mb();
if ((rc = ibmvfc_send_crq(vhost, be64_to_cpu(crq_as_u64[0]),
be64_to_cpu(crq_as_u64[1])))) {
list_del(&evt->queue_list);
+ spin_unlock_irqrestore(&evt->queue->l_lock, flags);
del_timer(&evt->timer);
/* If send_crq returns H_CLOSED, return SCSI_MLQUEUE_HOST_BUSY.
@@ -1554,8 +1589,10 @@ static int ibmvfc_send_event(struct ibmvfc_event *evt,
evt->xfer_iu->mad_common.status = cpu_to_be16(IBMVFC_MAD_CRQ_ERROR);
evt->done(evt);
- } else
+ } else {
+ spin_unlock_irqrestore(&evt->queue->l_lock, flags);
ibmvfc_trc_start(evt);
+ }
return 0;
}
@@ -1663,9 +1700,6 @@ static void ibmvfc_scsi_done(struct ibmvfc_event *evt)
cmnd->scsi_done(cmnd);
}
- if (evt->eh_comp)
- complete(evt->eh_comp);
-
ibmvfc_free_event(evt);
}
@@ -2219,28 +2253,28 @@ static int ibmvfc_wait_for_ops(struct ibmvfc_host *vhost, void *device,
ENTER;
do {
wait = 0;
- spin_lock_irqsave(vhost->host->host_lock, flags);
+ spin_lock_irqsave(&vhost->crq.l_lock, flags);
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (match(evt, device)) {
evt->eh_comp = ∁
wait++;
}
}
- spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ spin_unlock_irqrestore(&vhost->crq.l_lock, flags);
if (wait) {
timeout = wait_for_completion_timeout(&comp, timeout);
if (!timeout) {
wait = 0;
- spin_lock_irqsave(vhost->host->host_lock, flags);
+ spin_lock_irqsave(&vhost->crq.l_lock, flags);
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (match(evt, device)) {
evt->eh_comp = NULL;
wait++;
}
}
- spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ spin_unlock_irqrestore(&vhost->crq.l_lock, flags);
if (wait)
dev_err(vhost->dev, "Timed out waiting for aborted commands\n");
LEAVE;
@@ -2277,14 +2311,16 @@ static int ibmvfc_cancel_all(struct scsi_device *sdev, int type)
u16 status;
ENTER;
- spin_lock_irqsave(vhost->host->host_lock, flags);
found_evt = NULL;
+ spin_lock_irqsave(vhost->host->host_lock, flags);
+ spin_lock(&vhost->crq.l_lock);
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (evt->cmnd && evt->cmnd->device == sdev) {
found_evt = evt;
break;
}
}
+ spin_unlock(&vhost->crq.l_lock);
if (!found_evt) {
if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
@@ -2414,14 +2450,16 @@ static int ibmvfc_abort_task_set(struct scsi_device *sdev)
unsigned long flags, timeout = IBMVFC_ABORT_TIMEOUT;
int rsp_code = 0;
- spin_lock_irqsave(vhost->host->host_lock, flags);
found_evt = NULL;
+ spin_lock_irqsave(vhost->host->host_lock, flags);
+ spin_lock(&vhost->crq.l_lock);
list_for_each_entry(evt, &vhost->crq.sent, queue_list) {
if (evt->cmnd && evt->cmnd->device == sdev) {
found_evt = evt;
break;
}
}
+ spin_unlock(&vhost->crq.l_lock);
if (!found_evt) {
if (vhost->log_level > IBMVFC_DEFAULT_LOG_LEVEL)
@@ -2935,7 +2973,9 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
}
del_timer(&evt->timer);
+ spin_lock(&evt->queue->l_lock);
list_del(&evt->queue_list);
+ spin_unlock(&evt->queue->l_lock);
ibmvfc_trc_end(evt);
evt->done(evt);
}
@@ -3328,6 +3368,7 @@ static void ibmvfc_tasklet(void *data)
int done = 0;
spin_lock_irqsave(vhost->host->host_lock, flags);
+ spin_lock(vhost->crq.q_lock);
while (!done) {
/* Pull all the valid messages off the async CRQ */
while ((async = ibmvfc_next_async_crq(vhost)) != NULL) {
@@ -3358,6 +3399,7 @@ static void ibmvfc_tasklet(void *data)
done = 1;
}
+ spin_unlock(vhost->crq.q_lock);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
}
@@ -4734,6 +4776,7 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
struct ibmvfc_target *tgt;
unsigned long flags;
struct fc_rport *rport;
+ LIST_HEAD(purge);
int rc;
ibmvfc_log_ae(vhost, vhost->events_to_log);
@@ -4746,6 +4789,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
break;
case IBMVFC_HOST_ACTION_RESET:
vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
+ list_splice_init(&vhost->purge, &purge);
+ ibmvfc_complete_purge(&purge);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
rc = ibmvfc_reset_crq(vhost);
spin_lock_irqsave(vhost->host->host_lock, flags);
@@ -4759,6 +4804,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
break;
case IBMVFC_HOST_ACTION_REENABLE:
vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
+ list_splice_init(&vhost->purge, &purge);
+ ibmvfc_complete_purge(&purge);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
rc = ibmvfc_reenable_crq_queue(vhost);
spin_lock_irqsave(vhost->host->host_lock, flags);
@@ -4936,6 +4983,9 @@ static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
size_t fmt_size;
ENTER;
+ spin_lock_init(&queue->_lock);
+ queue->q_lock = &queue->_lock;
+
switch (fmt) {
case IBMVFC_CRQ_FMT:
fmt_size = sizeof(*queue->msgs.crq);
@@ -5098,6 +5148,7 @@ static int ibmvfc_alloc_mem(struct ibmvfc_host *vhost)
vhost->trace = kcalloc(IBMVFC_NUM_TRACE_ENTRIES,
sizeof(struct ibmvfc_trace_entry), GFP_KERNEL);
+ atomic_set(&vhost->trace_index, -1);
if (!vhost->trace)
goto free_disc_buffer;
@@ -5214,6 +5265,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
vhost = shost_priv(shost);
INIT_LIST_HEAD(&vhost->targets);
+ INIT_LIST_HEAD(&vhost->purge);
sprintf(vhost->name, IBMVFC_NAME);
vhost->host = shost;
vhost->dev = dev;
@@ -5298,6 +5350,7 @@ static int ibmvfc_probe(struct vio_dev *vdev, const struct vio_device_id *id)
static int ibmvfc_remove(struct vio_dev *vdev)
{
struct ibmvfc_host *vhost = dev_get_drvdata(&vdev->dev);
+ LIST_HEAD(purge);
unsigned long flags;
ENTER;
@@ -5315,6 +5368,8 @@ static int ibmvfc_remove(struct vio_dev *vdev)
spin_lock_irqsave(vhost->host->host_lock, flags);
ibmvfc_purge_requests(vhost, DID_ERROR);
+ list_splice_init(&vhost->purge, &purge);
+ ibmvfc_complete_purge(&purge);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
ibmvfc_free_event_pool(vhost, &vhost->crq);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 61c73b6f7a77..faf5b50d65b9 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -768,10 +768,13 @@ struct ibmvfc_queue {
dma_addr_t msg_token;
enum ibmvfc_msg_fmt fmt;
int size, cur;
+ spinlock_t _lock;
+ spinlock_t *q_lock;
struct ibmvfc_event_pool evt_pool;
struct list_head sent;
struct list_head free;
+ spinlock_t l_lock;
};
enum ibmvfc_host_action {
@@ -808,11 +811,13 @@ struct ibmvfc_host {
enum ibmvfc_host_action action;
#define IBMVFC_NUM_TRACE_INDEX_BITS 8
#define IBMVFC_NUM_TRACE_ENTRIES (1 << IBMVFC_NUM_TRACE_INDEX_BITS)
+#define IBMVFC_TRACE_INDEX_MASK (IBMVFC_NUM_TRACE_ENTRIES - 1)
#define IBMVFC_TRACE_SIZE (sizeof(struct ibmvfc_trace_entry) * IBMVFC_NUM_TRACE_ENTRIES)
struct ibmvfc_trace_entry *trace;
- u32 trace_index:IBMVFC_NUM_TRACE_INDEX_BITS;
+ atomic_t trace_index;
int num_targets;
struct list_head targets;
+ struct list_head purge;
struct device *dev;
struct dma_pool *sg_pool;
mempool_t *tgt_pool;
--
2.27.0
^ permalink raw reply related
* [PATCH 1/5] ibmvfc: define generic queue structure for CRQs
From: Tyrel Datwyler @ 2020-12-18 23:19 UTC (permalink / raw)
To: james.bottomley
Cc: Tyrel Datwyler, martin.petersen, linux-scsi, linux-kernel,
Brian King, brking, linuxppc-dev
In-Reply-To: <20201218231916.279833-1-tyreld@linux.ibm.com>
The primary and async CRQs are nearly identical outside of the format
and length of each message entry in the dma mapped page that represents
the queue data. These queues can be represented with a generic queue
structure that uses a union to differentiate between message format of
the mapped page.
This structure will further be leveraged in a followup patcheset that
introduce Sub-CRQs.
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 135 +++++++++++++++++++++------------
drivers/scsi/ibmvscsi/ibmvfc.h | 34 +++++----
2 files changed, 107 insertions(+), 62 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 42e4d35e0d35..c8e7c4701ac4 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -660,7 +660,7 @@ static void ibmvfc_init_host(struct ibmvfc_host *vhost)
}
if (!ibmvfc_set_host_state(vhost, IBMVFC_INITIALIZING)) {
- memset(vhost->async_crq.msgs, 0, PAGE_SIZE);
+ memset(vhost->async_crq.msgs.async, 0, PAGE_SIZE);
vhost->async_crq.cur = 0;
list_for_each_entry(tgt, &vhost->targets, queue)
@@ -713,6 +713,23 @@ static int ibmvfc_send_crq_init_complete(struct ibmvfc_host *vhost)
return ibmvfc_send_crq(vhost, 0xC002000000000000LL, 0);
}
+/**
+ * ibmvfc_free_queue - Deallocate queue
+ * @vhost: ibmvfc host struct
+ * @queue: ibmvfc queue struct
+ *
+ * Unmaps dma and deallocates page for messages
+ **/
+static void ibmvfc_free_queue(struct ibmvfc_host *vhost,
+ struct ibmvfc_queue *queue)
+{
+ struct device *dev = vhost->dev;
+
+ dma_unmap_single(dev, queue->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL);
+ free_page((unsigned long)queue->msgs.handle);
+ queue->msgs.handle = NULL;
+}
+
/**
* ibmvfc_release_crq_queue - Deallocates data and unregisters CRQ
* @vhost: ibmvfc host struct
@@ -724,7 +741,7 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost)
{
long rc = 0;
struct vio_dev *vdev = to_vio_dev(vhost->dev);
- struct ibmvfc_crq_queue *crq = &vhost->crq;
+ struct ibmvfc_queue *crq = &vhost->crq;
ibmvfc_dbg(vhost, "Releasing CRQ\n");
free_irq(vdev->irq, vhost);
@@ -737,8 +754,8 @@ static void ibmvfc_release_crq_queue(struct ibmvfc_host *vhost)
vhost->state = IBMVFC_NO_CRQ;
vhost->logged_in = 0;
- dma_unmap_single(vhost->dev, crq->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL);
- free_page((unsigned long)crq->msgs);
+
+ ibmvfc_free_queue(vhost, crq);
}
/**
@@ -778,7 +795,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
int rc = 0;
unsigned long flags;
struct vio_dev *vdev = to_vio_dev(vhost->dev);
- struct ibmvfc_crq_queue *crq = &vhost->crq;
+ struct ibmvfc_queue *crq = &vhost->crq;
/* Close the CRQ */
do {
@@ -792,7 +809,7 @@ static int ibmvfc_reset_crq(struct ibmvfc_host *vhost)
vhost->logged_in = 0;
/* Clean out the queue */
- memset(crq->msgs, 0, PAGE_SIZE);
+ memset(crq->msgs.crq, 0, PAGE_SIZE);
crq->cur = 0;
/* And re-open it again */
@@ -1238,6 +1255,7 @@ static void ibmvfc_gather_partition_info(struct ibmvfc_host *vhost)
static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
{
struct ibmvfc_npiv_login *login_info = &vhost->login_info;
+ struct ibmvfc_queue *async_crq = &vhost->async_crq;
struct device_node *of_node = vhost->dev->of_node;
const char *location;
@@ -1257,7 +1275,8 @@ static void ibmvfc_set_login_info(struct ibmvfc_host *vhost)
login_info->max_cmds = cpu_to_be32(max_requests + IBMVFC_NUM_INTERNAL_REQ);
login_info->capabilities = cpu_to_be64(IBMVFC_CAN_MIGRATE | IBMVFC_CAN_SEND_VF_WWPN);
login_info->async.va = cpu_to_be64(vhost->async_crq.msg_token);
- login_info->async.len = cpu_to_be32(vhost->async_crq.size * sizeof(*vhost->async_crq.msgs));
+ login_info->async.len = cpu_to_be32(async_crq->size *
+ sizeof(*async_crq->msgs.async));
strncpy(login_info->partition_name, vhost->partition_name, IBMVFC_MAX_NAME);
strncpy(login_info->device_name,
dev_name(&vhost->host->shost_gendev), IBMVFC_MAX_NAME);
@@ -3230,10 +3249,10 @@ static struct scsi_host_template driver_template = {
**/
static struct ibmvfc_async_crq *ibmvfc_next_async_crq(struct ibmvfc_host *vhost)
{
- struct ibmvfc_async_crq_queue *async_crq = &vhost->async_crq;
+ struct ibmvfc_queue *async_crq = &vhost->async_crq;
struct ibmvfc_async_crq *crq;
- crq = &async_crq->msgs[async_crq->cur];
+ crq = &async_crq->msgs.async[async_crq->cur];
if (crq->valid & 0x80) {
if (++async_crq->cur == async_crq->size)
async_crq->cur = 0;
@@ -3253,10 +3272,10 @@ static struct ibmvfc_async_crq *ibmvfc_next_async_crq(struct ibmvfc_host *vhost)
**/
static struct ibmvfc_crq *ibmvfc_next_crq(struct ibmvfc_host *vhost)
{
- struct ibmvfc_crq_queue *queue = &vhost->crq;
+ struct ibmvfc_queue *queue = &vhost->crq;
struct ibmvfc_crq *crq;
- crq = &queue->msgs[queue->cur];
+ crq = &queue->msgs.crq[queue->cur];
if (crq->valid & 0x80) {
if (++queue->cur == queue->size)
queue->cur = 0;
@@ -4895,6 +4914,54 @@ static int ibmvfc_work(void *data)
return 0;
}
+/**
+ * ibmvfc_alloc_queue - Allocate queue
+ * @vhost: ibmvfc host struct
+ * @queue: ibmvfc queue to allocate
+ * @fmt: queue format to allocate
+ *
+ * Returns:
+ * 0 on success / non-zero on failure
+ **/
+static int ibmvfc_alloc_queue(struct ibmvfc_host *vhost,
+ struct ibmvfc_queue *queue,
+ enum ibmvfc_msg_fmt fmt)
+{
+ struct device *dev = vhost->dev;
+ size_t fmt_size;
+
+ ENTER;
+ switch (fmt) {
+ case IBMVFC_CRQ_FMT:
+ fmt_size = sizeof(*queue->msgs.crq);
+ break;
+ case IBMVFC_ASYNC_FMT:
+ fmt_size = sizeof(*queue->msgs.async);
+ break;
+ default:
+ dev_warn(dev, "Unknown command/response queue message format: %d\n", fmt);
+ return -EINVAL;
+ }
+
+ queue->msgs.handle = (void *)get_zeroed_page(GFP_KERNEL);
+ if (!queue->msgs.handle)
+ return -ENOMEM;
+
+ queue->msg_token = dma_map_single(dev, queue->msgs.handle, PAGE_SIZE,
+ DMA_BIDIRECTIONAL);
+
+ if (dma_mapping_error(dev, queue->msg_token)) {
+ free_page((unsigned long)queue->msgs.handle);
+ queue->msgs.handle = NULL;
+ return -ENOMEM;
+ }
+
+ queue->cur = 0;
+ queue->fmt = fmt;
+ queue->size = PAGE_SIZE / fmt_size;
+ return 0;
+}
+
/**
* ibmvfc_init_crq - Initializes and registers CRQ with hypervisor
* @vhost: ibmvfc host struct
@@ -4910,21 +4977,12 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
int rc, retrc = -ENOMEM;
struct device *dev = vhost->dev;
struct vio_dev *vdev = to_vio_dev(dev);
- struct ibmvfc_crq_queue *crq = &vhost->crq;
+ struct ibmvfc_queue *crq = &vhost->crq;
ENTER;
- crq->msgs = (struct ibmvfc_crq *)get_zeroed_page(GFP_KERNEL);
-
- if (!crq->msgs)
+ if (ibmvfc_alloc_queue(vhost, crq, IBMVFC_CRQ_FMT))
return -ENOMEM;
- crq->size = PAGE_SIZE / sizeof(*crq->msgs);
- crq->msg_token = dma_map_single(dev, crq->msgs,
- PAGE_SIZE, DMA_BIDIRECTIONAL);
-
- if (dma_mapping_error(dev, crq->msg_token))
- goto map_failed;
-
retrc = rc = plpar_hcall_norets(H_REG_CRQ, vdev->unit_address,
crq->msg_token, PAGE_SIZE);
@@ -4953,7 +5011,6 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
goto req_irq_failed;
}
- crq->cur = 0;
LEAVE;
return retrc;
@@ -4963,9 +5020,7 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
rc = plpar_hcall_norets(H_FREE_CRQ, vdev->unit_address);
} while (rc == H_BUSY || H_IS_LONG_BUSY(rc));
reg_crq_failed:
- dma_unmap_single(dev, crq->msg_token, PAGE_SIZE, DMA_BIDIRECTIONAL);
-map_failed:
- free_page((unsigned long)crq->msgs);
+ ibmvfc_free_queue(vhost, crq);
return retrc;
}
@@ -4978,7 +5033,7 @@ static int ibmvfc_init_crq(struct ibmvfc_host *vhost)
**/
static void ibmvfc_free_mem(struct ibmvfc_host *vhost)
{
- struct ibmvfc_async_crq_queue *async_q = &vhost->async_crq;
+ struct ibmvfc_queue *async_q = &vhost->async_crq;
ENTER;
mempool_destroy(vhost->tgt_pool);
@@ -4988,9 +5043,7 @@ static void ibmvfc_free_mem(struct ibmvfc_host *vhost)
dma_free_coherent(vhost->dev, sizeof(*vhost->login_buf),
vhost->login_buf, vhost->login_buf_dma);
dma_pool_destroy(vhost->sg_pool);
- dma_unmap_single(vhost->dev, async_q->msg_token,
- async_q->size * sizeof(*async_q->msgs), DMA_BIDIRECTIONAL);
- free_page((unsigned long)async_q->msgs);
+ ibmvfc_free_queue(vhost, async_q);
LEAVE;
}
@@ -5003,26 +5056,15 @@ static void ibmvfc_free_mem(struct ibmvfc_host *vhost)
**/
static int ibmvfc_alloc_mem(struct ibmvfc_host *vhost)
{
- struct ibmvfc_async_crq_queue *async_q = &vhost->async_crq;
+ struct ibmvfc_queue *async_q = &vhost->async_crq;
struct device *dev = vhost->dev;
ENTER;
- async_q->msgs = (struct ibmvfc_async_crq *)get_zeroed_page(GFP_KERNEL);
- if (!async_q->msgs) {
- dev_err(dev, "Couldn't allocate async queue.\n");
+ if (ibmvfc_alloc_queue(vhost, async_q, IBMVFC_ASYNC_FMT)) {
+ dev_err(dev, "Couldn't allocate/map async queue.\n");
goto nomem;
}
- async_q->size = PAGE_SIZE / sizeof(struct ibmvfc_async_crq);
- async_q->msg_token = dma_map_single(dev, async_q->msgs,
- async_q->size * sizeof(*async_q->msgs),
- DMA_BIDIRECTIONAL);
-
- if (dma_mapping_error(dev, async_q->msg_token)) {
- dev_err(dev, "Failed to map async queue\n");
- goto free_async_crq;
- }
-
vhost->sg_pool = dma_pool_create(IBMVFC_NAME, dev,
SG_ALL * sizeof(struct srp_direct_buf),
sizeof(struct srp_direct_buf), 0);
@@ -5077,10 +5119,7 @@ static int ibmvfc_alloc_mem(struct ibmvfc_host *vhost)
free_sg_pool:
dma_pool_destroy(vhost->sg_pool);
unmap_async_crq:
- dma_unmap_single(dev, async_q->msg_token,
- async_q->size * sizeof(*async_q->msgs), DMA_BIDIRECTIONAL);
-free_async_crq:
- free_page((unsigned long)async_q->msgs);
+ ibmvfc_free_queue(vhost, async_q);
nomem:
LEAVE;
return -ENOMEM;
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index 9d58cfd774d3..5bf1621223d6 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -645,12 +645,6 @@ struct ibmvfc_crq {
volatile __be64 ioba;
} __packed __aligned(8);
-struct ibmvfc_crq_queue {
- struct ibmvfc_crq *msgs;
- int size, cur;
- dma_addr_t msg_token;
-};
-
enum ibmvfc_ae_link_state {
IBMVFC_AE_LS_LINK_UP = 0x01,
IBMVFC_AE_LS_LINK_BOUNCED = 0x02,
@@ -678,12 +672,6 @@ struct ibmvfc_async_crq {
__be64 reserved;
} __packed __aligned(8);
-struct ibmvfc_async_crq_queue {
- struct ibmvfc_async_crq *msgs;
- int size, cur;
- dma_addr_t msg_token;
-};
-
union ibmvfc_iu {
struct ibmvfc_mad_common mad_common;
struct ibmvfc_npiv_login_mad npiv_login;
@@ -763,6 +751,24 @@ struct ibmvfc_event_pool {
dma_addr_t iu_token;
};
+enum ibmvfc_msg_fmt {
+ IBMVFC_CRQ_FMT = 0,
+ IBMVFC_ASYNC_FMT,
+};
+
+union ibmvfc_msgs {
+ void *handle;
+ struct ibmvfc_crq *crq;
+ struct ibmvfc_async_crq *async;
+};
+
+struct ibmvfc_queue {
+ union ibmvfc_msgs msgs;
+ dma_addr_t msg_token;
+ enum ibmvfc_msg_fmt fmt;
+ int size, cur;
+};
+
enum ibmvfc_host_action {
IBMVFC_HOST_ACTION_NONE = 0,
IBMVFC_HOST_ACTION_RESET,
@@ -808,8 +814,8 @@ struct ibmvfc_host {
struct ibmvfc_event_pool pool;
struct dma_pool *sg_pool;
mempool_t *tgt_pool;
- struct ibmvfc_crq_queue crq;
- struct ibmvfc_async_crq_queue async_crq;
+ struct ibmvfc_queue crq;
+ struct ibmvfc_queue async_crq;
struct ibmvfc_npiv_login login_info;
union ibmvfc_npiv_login_data *login_buf;
dma_addr_t login_buf_dma;
--
2.27.0
^ permalink raw reply related
* [PATCH 4/5] ibmvfc: complete commands outside the host/queue lock
From: Tyrel Datwyler @ 2020-12-18 23:19 UTC (permalink / raw)
To: james.bottomley
Cc: Tyrel Datwyler, martin.petersen, linux-scsi, linux-kernel,
Brian King, brking, linuxppc-dev
In-Reply-To: <20201218231916.279833-1-tyreld@linux.ibm.com>
Drain the command queue and place all commands on a completion list.
Perform command completion on that list outside the host/queue locks.
Further, move purged command compeletions outside the host_lock as well.
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 58 ++++++++++++++++++++++++++--------
drivers/scsi/ibmvscsi/ibmvfc.h | 3 +-
2 files changed, 47 insertions(+), 14 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index 69a6401ca504..b74080489807 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -894,7 +894,7 @@ static void ibmvfc_scsi_eh_done(struct ibmvfc_event *evt)
* @purge_list: list head of failed commands
*
* This function runs completions on commands to fail as a result of a
- * host reset or platform migration. Caller must hold host_lock.
+ * host reset or platform migration.
**/
static void ibmvfc_complete_purge(struct list_head *purge_list)
{
@@ -1407,6 +1407,23 @@ static struct ibmvfc_event *ibmvfc_get_event(struct ibmvfc_queue *queue)
return evt;
}
+/**
+ * ibmvfc_locked_done - Calls evt completion with host_lock held
+ * @evt: ibmvfc evt to complete
+ *
+ * All non-scsi command completion callbacks have the expectation that the
+ * host_lock is held. This callback is used by ibmvfc_init_event to wrap a
+ * MAD evt with the host_lock.
+ **/
+void ibmvfc_locked_done(struct ibmvfc_event *evt)
+{
+ unsigned long flags;
+
+ spin_lock_irqsave(evt->vhost->host->host_lock, flags);
+ evt->_done(evt);
+ spin_unlock_irqrestore(evt->vhost->host->host_lock, flags);
+}
+
/**
* ibmvfc_init_event - Initialize fields in an event struct that are always
* required.
@@ -1419,9 +1436,14 @@ static void ibmvfc_init_event(struct ibmvfc_event *evt,
{
evt->cmnd = NULL;
evt->sync_iu = NULL;
- evt->crq.format = format;
- evt->done = done;
evt->eh_comp = NULL;
+ evt->crq.format = format;
+ if (format == IBMVFC_CMD_FORMAT)
+ evt->done = done;
+ else {
+ evt->_done = done;
+ evt->done = ibmvfc_locked_done;
+ }
}
/**
@@ -1640,7 +1662,9 @@ static void ibmvfc_relogin(struct scsi_device *sdev)
struct ibmvfc_host *vhost = shost_priv(sdev->host);
struct fc_rport *rport = starget_to_rport(scsi_target(sdev));
struct ibmvfc_target *tgt;
+ unsigned long flags;
+ spin_lock_irqsave(vhost->host->host_lock, flags);
list_for_each_entry(tgt, &vhost->targets, queue) {
if (rport == tgt->rport) {
ibmvfc_del_tgt(tgt);
@@ -1649,6 +1673,7 @@ static void ibmvfc_relogin(struct scsi_device *sdev)
}
ibmvfc_reinit_host(vhost);
+ spin_unlock_irqrestore(vhost->host->host_lock, flags);
}
/**
@@ -2901,7 +2926,8 @@ static void ibmvfc_handle_async(struct ibmvfc_async_crq *crq,
* @vhost: ibmvfc host struct
*
**/
-static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
+static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost,
+ struct list_head *evt_doneq)
{
long rc;
struct ibmvfc_event *evt = (struct ibmvfc_event *)be64_to_cpu(crq->ioba);
@@ -2972,12 +2998,9 @@ static void ibmvfc_handle_crq(struct ibmvfc_crq *crq, struct ibmvfc_host *vhost)
return;
}
- del_timer(&evt->timer);
spin_lock(&evt->queue->l_lock);
- list_del(&evt->queue_list);
+ list_move_tail(&evt->queue_list, evt_doneq);
spin_unlock(&evt->queue->l_lock);
- ibmvfc_trc_end(evt);
- evt->done(evt);
}
/**
@@ -3364,8 +3387,10 @@ static void ibmvfc_tasklet(void *data)
struct vio_dev *vdev = to_vio_dev(vhost->dev);
struct ibmvfc_crq *crq;
struct ibmvfc_async_crq *async;
+ struct ibmvfc_event *evt, *temp;
unsigned long flags;
int done = 0;
+ LIST_HEAD(evt_doneq);
spin_lock_irqsave(vhost->host->host_lock, flags);
spin_lock(vhost->crq.q_lock);
@@ -3379,7 +3404,7 @@ static void ibmvfc_tasklet(void *data)
/* Pull all the valid messages off the CRQ */
while ((crq = ibmvfc_next_crq(vhost)) != NULL) {
- ibmvfc_handle_crq(crq, vhost);
+ ibmvfc_handle_crq(crq, vhost, &evt_doneq);
crq->valid = 0;
wmb();
}
@@ -3392,7 +3417,7 @@ static void ibmvfc_tasklet(void *data)
wmb();
} else if ((crq = ibmvfc_next_crq(vhost)) != NULL) {
vio_disable_interrupts(vdev);
- ibmvfc_handle_crq(crq, vhost);
+ ibmvfc_handle_crq(crq, vhost, &evt_doneq);
crq->valid = 0;
wmb();
} else
@@ -3401,6 +3426,13 @@ static void ibmvfc_tasklet(void *data)
spin_unlock(vhost->crq.q_lock);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
+
+ list_for_each_entry_safe(evt, temp, &evt_doneq, queue_list) {
+ del_timer(&evt->timer);
+ list_del(&evt->queue_list);
+ ibmvfc_trc_end(evt);
+ evt->done(evt);
+ }
}
/**
@@ -4790,8 +4822,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
case IBMVFC_HOST_ACTION_RESET:
vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
list_splice_init(&vhost->purge, &purge);
- ibmvfc_complete_purge(&purge);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ ibmvfc_complete_purge(&purge);
rc = ibmvfc_reset_crq(vhost);
spin_lock_irqsave(vhost->host->host_lock, flags);
if (rc == H_CLOSED)
@@ -4805,8 +4837,8 @@ static void ibmvfc_do_work(struct ibmvfc_host *vhost)
case IBMVFC_HOST_ACTION_REENABLE:
vhost->action = IBMVFC_HOST_ACTION_TGT_DEL;
list_splice_init(&vhost->purge, &purge);
- ibmvfc_complete_purge(&purge);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ ibmvfc_complete_purge(&purge);
rc = ibmvfc_reenable_crq_queue(vhost);
spin_lock_irqsave(vhost->host->host_lock, flags);
if (rc || (rc = ibmvfc_send_crq_init(vhost))) {
@@ -5369,8 +5401,8 @@ static int ibmvfc_remove(struct vio_dev *vdev)
spin_lock_irqsave(vhost->host->host_lock, flags);
ibmvfc_purge_requests(vhost, DID_ERROR);
list_splice_init(&vhost->purge, &purge);
- ibmvfc_complete_purge(&purge);
spin_unlock_irqrestore(vhost->host->host_lock, flags);
+ ibmvfc_complete_purge(&purge);
ibmvfc_free_event_pool(vhost, &vhost->crq);
ibmvfc_free_mem(vhost);
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.h b/drivers/scsi/ibmvscsi/ibmvfc.h
index faf5b50d65b9..632e977449c5 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.h
+++ b/drivers/scsi/ibmvscsi/ibmvfc.h
@@ -733,7 +733,8 @@ struct ibmvfc_event {
struct scsi_cmnd *cmnd;
atomic_t free;
union ibmvfc_iu *xfer_iu;
- void (*done) (struct ibmvfc_event *);
+ void (*done)(struct ibmvfc_event *evt);
+ void (*_done)(struct ibmvfc_event *evt);
struct ibmvfc_crq crq;
union ibmvfc_iu iu;
union ibmvfc_iu *sync_iu;
--
2.27.0
^ permalink raw reply related
* [PATCH 5/5] ibmvfc: relax locking around ibmvfc_queuecommand
From: Tyrel Datwyler @ 2020-12-18 23:19 UTC (permalink / raw)
To: james.bottomley
Cc: Tyrel Datwyler, martin.petersen, linux-scsi, linux-kernel,
Brian King, brking, linuxppc-dev
In-Reply-To: <20201218231916.279833-1-tyreld@linux.ibm.com>
The drivers queuecommand routine is still wrapped to hold the host lock
for the duration of the call. This will become problematic when moving
to multiple queues due to the lock contention preventing asynchronous
submissions to mulitple queues. There is no real legatimate reason to
hold the host lock, and previous patches have insured proper protection
of moving ibmvfc_event objects between free and sent lists.
Signed-off-by: Tyrel Datwyler <tyreld@linux.ibm.com>
Reviewed-by: Brian King <brking@linux.vnet.ibm.com>
---
drivers/scsi/ibmvscsi/ibmvfc.c | 12 ++++--------
1 file changed, 4 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/ibmvscsi/ibmvfc.c b/drivers/scsi/ibmvscsi/ibmvfc.c
index b74080489807..151e9111ab8a 100644
--- a/drivers/scsi/ibmvscsi/ibmvfc.c
+++ b/drivers/scsi/ibmvscsi/ibmvfc.c
@@ -1793,10 +1793,9 @@ static struct ibmvfc_cmd *ibmvfc_init_vfc_cmd(struct ibmvfc_event *evt, struct s
* Returns:
* 0 on success / other on failure
**/
-static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
- void (*done) (struct scsi_cmnd *))
+static int ibmvfc_queuecommand(struct Scsi_Host *shost, struct scsi_cmnd *cmnd)
{
- struct ibmvfc_host *vhost = shost_priv(cmnd->device->host);
+ struct ibmvfc_host *vhost = shost_priv(shost);
struct fc_rport *rport = starget_to_rport(scsi_target(cmnd->device));
struct ibmvfc_cmd *vfc_cmd;
struct ibmvfc_fcp_cmd_iu *iu;
@@ -1806,7 +1805,7 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
if (unlikely((rc = fc_remote_port_chkready(rport))) ||
unlikely((rc = ibmvfc_host_chkready(vhost)))) {
cmnd->result = rc;
- done(cmnd);
+ cmnd->scsi_done(cmnd);
return 0;
}
@@ -1814,7 +1813,6 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
evt = ibmvfc_get_event(&vhost->crq);
ibmvfc_init_event(evt, ibmvfc_scsi_done, IBMVFC_CMD_FORMAT);
evt->cmnd = cmnd;
- cmnd->scsi_done = done;
vfc_cmd = ibmvfc_init_vfc_cmd(evt, cmnd->device);
iu = ibmvfc_get_fcp_iu(vhost, vfc_cmd);
@@ -1841,12 +1839,10 @@ static int ibmvfc_queuecommand_lck(struct scsi_cmnd *cmnd,
"Failed to map DMA buffer for command. rc=%d\n", rc);
cmnd->result = DID_ERROR << 16;
- done(cmnd);
+ cmnd->scsi_done(cmnd);
return 0;
}
-static DEF_SCSI_QCMD(ibmvfc_queuecommand)
-
/**
* ibmvfc_sync_completion - Signal that a synchronous command has completed
* @evt: ibmvfc event struct
--
2.27.0
^ permalink raw reply related
* [PATCH 0/5] ibmvfc: MQ preparatory locking work
From: Tyrel Datwyler @ 2020-12-18 23:19 UTC (permalink / raw)
To: james.bottomley
Cc: Tyrel Datwyler, martin.petersen, linux-scsi, linux-kernel, brking,
linuxppc-dev
The ibmvfc driver in its current form relies heavily on the host_lock. This
patchset introduces a genric queue with its own queue lock and sent/free event
list locks. This generic queue allows the driver to decouple the primary queue
and future subordinate queues from the host lock reducing lock contention while
also relaxing locking for submissions and completions to simply the list lock of
the queue in question.
Tyrel Datwyler (5):
ibmvfc: define generic queue structure for CRQs
ibmvfc: make command event pool queue specific
ibmvfc: define per-queue state/list locks
ibmvfc: complete commands outside the host/queue lock
ibmvfc: relax locking around ibmvfc_queuecommand
drivers/scsi/ibmvscsi/ibmvfc.c | 379 ++++++++++++++++++++++-----------
drivers/scsi/ibmvscsi/ibmvfc.h | 54 +++--
2 files changed, 286 insertions(+), 147 deletions(-)
--
2.27.0
^ permalink raw reply
* Re: GIT kernel with the PowerPC updates 5.11-1 doesn't boot on a FSL P5040 board and in a virtual e5500 QEMU machine
From: Christian Zigotzky @ 2020-12-19 0:38 UTC (permalink / raw)
To: Denis Kirjanov; +Cc: Darren Stevens, mad skateman, R.T.Dickinson, linuxppc-dev
In-Reply-To: <ad682b81-60f6-4e13-46f4-39539de2be72@xenosoft.de>
On 18 December 2020 at 11:49pm, Christian Zigotzky wrote:
> On 18 December 2020 at 10:25pm, Denis Kirjanov wrote:
> >
> >
> > On Friday, December 18, 2020, Christian Zigotzky
> <chzigotzky@xenosoft.de> wrote:
> >
> > Hello,
> >
> > I compiled the latest Git kernel with the new PowerPC updates
> 5.11-1 [1] today. Unfortunately this kernel doesn't boot on my FSL
> P5040 board [2] and in a virtual e5500 QEMU machine [3].
> >
> > I was able to revert the new PowerPC updates 5.11-1 [4] and
> after a new compiling, the kernel boots without any problems on my FSL
> P5040 board.
> >
> > Please check the new PowerPC updates 5.11-1.
> >
> >
> > Can you bisect the bad commit?
> >
> Hello Denis,
>
> I have bisected [5] and d0e3fc69d00d1f50d22d6b6acfc555ccda80ad1e
> (powerpc/vdso: Provide __kernel_clock_gettime64() on vdso32) [6] is
> the first bad commit.
>
> I was able to revert this bad commit and after a new compiling, the
> kernel boots without any problems.
>
> Thanks,
> Christian
>
> [5] https://forum.hyperion-entertainment.com/viewtopic.php?p=52077#p52077
> [6]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=d0e3fc69d00d1f50d22d6b6acfc555ccda80ad1e
>
> >
> >
> >
> > Thanks,
> > Christian
> >
> >
> > [1]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=8a5be36b9303ae167468d4f5e1b3c090b9981396
> > [2] http://wiki.amiga.org/index.php?title=X5000
> > [3] qemu-system-ppc64 -M ppce500 -cpu e5500 -m 1024 -kernel
> uImage -drive format=raw,file=MintPPC32-X5000.img,index=0,if=virtio
> -netdev user,id=mynet0 -device virtio-net-pci,netdev=mynet0 -append
> "rw root=/dev/vda" -device virtio-vga -usb -device usb-ehci,id=ehci
> -device usb-tablet -device virtio-keyboard-pci -smp 4 -vnc :1
> > [4] git revert 8a5be36b9303ae167468d4f5e1b3c090b9981396 -m 1
> >
>
Hello,
I created a patch for reverting the bad commit. I can boot the latest
Git kernel compiled with this patch on my FSL P5040 board and in a
virtual e5500 QEMU machine.
------
diff -rupN a/arch/powerpc/include/asm/vdso/gettimeofday.h
b/arch/powerpc/include/asm/vdso/gettimeofday.h
--- a/arch/powerpc/include/asm/vdso/gettimeofday.h 2020-12-19
00:01:16.825846606 +0100
+++ b/arch/powerpc/include/asm/vdso/gettimeofday.h 2020-12-19
00:00:38.213374736 +0100
@@ -187,8 +187,6 @@ int __c_kernel_clock_getres(clockid_t cl
#else
int __c_kernel_clock_gettime(clockid_t clock, struct old_timespec32 *ts,
const struct vdso_data *vd);
-int __c_kernel_clock_gettime64(clockid_t clock, struct
__kernel_timespec *ts,
- const struct vdso_data *vd);
int __c_kernel_clock_getres(clockid_t clock_id, struct old_timespec32
*res,
const struct vdso_data *vd);
#endif
diff -rupN a/arch/powerpc/kernel/vdso32/gettimeofday.S
b/arch/powerpc/kernel/vdso32/gettimeofday.S
--- a/arch/powerpc/kernel/vdso32/gettimeofday.S 2020-12-19
00:01:16.829846652 +0100
+++ b/arch/powerpc/kernel/vdso32/gettimeofday.S 2020-12-19
00:00:37.817369691 +0100
@@ -35,15 +35,6 @@ V_FUNCTION_BEGIN(__kernel_clock_gettime)
cvdso_call __c_kernel_clock_gettime
V_FUNCTION_END(__kernel_clock_gettime)
-/*
- * Exact prototype of clock_gettime64()
- *
- * int __kernel_clock_gettime64(clockid_t clock_id, struct __timespec64
*ts);
- *
- */
-V_FUNCTION_BEGIN(__kernel_clock_gettime64)
- cvdso_call __c_kernel_clock_gettime64
-V_FUNCTION_END(__kernel_clock_gettime64)
/*
* Exact prototype of clock_getres()
diff -rupN a/arch/powerpc/kernel/vdso32/vdso32.lds.S
b/arch/powerpc/kernel/vdso32/vdso32.lds.S
--- a/arch/powerpc/kernel/vdso32/vdso32.lds.S 2020-12-19
00:01:16.829846652 +0100
+++ b/arch/powerpc/kernel/vdso32/vdso32.lds.S 2020-12-19
00:00:38.209374686 +0100
@@ -118,7 +118,6 @@ VERSION
__kernel_get_syscall_map;
__kernel_gettimeofday;
__kernel_clock_gettime;
- __kernel_clock_gettime64;
__kernel_clock_getres;
__kernel_time;
__kernel_get_tbfreq;
diff -rupN a/arch/powerpc/kernel/vdso32/vgettimeofday.c
b/arch/powerpc/kernel/vdso32/vgettimeofday.c
--- a/arch/powerpc/kernel/vdso32/vgettimeofday.c 2020-12-19
00:01:16.829846652 +0100
+++ b/arch/powerpc/kernel/vdso32/vgettimeofday.c 2020-12-19
00:00:37.817369691 +0100
@@ -10,12 +10,6 @@ int __c_kernel_clock_gettime(clockid_t c
return __cvdso_clock_gettime32_data(vd, clock, ts);
}
-int __c_kernel_clock_gettime64(clockid_t clock, struct
__kernel_timespec *ts,
- const struct vdso_data *vd)
-{
- return __cvdso_clock_gettime_data(vd, clock, ts);
-}
-
int __c_kernel_gettimeofday(struct __kernel_old_timeval *tv, struct
timezone *tz,
const struct vdso_data *vd)
{
------
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox