* [RFC][PATCH bpf] tools: bpftool: Fix tags for bpf-to-bpf calls
From: Sandipan Das @ 2018-02-27 12:13 UTC (permalink / raw)
To: daniel, naveen.n.rao; +Cc: ast, mpe, jakub.kicinski, netdev, linuxppc-dev
In-Reply-To: <1519153431.im5wioxel1.naveen@linux.ibm.com>
"Naveen N. Rao" wrote:
> I'm wondering if we can instead encode the bpf prog id in
> imm32. That way, we should be able to indicate the BPF
> function being called into. Daniel, is that something we
> can consider?
Since each subprog does not get a separate id, we cannot fetch
the fd and therefore the tag of a subprog. Instead we can use
the tag of the complete program as shown below.
"Daniel Borkmann" wrote:
> I think one limitation that would still need to be addressed later
> with such approach would be regarding the xlated prog dump in bpftool,
> see 'BPF calls via JIT' in 7105e828c087 ("bpf: allow for correlation
> of maps and helpers in dump"). Any ideas for this (potentially if we
> could use off + imm for calls, we'd get to 48 bits, but that seems
> still not be enough as you say)?
As an alternative, this is what I am thinking of:
Currently, for bpf-to-bpf calls, if bpf_jit_kallsyms is enabled,
bpftool looks up the name of the corresponding symbol for the
JIT-ed subprogram and shows it in the xlated dump alongside the
actual call instruction. However, the lookup is based on the
target address which is calculated using the imm field of the
instruction. So, once again, if imm is truncated, we will end
up with the wrong address. Also, the subprog aux data (which
has been proposed as a mitigation for this) is not accessible
from this tool.
We can still access the tag for the complete bpf program and use
this with the correct offset in an objdump-like notation as an
alterative for the name of the subprog that is the target of a
bpf-to-bpf call instruction.
Currently, an xlated dump looks like this:
0: (85) call pc+2#bpf_prog_5f76847930402518_F
1: (b7) r0 = 1
2: (95) exit
3: (b7) r0 = 2
4: (95) exit
With this patch, it will look like this:
0: (85) call pc+2#bpf_prog_8f85936f29a7790a+3
1: (b7) r0 = 1
2: (95) exit
3: (b7) r0 = 2
4: (95) exit
where 8f85936f29a7790a is the tag of the bpf program and 3 is
the offset to the start of the subprog from the start of the
program.
Signed-off-by: Sandipan Das <sandipan@linux.vnet.ibm.com>
---
tools/bpf/bpftool/prog.c | 23 ++++++++++++++---------
1 file changed, 14 insertions(+), 9 deletions(-)
diff --git a/tools/bpf/bpftool/prog.c b/tools/bpf/bpftool/prog.c
index e8e2baaf93c2..93746d5d1e3c 100644
--- a/tools/bpf/bpftool/prog.c
+++ b/tools/bpf/bpftool/prog.c
@@ -415,9 +415,11 @@ struct kernel_sym {
};
struct dump_data {
+ unsigned char prog_tag[BPF_TAG_SIZE];
unsigned long address_call_base;
struct kernel_sym *sym_mapping;
__u32 sym_count;
+ unsigned int curr_line;
char scratch_buff[SYM_MAX_NAME];
};
@@ -499,16 +501,16 @@ static void print_insn(struct bpf_verifier_env *env, const char *fmt, ...)
}
static const char *print_call_pcrel(struct dump_data *dd,
- struct kernel_sym *sym,
- unsigned long address,
const struct bpf_insn *insn)
{
- if (sym)
- snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
- "%+d#%s", insn->off, sym->name);
- else
- snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
- "%+d#0x%lx", insn->off, address);
+ snprintf(dd->scratch_buff, sizeof(dd->scratch_buff),
+ "+%d#bpf_prog_%02x%02x%02x%02x%02x%02x%02x%02x+%d",
+ insn->off,
+ dd->prog_tag[0], dd->prog_tag[1],
+ dd->prog_tag[2], dd->prog_tag[3],
+ dd->prog_tag[4], dd->prog_tag[5],
+ dd->prog_tag[6], dd->prog_tag[7],
+ dd->curr_line + insn->off + 1);
return dd->scratch_buff;
}
@@ -534,7 +536,7 @@ static const char *print_call(void *private_data,
sym = kernel_syms_search(dd, address);
if (insn->src_reg == BPF_PSEUDO_CALL)
- return print_call_pcrel(dd, sym, address, insn);
+ return print_call_pcrel(dd, insn);
else
return print_call_helper(dd, sym, address);
}
@@ -576,6 +578,7 @@ static void dump_xlated_plain(struct dump_data *dd, void *buf,
double_insn = insn[i].code == (BPF_LD | BPF_IMM | BPF_DW);
printf("% 4d: ", i);
+ dd->curr_line = i;
print_bpf_insn(&cbs, NULL, insn + i, true);
if (opcodes) {
@@ -628,6 +631,7 @@ static void dump_xlated_json(struct dump_data *dd, void *buf,
jsonw_start_object(json_wtr);
jsonw_name(json_wtr, "disasm");
+ dd->curr_line = i;
print_bpf_insn(&cbs, NULL, insn + i, true);
if (opcodes) {
@@ -788,6 +792,7 @@ static int do_dump(int argc, char **argv)
disasm_print_insn(buf, *member_len, opcodes, name);
} else {
+ memcpy(dd.prog_tag, info.tag, sizeof(info.tag));
kernel_syms_load(&dd);
if (json_output)
dump_xlated_json(&dd, buf, *member_len, opcodes);
--
2.14.3
^ permalink raw reply related
* [PATCH] powerpc/8xx: fix cpm_cascade() dual end of interrupt
From: Christophe Leroy @ 2018-02-27 11:25 UTC (permalink / raw)
To: Benjamin Herrenschmidt, Paul Mackerras, Michael Ellerman,
Scott Wood, Vitaly Bordug
Cc: linux-kernel, linuxppc-dev
cpm_cascade() doesn't have to call eoi() as it is already called
by handle_fasteoi_irq()
And cpm_get_irq() will always return an unsigned int so the test
is useless
Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
---
arch/powerpc/platforms/8xx/m8xx_setup.c | 8 +-------
1 file changed, 1 insertion(+), 7 deletions(-)
diff --git a/arch/powerpc/platforms/8xx/m8xx_setup.c b/arch/powerpc/platforms/8xx/m8xx_setup.c
index e1274db53d48..2188d691a40f 100644
--- a/arch/powerpc/platforms/8xx/m8xx_setup.c
+++ b/arch/powerpc/platforms/8xx/m8xx_setup.c
@@ -217,13 +217,7 @@ void __noreturn mpc8xx_restart(char *cmd)
static void cpm_cascade(struct irq_desc *desc)
{
- struct irq_chip *chip = irq_desc_get_chip(desc);
- int cascade_irq = cpm_get_irq();
-
- if (cascade_irq >= 0)
- generic_handle_irq(cascade_irq);
-
- chip->irq_eoi(&desc->irq_data);
+ generic_handle_irq(cpm_get_irq());
}
/* Initialize the internal interrupt controllers. The number of
--
2.13.3
^ permalink raw reply related
* Re: Linux 4.16: Reported regressions as of Monday, 2018-02-26 (Was: Linux 4.16-rc3)
From: Rafael J. Wysocki @ 2018-02-27 11:21 UTC (permalink / raw)
To: Thorsten Leemhuis
Cc: Linus Torvalds, Linux Kernel Mailing List, linuxppc-dev,
Jonathan Corbet, x86, William Grant, Woody Suwalski
In-Reply-To: <2cf45d87-066c-7368-3fbd-20675f2d74ae@leemhuis.info>
On Monday, February 26, 2018 11:25:09 AM CET Thorsten Leemhuis wrote:
> On 26.02.2018 04:05, Linus Torvalds wrote:
> > We're on the normal schedule for 4.16 and everything still looks very regular.
>
> Hi! Find below my second regression report for Linux 4.16. It lists 8
> regressions I'm currently aware of.
>
> To anyone reading this: Are you aware of any other regressions that got
> introduced this development cycle? Then please let me know by mail (a
> simple bounce or forward to the email address is enough!).
>
> For details see http://bit.ly/lnxregtrackid And please tell me if there
> is anything in the report that shouldn't be there.
Please add https://bugzilla.kernel.org/show_bug.cgi?id=198763
It has a bisect result and seems to be readily reproducible.
No response from the author of the problematic commit so far.
Thanks,
Rafael
^ permalink raw reply
* Re: [RFC REBASED 5/5] powerpc/mm/slice: use the dynamic high slice size to limit bitmap operations
From: Nicholas Piggin @ 2018-02-27 9:11 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: Christophe Leroy, linux-kernel, linuxppc-dev
In-Reply-To: <87bmga7qng.fsf@linux.vnet.ibm.com>
On Tue, 27 Feb 2018 14:31:07 +0530
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:
> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>
> > The number of high slices a process might use now depends on its
> > address space size, and what allocation address it has requested.
> >
> > This patch uses that limit throughout call chains where possible,
> > rather than use the fixed SLICE_NUM_HIGH for bitmap operations.
> > This saves some cost for processes that don't use very large address
> > spaces.
>
> I haven't really looked at the final code. One of the issue we had was
> with the below scenario.
>
> mmap(addr, len) where addr < 128TB and addr+len > 128TB We want to make
> sure we build the mask such that we don't find the addr available.
We should run it through the mmap regression tests. I *think* we moved
all of that logic from the slice code to get_ummapped_area before going
in to slices. I may have missed something though, it would be good to
have more eyes on it.
Thanks,
Nick
^ permalink raw reply
* Re: [RFC REBASED 4/5] powerpc/mm/slice: Use const pointers to cached slice masks where possible
From: Nicholas Piggin @ 2018-02-27 9:08 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: Christophe Leroy, linux-kernel, linuxppc-dev
In-Reply-To: <87h8q27uvi.fsf@linux.vnet.ibm.com>
On Tue, 27 Feb 2018 12:59:53 +0530
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:
> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>
> > The slice_mask cache was a basic conversion which copied the slice
> > mask into caller's structures, because that's how the original code
> > worked. In most cases the pointer can be used directly instead, saving
> > a copy and an on-stack structure.
> >
> > This also converts the slice_mask bit operation helpers to be the usual
> > 3-operand kind, which is clearer to work with. And we remove some
> > unnecessary intermediate bitmaps, reducing stack and copy overhead
> > further.
>
> Can we move the reduce unncessary intermediate bitmaps as another patch?
This was rightly split out -- it moved to Christophe's patch he already
made in his series. The changelog can just be adjusted.
Thanks,
Nick
^ permalink raw reply
* Re: [RFC REBASED 3/5] powerpc/mm/slice: implement slice_check_range_fits
From: Nicholas Piggin @ 2018-02-27 9:04 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: Christophe Leroy, linux-kernel, linuxppc-dev
In-Reply-To: <87k1uy7vbr.fsf@linux.vnet.ibm.com>
On Tue, 27 Feb 2018 12:50:08 +0530
"Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com> wrote:
> Christophe Leroy <christophe.leroy@c-s.fr> writes:
> + if ((start + len) > SLICE_LOW_TOP) {
> > + unsigned long start_index = GET_HIGH_SLICE_INDEX(start);
> > + unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT));
> > + unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index;
> > + unsigned long i;
> >
> > - slice_bitmap_and(result, mask->high_slices, available->high_slices,
> > - slice_count);
> > + for (i = start_index; i < start_index + count; i++) {
> > + if (!test_bit(i, available->high_slices))
> > + return false;
> > + }
> > + }
>
> why not bitmap_equal here instead of test_bit in loop?
Because we only have the available bitmap now. If we see large ranges
here we could use some bitmap operation like find_next_zero_bit perhaps.
Thanks,
Nick
^ permalink raw reply
* Re: [RFC REBASED 5/5] powerpc/mm/slice: use the dynamic high slice size to limit bitmap operations
From: Aneesh Kumar K.V @ 2018-02-27 9:01 UTC (permalink / raw)
To: Christophe Leroy, Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <5badd882663833576c10b8aafe235fe1e443f119.1518382747.git.christophe.leroy@c-s.fr>
Christophe Leroy <christophe.leroy@c-s.fr> writes:
> The number of high slices a process might use now depends on its
> address space size, and what allocation address it has requested.
>
> This patch uses that limit throughout call chains where possible,
> rather than use the fixed SLICE_NUM_HIGH for bitmap operations.
> This saves some cost for processes that don't use very large address
> spaces.
I haven't really looked at the final code. One of the issue we had was
with the below scenario.
mmap(addr, len) where addr < 128TB and addr+len > 128TB We want to make
sure we build the mask such that we don't find the addr available.
-aneesh
^ permalink raw reply
* Re: [PATCH 01/21] powerpc: Remove warning on array size when empty
From: Mathieu Malaterre @ 2018-02-27 7:44 UTC (permalink / raw)
To: Christophe LEROY
Cc: Andy Shevchenko, Linux Kernel Mailing List, Paul Mackerras,
Jiri Slaby, open list:LINUX FOR POWERPC PA SEMI PWRFICIENT
In-Reply-To: <603d5335-6220-73f2-d902-b92bc74bc79e@c-s.fr>
On Tue, Feb 27, 2018 at 8:33 AM, Christophe LEROY
<christophe.leroy@c-s.fr> wrote:
>
>
> Le 27/02/2018 =C3=A0 08:25, Mathieu Malaterre a =C3=A9crit :
>>
>> On Mon, Feb 26, 2018 at 3:45 PM, Andy Shevchenko
>> <andy.shevchenko@gmail.com> wrote:
>>>
>>> On Mon, Feb 26, 2018 at 4:44 PM, Andy Shevchenko
>>> <andy.shevchenko@gmail.com> wrote:
>>>>
>>>> On Sun, Feb 25, 2018 at 7:22 PM, Mathieu Malaterre <malat@debian.org>
>>>> wrote:
>>>
>>>
>>>>> static void __init check_cpu_feature_properties(unsigned long node)
>>>>> {
>>>>> - unsigned long i;
>>>>> struct feature_property *fp =3D feature_properties;
>>>>> const __be32 *prop;
>>>>>
>>>>
>>>> Much simpler is just add
>>>>
>>>> if (ARRAY_SIZE() =3D=3D 0)
>>>> return;
>>>>
>>>>> - for (i =3D 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) =
{
>>>>> + for (; fp !=3D feature_properties +
>>>>> ARRAY_SIZE(feature_properties); ++fp) {
>>>
>>>
>>> ...or convert to while(), which will be more readable.
>>
>>
>> So you'd prefer something like:
>>
>> while (fp < feature_properties + ARRAY_SIZE(feature_properties)) {
>> ...
>> ++fp;
>> }
>>
>> right ?
>>
>
>
> Why not do as suggested by Segher, ie just replace < by !=3D in the origi=
nal
> form ?
I can do that.
> Or add in front:
> if (!ARRAY_SIZE(feature_properties))
> return;
(not tested) I believe the compiler still go over the for() loop and
will complain about the original unsigned comparison.
> Christophe
^ permalink raw reply
* Re: [PATCH 01/21] powerpc: Remove warning on array size when empty
From: Christophe LEROY @ 2018-02-27 7:33 UTC (permalink / raw)
To: Mathieu Malaterre, Andy Shevchenko
Cc: Linux Kernel Mailing List, Paul Mackerras, Jiri Slaby,
open list:LINUX FOR POWERPC PA SEMI PWRFICIENT
In-Reply-To: <CA+7wUszK++8Tr9j1=4jQtRSu-36MH=dqgimq-ST9D9hvacrJSQ@mail.gmail.com>
Le 27/02/2018 à 08:25, Mathieu Malaterre a écrit :
> On Mon, Feb 26, 2018 at 3:45 PM, Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
>> On Mon, Feb 26, 2018 at 4:44 PM, Andy Shevchenko
>> <andy.shevchenko@gmail.com> wrote:
>>> On Sun, Feb 25, 2018 at 7:22 PM, Mathieu Malaterre <malat@debian.org> wrote:
>>
>>>> static void __init check_cpu_feature_properties(unsigned long node)
>>>> {
>>>> - unsigned long i;
>>>> struct feature_property *fp = feature_properties;
>>>> const __be32 *prop;
>>>>
>>>
>>> Much simpler is just add
>>>
>>> if (ARRAY_SIZE() == 0)
>>> return;
>>>
>>>> - for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) {
>>>> + for (; fp != feature_properties + ARRAY_SIZE(feature_properties); ++fp) {
>>
>> ...or convert to while(), which will be more readable.
>
> So you'd prefer something like:
>
> while (fp < feature_properties + ARRAY_SIZE(feature_properties)) {
> ...
> ++fp;
> }
>
> right ?
>
Why not do as suggested by Segher, ie just replace < by != in the
original form ?
Or add in front:
if (!ARRAY_SIZE(feature_properties))
return;
Christophe
^ permalink raw reply
* Re: [RFC REBASED 4/5] powerpc/mm/slice: Use const pointers to cached slice masks where possible
From: Aneesh Kumar K.V @ 2018-02-27 7:29 UTC (permalink / raw)
To: Christophe Leroy, Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <6a8c9183257dfcfeb1d8ed1ecc778ec3da19dcd4.1518382747.git.christophe.leroy@c-s.fr>
Christophe Leroy <christophe.leroy@c-s.fr> writes:
> The slice_mask cache was a basic conversion which copied the slice
> mask into caller's structures, because that's how the original code
> worked. In most cases the pointer can be used directly instead, saving
> a copy and an on-stack structure.
>
> This also converts the slice_mask bit operation helpers to be the usual
> 3-operand kind, which is clearer to work with. And we remove some
> unnecessary intermediate bitmaps, reducing stack and copy overhead
> further.
Can we move the reduce unncessary intermediate bitmaps as another patch?
>
> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
> ---
> arch/powerpc/include/asm/book3s/64/slice.h | 7 +++
> arch/powerpc/include/asm/nohash/32/slice.h | 6 +++
> arch/powerpc/mm/slice.c | 77 ++++++++++++++++++------------
> 3 files changed, 59 insertions(+), 31 deletions(-)
>
> diff --git a/arch/powerpc/include/asm/book3s/64/slice.h b/arch/powerpc/include/asm/book3s/64/slice.h
> index f9a2c8bd7a77..be1ce8e91ad1 100644
> --- a/arch/powerpc/include/asm/book3s/64/slice.h
> +++ b/arch/powerpc/include/asm/book3s/64/slice.h
> @@ -63,6 +63,13 @@ static inline void slice_bitmap_set(unsigned long *map, unsigned int start,
> {
> bitmap_set(map, start, nbits);
> }
> +
> +static inline void slice_bitmap_copy(unsigned long *dst,
> + const unsigned long *src,
> + unsigned int nbits)
> +{
> + bitmap_copy(dst, src, nbits);
> +}
> #endif /* __ASSEMBLY__ */
>
> #else /* CONFIG_PPC_MM_SLICES */
> diff --git a/arch/powerpc/include/asm/nohash/32/slice.h b/arch/powerpc/include/asm/nohash/32/slice.h
> index bcb4924f7d22..38f041e01a0a 100644
> --- a/arch/powerpc/include/asm/nohash/32/slice.h
> +++ b/arch/powerpc/include/asm/nohash/32/slice.h
> @@ -58,6 +58,12 @@ static inline void slice_bitmap_set(unsigned long *map, unsigned int start,
> unsigned int nbits)
> {
> }
> +
> +static inline void slice_bitmap_copy(unsigned long *dst,
> + const unsigned long *src,
> + unsigned int nbits)
> +{
> +}
> #endif /* __ASSEMBLY__ */
>
> #endif /* CONFIG_PPC_MM_SLICES */
> diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
> index 311168ca3939..b8b691369c29 100644
> --- a/arch/powerpc/mm/slice.c
> +++ b/arch/powerpc/mm/slice.c
> @@ -468,21 +468,30 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
> return slice_find_area_bottomup(mm, len, mask, psize, high_limit);
> }
>
> -static inline void slice_or_mask(struct slice_mask *dst,
> +static inline void slice_copy_mask(struct slice_mask *dst,
> const struct slice_mask *src)
> {
> - dst->low_slices |= src->low_slices;
> - slice_bitmap_or(dst->high_slices, dst->high_slices, src->high_slices,
> + dst->low_slices = src->low_slices;
> + slice_bitmap_copy(dst->high_slices, src->high_slices, SLICE_NUM_HIGH);
> +}
> +
> +static inline void slice_or_mask(struct slice_mask *dst,
> + const struct slice_mask *src1,
> + const struct slice_mask *src2)
> +{
> + dst->low_slices = src1->low_slices | src2->low_slices;
> + slice_bitmap_or(dst->high_slices, src1->high_slices, src2->high_slices,
> SLICE_NUM_HIGH);
> }
>
> static inline void slice_andnot_mask(struct slice_mask *dst,
> - const struct slice_mask *src)
> + const struct slice_mask *src1,
> + const struct slice_mask *src2)
> {
> - dst->low_slices &= ~src->low_slices;
> + dst->low_slices = src1->low_slices & ~src2->low_slices;
>
> - slice_bitmap_andnot(dst->high_slices, dst->high_slices,
> - src->high_slices, SLICE_NUM_HIGH);
> + slice_bitmap_andnot(dst->high_slices, src1->high_slices,
> + src2->high_slices, SLICE_NUM_HIGH);
> }
>
> #ifdef CONFIG_PPC_64K_PAGES
> @@ -495,10 +504,10 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
> unsigned long flags, unsigned int psize,
> int topdown)
> {
> - struct slice_mask mask;
> struct slice_mask good_mask;
> struct slice_mask potential_mask;
> - struct slice_mask compat_mask;
> + const struct slice_mask *maskp;
> + const struct slice_mask *compat_maskp = NULL;
> int fixed = (flags & MAP_FIXED);
> int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
> unsigned long page_size = 1UL << pshift;
> @@ -537,9 +546,6 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
> potential_mask.low_slices = 0;
> slice_bitmap_zero(potential_mask.high_slices, SLICE_NUM_HIGH);
>
> - compat_mask.low_slices = 0;
> - slice_bitmap_zero(compat_mask.high_slices, SLICE_NUM_HIGH);
> -
> /* Sanity checks */
> BUG_ON(mm->task_size == 0);
> BUG_ON(mm->context.slb_addr_limit == 0);
> @@ -562,7 +568,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
> /* First make up a "good" mask of slices that have the right size
> * already
> */
> - good_mask = *slice_mask_for_size(mm, psize);
> + maskp = slice_mask_for_size(mm, psize);
> slice_print_mask(" good_mask", &good_mask);
>
> /*
> @@ -587,11 +593,16 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
> #ifdef CONFIG_PPC_64K_PAGES
> /* If we support combo pages, we can allow 64k pages in 4k slices */
> if (psize == MMU_PAGE_64K) {
> - compat_mask = *slice_mask_for_size(mm, MMU_PAGE_4K);
> + compat_maskp = slice_mask_for_size(mm, MMU_PAGE_4K);
> if (fixed)
> - slice_or_mask(&good_mask, &compat_mask);
> - }
> + slice_or_mask(&good_mask, maskp, compat_maskp);
> + else
> + slice_copy_mask(&good_mask, maskp);
> + } else
> #endif
> + {
> + slice_copy_mask(&good_mask, maskp);
> + }
>
> /* First check hint if it's valid or if we have MAP_FIXED */
> if (addr || fixed) {
> @@ -621,7 +632,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
> * empty and thus can be converted
> */
> slice_mask_for_free(mm, &potential_mask, high_limit);
> - slice_or_mask(&potential_mask, &good_mask);
> + slice_or_mask(&potential_mask, &potential_mask, &good_mask);
> slice_print_mask(" potential", &potential_mask);
>
> if (addr || fixed) {
> @@ -658,7 +669,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
> #ifdef CONFIG_PPC_64K_PAGES
> if (addr == -ENOMEM && psize == MMU_PAGE_64K) {
> /* retry the search with 4k-page slices included */
> - slice_or_mask(&potential_mask, &compat_mask);
> + slice_or_mask(&potential_mask, &potential_mask, compat_maskp);
> addr = slice_find_area(mm, len, &potential_mask,
> psize, topdown, high_limit);
> }
> @@ -667,16 +678,17 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
> if (addr == -ENOMEM)
> return -ENOMEM;
>
> - slice_range_to_mask(addr, len, &mask);
> + slice_range_to_mask(addr, len, &potential_mask);
Can we avoid reusing variables like that. I had to look at the change
below to ensure that this is intended change. The print below is wrong
then. In my patch series I did try to remove potential_mask and compat
mask and used tmp_mask in its place. IMHO that resulted in much simpiler
code. I do recompute tmp_mask for 4K size because of lack of variable.
But then i guess with your change to cache mask for different page size,
it should not have an impact?
> slice_dbg(" found potential area at 0x%lx\n", addr);
> - slice_print_mask(" mask", &mask);
> + slice_print_mask(" mask", maskp);
>
> convert:
> - slice_andnot_mask(&mask, &good_mask);
> - slice_andnot_mask(&mask, &compat_mask);
> - if (mask.low_slices ||
> - !slice_bitmap_empty(mask.high_slices, SLICE_NUM_HIGH)) {
> - slice_convert(mm, &mask, psize);
> + slice_andnot_mask(&potential_mask, &potential_mask, &good_mask);
> + if (compat_maskp && !fixed)
> + slice_andnot_mask(&potential_mask, &potential_mask, compat_maskp);
> + if (potential_mask.low_slices ||
> + !slice_bitmap_empty(potential_mask.high_slices, SLICE_NUM_HIGH)) {
> + slice_convert(mm, &potential_mask, psize);
> if (psize > MMU_PAGE_BASE)
> on_each_cpu(slice_flush_segments, mm, 1);
> }
> @@ -834,19 +846,22 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
> int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
> unsigned long len)
> {
> - struct slice_mask available;
> + const struct slice_mask *maskp;
> unsigned int psize = mm->context.user_psize;
>
> if (radix_enabled())
> return 0;
>
> - available = *slice_mask_for_size(mm, psize);
> + maskp = slice_mask_for_size(mm, psize);
> #ifdef CONFIG_PPC_64K_PAGES
> /* We need to account for 4k slices too */
> if (psize == MMU_PAGE_64K) {
> - struct slice_mask compat_mask;
> - compat_mask = *slice_mask_for_size(mm, MMU_PAGE_4K);
> - slice_or_mask(&available, &compat_mask);
> + const struct slice_mask *compat_maskp;
> + struct slice_mask available;
> +
> + compat_maskp = slice_mask_for_size(mm, MMU_PAGE_4K);
> + slice_or_mask(&available, maskp, compat_maskp);
> + return !slice_check_range_fits(mm, &available, addr, len);
> }
> #endif
>
> @@ -856,6 +871,6 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
> slice_print_mask(" mask", &mask);
> slice_print_mask(" available", &available);
> #endif
> - return !slice_check_range_fits(mm, &available, addr, len);
> + return !slice_check_range_fits(mm, maskp, addr, len);
> }
> #endif
> --
> 2.13.3
^ permalink raw reply
* Re: [PATCH 01/21] powerpc: Remove warning on array size when empty
From: Mathieu Malaterre @ 2018-02-27 7:25 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Michael Ellerman, Benjamin Herrenschmidt, Paul Mackerras,
Jiri Slaby, open list:LINUX FOR POWERPC PA SEMI PWRFICIENT,
Linux Kernel Mailing List
In-Reply-To: <CAHp75Ve_zxp4_N_YzzvJ=H8Qs65G5j7bgGBv_TvsZ6Ye2nuECA@mail.gmail.com>
On Mon, Feb 26, 2018 at 3:45 PM, Andy Shevchenko
<andy.shevchenko@gmail.com> wrote:
> On Mon, Feb 26, 2018 at 4:44 PM, Andy Shevchenko
> <andy.shevchenko@gmail.com> wrote:
>> On Sun, Feb 25, 2018 at 7:22 PM, Mathieu Malaterre <malat@debian.org> wrote:
>
>>> static void __init check_cpu_feature_properties(unsigned long node)
>>> {
>>> - unsigned long i;
>>> struct feature_property *fp = feature_properties;
>>> const __be32 *prop;
>>>
>>
>> Much simpler is just add
>>
>> if (ARRAY_SIZE() == 0)
>> return;
>>
>>> - for (i = 0; i < ARRAY_SIZE(feature_properties); ++i, ++fp) {
>>> + for (; fp != feature_properties + ARRAY_SIZE(feature_properties); ++fp) {
>
> ...or convert to while(), which will be more readable.
So you'd prefer something like:
while (fp < feature_properties + ARRAY_SIZE(feature_properties)) {
...
++fp;
}
right ?
^ permalink raw reply
* Re: [RFC REBASED 3/5] powerpc/mm/slice: implement slice_check_range_fits
From: Aneesh Kumar K.V @ 2018-02-27 7:20 UTC (permalink / raw)
To: Christophe Leroy, Nicholas Piggin; +Cc: linux-kernel, linuxppc-dev
In-Reply-To: <caa9d52e0a8ef15719bafe8002a4ad2dc359c634.1518382747.git.christophe.leroy@c-s.fr>
Christophe Leroy <christophe.leroy@c-s.fr> writes:
+ if ((start + len) > SLICE_LOW_TOP) {
> + unsigned long start_index = GET_HIGH_SLICE_INDEX(start);
> + unsigned long align_end = ALIGN(end, (1UL << SLICE_HIGH_SHIFT));
> + unsigned long count = GET_HIGH_SLICE_INDEX(align_end) - start_index;
> + unsigned long i;
>
> - slice_bitmap_and(result, mask->high_slices, available->high_slices,
> - slice_count);
> + for (i = start_index; i < start_index + count; i++) {
> + if (!test_bit(i, available->high_slices))
> + return false;
> + }
> + }
why not bitmap_equal here instead of test_bit in loop?
>
> - return (mask->low_slices & available->low_slices) == mask->low_slices &&
> - slice_bitmap_equal(result, mask->high_slices, slice_count);
> + return true;
> }
-aneesh
^ permalink raw reply
* Re: [RFC REBASED 1/5] powerpc/mm/slice: pass pointers to struct slice_mask where possible
From: Christophe LEROY @ 2018-02-27 7:04 UTC (permalink / raw)
To: Aneesh Kumar K.V; +Cc: linuxppc-dev@lists.ozlabs.org, Nicholas Piggin
In-Reply-To: <87muzu7w58.fsf@linux.vnet.ibm.com>
Le 27/02/2018 à 08:02, Aneesh Kumar K.V a écrit :
>
> Hi,
>
> Do you have an updated series for this with your latest PPC32 slice
> post?
No, but I can make one if it is on any interest.
Christophe
>
> Christophe Leroy <christophe.leroy@c-s.fr> writes:
>
>> Pass around const pointers to struct slice_mask where possible, rather
>> than copies of slice_mask, to reduce stack and call overhead.
>>
>> checkstack.pl gives, before:
>> 0x00000de4 slice_get_unmapped_area [slice.o]: 656
>> 0x00001b4c is_hugepage_only_range [slice.o]: 512
>> 0x0000075c slice_find_area_topdown [slice.o]: 416
>> 0x000004c8 slice_find_area_bottomup.isra.1 [slice.o]: 272
>> 0x00001aa0 slice_set_range_psize [slice.o]: 240
>> 0x00000a64 slice_find_area [slice.o]: 176
>> 0x00000174 slice_check_fit [slice.o]: 112
>>
>> after:
>> 0x00000bd4 slice_get_unmapped_area [slice.o]: 496
>> 0x000017cc is_hugepage_only_range [slice.o]: 352
>> 0x00000758 slice_find_area [slice.o]: 144
>> 0x00001750 slice_set_range_psize [slice.o]: 144
>> 0x00000180 slice_check_fit [slice.o]: 128
>> 0x000005b0 slice_find_area_bottomup.isra.2 [slice.o]: 128
>>
>> Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
>> Signed-off-by: Christophe Leroy <christophe.leroy@c-s.fr>
>> ---
>> rebased on top of "[v4,3/5] powerpc/mm/slice: Fix hugepage allocation at hint address on 8xx" (https://patchwork.ozlabs.org/patch/871675/)
>>
>> arch/powerpc/mm/slice.c | 81 +++++++++++++++++++++++++++----------------------
>> 1 file changed, 44 insertions(+), 37 deletions(-)
>>
>> diff --git a/arch/powerpc/mm/slice.c b/arch/powerpc/mm/slice.c
>> index 549704dfa777..db1278ac21c2 100644
>> --- a/arch/powerpc/mm/slice.c
>> +++ b/arch/powerpc/mm/slice.c
>> @@ -50,19 +50,21 @@ struct slice_mask {
>> #ifdef DEBUG
>> int _slice_debug = 1;
>>
>> -static void slice_print_mask(const char *label, struct slice_mask mask)
>> +static void slice_print_mask(const char *label, const struct slice_mask *mask)
>> {
>> if (!_slice_debug)
>> return;
>> - pr_devel("%s low_slice: %*pbl\n", label, (int)SLICE_NUM_LOW, &mask.low_slices);
>> - pr_devel("%s high_slice: %*pbl\n", label, (int)SLICE_NUM_HIGH, mask.high_slices);
>> + pr_devel("%s low_slice: %*pbl\n", label,
>> + (int)SLICE_NUM_LOW, &mask->low_slices);
>> + pr_devel("%s high_slice: %*pbl\n", label,
>> + (int)SLICE_NUM_HIGH, mask->high_slices);
>> }
>>
>> #define slice_dbg(fmt...) do { if (_slice_debug) pr_devel(fmt); } while (0)
>>
>> #else
>>
>> -static void slice_print_mask(const char *label, struct slice_mask mask) {}
>> +static void slice_print_mask(const char *label, const struct slice_mask *mask) {}
>> #define slice_dbg(fmt...)
>>
>> #endif
>> @@ -145,7 +147,8 @@ static void slice_mask_for_free(struct mm_struct *mm, struct slice_mask *ret,
>> __set_bit(i, ret->high_slices);
>> }
>>
>> -static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_mask *ret,
>> +static void slice_mask_for_size(struct mm_struct *mm, int psize,
>> + struct slice_mask *ret,
>> unsigned long high_limit)
>> {
>> unsigned char *hpsizes;
>> @@ -174,7 +177,8 @@ static void slice_mask_for_size(struct mm_struct *mm, int psize, struct slice_ma
>> }
>>
>> static int slice_check_fit(struct mm_struct *mm,
>> - struct slice_mask mask, struct slice_mask available)
>> + const struct slice_mask *mask,
>> + const struct slice_mask *available)
>> {
>> DECLARE_BITMAP(result, SLICE_NUM_HIGH);
>> /*
>> @@ -183,11 +187,11 @@ static int slice_check_fit(struct mm_struct *mm,
>> */
>> unsigned long slice_count = GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit);
>>
>> - slice_bitmap_and(result, mask.high_slices, available.high_slices,
>> + slice_bitmap_and(result, mask->high_slices, available->high_slices,
>> slice_count);
>>
>> - return (mask.low_slices & available.low_slices) == mask.low_slices &&
>> - slice_bitmap_equal(result, mask.high_slices, slice_count);
>> + return (mask->low_slices & available->low_slices) == mask->low_slices &&
>> + slice_bitmap_equal(result, mask->high_slices, slice_count);
>> }
>>
>> static void slice_flush_segments(void *parm)
>> @@ -207,7 +211,8 @@ static void slice_flush_segments(void *parm)
>> #endif
>> }
>>
>> -static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psize)
>> +static void slice_convert(struct mm_struct *mm,
>> + const struct slice_mask *mask, int psize)
>> {
>> int index, mask_index;
>> /* Write the new slice psize bits */
>> @@ -225,7 +230,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
>>
>> lpsizes = mm->context.low_slices_psize;
>> for (i = 0; i < SLICE_NUM_LOW; i++)
>> - if (mask.low_slices & (1u << i))
>> + if (mask->low_slices & (1u << i))
>> lpsizes = (lpsizes & ~(0xful << (i * 4))) |
>> (((unsigned long)psize) << (i * 4));
>>
>> @@ -236,7 +241,7 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
>> for (i = 0; i < GET_HIGH_SLICE_INDEX(mm->context.slb_addr_limit); i++) {
>> mask_index = i & 0x1;
>> index = i >> 1;
>> - if (test_bit(i, mask.high_slices))
>> + if (test_bit(i, mask->high_slices))
>> hpsizes[index] = (hpsizes[index] &
>> ~(0xf << (mask_index * 4))) |
>> (((unsigned long)psize) << (mask_index * 4));
>> @@ -259,26 +264,25 @@ static void slice_convert(struct mm_struct *mm, struct slice_mask mask, int psiz
>> * 'available' slice_mark.
>> */
>> static bool slice_scan_available(unsigned long addr,
>> - struct slice_mask available,
>> - int end,
>> - unsigned long *boundary_addr)
>> + const struct slice_mask *available,
>> + int end, unsigned long *boundary_addr)
>> {
>> unsigned long slice;
>> if (addr < SLICE_LOW_TOP) {
>> slice = GET_LOW_SLICE_INDEX(addr);
>> *boundary_addr = (slice + end) << SLICE_LOW_SHIFT;
>> - return !!(available.low_slices & (1u << slice));
>> + return !!(available->low_slices & (1u << slice));
>> } else {
>> slice = GET_HIGH_SLICE_INDEX(addr);
>> *boundary_addr = (slice + end) ?
>> ((slice + end) << SLICE_HIGH_SHIFT) : SLICE_LOW_TOP;
>> - return !!test_bit(slice, available.high_slices);
>> + return !!test_bit(slice, available->high_slices);
>> }
>> }
>>
>> static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
>> unsigned long len,
>> - struct slice_mask available,
>> + const struct slice_mask *available,
>> int psize, unsigned long high_limit)
>> {
>> int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
>> @@ -324,7 +328,7 @@ static unsigned long slice_find_area_bottomup(struct mm_struct *mm,
>>
>> static unsigned long slice_find_area_topdown(struct mm_struct *mm,
>> unsigned long len,
>> - struct slice_mask available,
>> + const struct slice_mask *available,
>> int psize, unsigned long high_limit)
>> {
>> int pshift = max_t(int, mmu_psize_defs[psize].shift, PAGE_SHIFT);
>> @@ -382,7 +386,7 @@ static unsigned long slice_find_area_topdown(struct mm_struct *mm,
>>
>>
>> static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
>> - struct slice_mask mask, int psize,
>> + const struct slice_mask *mask, int psize,
>> int topdown, unsigned long high_limit)
>> {
>> if (topdown)
>> @@ -391,14 +395,16 @@ static unsigned long slice_find_area(struct mm_struct *mm, unsigned long len,
>> return slice_find_area_bottomup(mm, len, mask, psize, high_limit);
>> }
>>
>> -static inline void slice_or_mask(struct slice_mask *dst, struct slice_mask *src)
>> +static inline void slice_or_mask(struct slice_mask *dst,
>> + const struct slice_mask *src)
>> {
>> dst->low_slices |= src->low_slices;
>> slice_bitmap_or(dst->high_slices, dst->high_slices, src->high_slices,
>> SLICE_NUM_HIGH);
>> }
>>
>> -static inline void slice_andnot_mask(struct slice_mask *dst, struct slice_mask *src)
>> +static inline void slice_andnot_mask(struct slice_mask *dst,
>> + const struct slice_mask *src)
>> {
>> dst->low_slices &= ~src->low_slices;
>>
>> @@ -483,7 +489,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
>> * already
>> */
>> slice_mask_for_size(mm, psize, &good_mask, high_limit);
>> - slice_print_mask(" good_mask", good_mask);
>> + slice_print_mask(" good_mask", &good_mask);
>>
>> /*
>> * Here "good" means slices that are already the right page size,
>> @@ -517,12 +523,12 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
>> if (addr != 0 || fixed) {
>> /* Build a mask for the requested range */
>> slice_range_to_mask(addr, len, &mask);
>> - slice_print_mask(" mask", mask);
>> + slice_print_mask(" mask", &mask);
>>
>> /* Check if we fit in the good mask. If we do, we just return,
>> * nothing else to do
>> */
>> - if (slice_check_fit(mm, mask, good_mask)) {
>> + if (slice_check_fit(mm, &mask, &good_mask)) {
>> slice_dbg(" fits good !\n");
>> return addr;
>> }
>> @@ -530,7 +536,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
>> /* Now let's see if we can find something in the existing
>> * slices for that size
>> */
>> - newaddr = slice_find_area(mm, len, good_mask,
>> + newaddr = slice_find_area(mm, len, &good_mask,
>> psize, topdown, high_limit);
>> if (newaddr != -ENOMEM) {
>> /* Found within the good mask, we don't have to setup,
>> @@ -546,9 +552,10 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
>> */
>> slice_mask_for_free(mm, &potential_mask, high_limit);
>> slice_or_mask(&potential_mask, &good_mask);
>> - slice_print_mask(" potential", potential_mask);
>> + slice_print_mask(" potential", &potential_mask);
>>
>> - if ((addr != 0 || fixed) && slice_check_fit(mm, mask, potential_mask)) {
>> + if ((addr != 0 || fixed) &&
>> + slice_check_fit(mm, &mask, &potential_mask)) {
>> slice_dbg(" fits potential !\n");
>> goto convert;
>> }
>> @@ -563,7 +570,7 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
>> * anywhere in the good area.
>> */
>> if (addr) {
>> - addr = slice_find_area(mm, len, good_mask,
>> + addr = slice_find_area(mm, len, &good_mask,
>> psize, topdown, high_limit);
>> if (addr != -ENOMEM) {
>> slice_dbg(" found area at 0x%lx\n", addr);
>> @@ -574,14 +581,14 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
>> /* Now let's see if we can find something in the existing slices
>> * for that size plus free slices
>> */
>> - addr = slice_find_area(mm, len, potential_mask,
>> + addr = slice_find_area(mm, len, &potential_mask,
>> psize, topdown, high_limit);
>>
>> #ifdef CONFIG_PPC_64K_PAGES
>> if (addr == -ENOMEM && psize == MMU_PAGE_64K) {
>> /* retry the search with 4k-page slices included */
>> slice_or_mask(&potential_mask, &compat_mask);
>> - addr = slice_find_area(mm, len, potential_mask,
>> + addr = slice_find_area(mm, len, &potential_mask,
>> psize, topdown, high_limit);
>> }
>> #endif
>> @@ -591,14 +598,14 @@ unsigned long slice_get_unmapped_area(unsigned long addr, unsigned long len,
>>
>> slice_range_to_mask(addr, len, &mask);
>> slice_dbg(" found potential area at 0x%lx\n", addr);
>> - slice_print_mask(" mask", mask);
>> + slice_print_mask(" mask", &mask);
>>
>> convert:
>> slice_andnot_mask(&mask, &good_mask);
>> slice_andnot_mask(&mask, &compat_mask);
>> if (mask.low_slices ||
>> !slice_bitmap_empty(mask.high_slices, SLICE_NUM_HIGH)) {
>> - slice_convert(mm, mask, psize);
>> + slice_convert(mm, &mask, psize);
>> if (psize > MMU_PAGE_BASE)
>> on_each_cpu(slice_flush_segments, mm, 1);
>> }
>> @@ -727,7 +734,7 @@ void slice_set_range_psize(struct mm_struct *mm, unsigned long start,
>> VM_BUG_ON(radix_enabled());
>>
>> slice_range_to_mask(start, len, &mask);
>> - slice_convert(mm, mask, psize);
>> + slice_convert(mm, &mask, psize);
>> }
>>
>> #ifdef CONFIG_HUGETLB_PAGE
>> @@ -774,9 +781,9 @@ int is_hugepage_only_range(struct mm_struct *mm, unsigned long addr,
>> #if 0 /* too verbose */
>> slice_dbg("is_hugepage_only_range(mm=%p, addr=%lx, len=%lx)\n",
>> mm, addr, len);
>> - slice_print_mask(" mask", mask);
>> - slice_print_mask(" available", available);
>> + slice_print_mask(" mask", &mask);
>> + slice_print_mask(" available", &available);
>> #endif
>> - return !slice_check_fit(mm, mask, available);
>> + return !slice_check_fit(mm, &mask, &available);
>> }
>> #endif
>> --
>> 2.13.3
^ permalink raw reply
* Re: [PATCH V2 4/4] powerpc/mm/hash64: Increase the VA range
From: Aneesh Kumar K.V @ 2018-02-27 4:02 UTC (permalink / raw)
To: Murilo Opsfelder Araujo, benh, paulus, mpe; +Cc: linuxppc-dev
In-Reply-To: <5876ab5b-237f-6e05-62e9-59fb2fe4a8f1@linux.vnet.ibm.com>
Murilo Opsfelder Araujo <muriloo@linux.vnet.ibm.com> writes:
> On 02/26/2018 11:08 AM, Aneesh Kumar K.V wrote:
>> ---
>> arch/powerpc/include/asm/book3s/64/hash-64k.h | 2 +-
>> arch/powerpc/include/asm/processor.h | 9 ++++++++-
>> arch/powerpc/mm/init_64.c | 6 ------
>> arch/powerpc/mm/pgtable_64.c | 5 -----
>> 4 files changed, 9 insertions(+), 13 deletions(-)
>
> Hi, Aneesh.
>
> This patch is missing Signed-off-by: line. You're encouraged to run
> checkpatch.pl to inspect your patches.
>
> You may also want to add a brief paragraph in the commit message
> explaining the "why" of this change.
>
Will update.
-aneesh
^ permalink raw reply
* Re: [PATCH V2 2/4] powerpc/mm/slice: Reduce the stack usage in slice_get_unmapped_area
From: Aneesh Kumar K.V @ 2018-02-27 4:01 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: Benjamin Herrenschmidt, paulus, mpe, linuxppc-dev
In-Reply-To: <CANashXPZ=KZdixoqCoO7hTy4z7kJLqAst6C-77fg7OdAdfe8EA@mail.gmail.com>
Nicholas Piggin <nicholas.piggin@gmail.com> writes:
> I had a series which goes significantly further with stack reduction. What
> do you think about just going with that?
I am yet to review that. What I did here is minimum that is required to
get 4PB series compiled.
>
> I wonder if we should switch to dynamically allocating the slice stuff on
> ppc64
-aneesh
^ permalink raw reply
* Re: [PATCH V2] powerpc: Don't do runtime futex_cmpxchg test
From: Aneesh Kumar K.V @ 2018-02-27 4:00 UTC (permalink / raw)
To: Nicholas Piggin; +Cc: Benjamin Herrenschmidt, paulus, mpe, linuxppc-dev
In-Reply-To: <CANashXPc952+httE=Vhx=wGrkN3Ycva7j+a+WE6jXQaw38p=YQ@mail.gmail.com>
Nicholas Piggin <nicholas.piggin@gmail.com> writes:
> On 27 Feb. 2018 00:34, "Aneesh Kumar K.V" <aneesh.kumar@linux.vnet.ibm.com>
> wrote:
>
> futex_detect_cmpxchg() does a cmpxchg_futex_value_locked on a NULL user
> addr to
> runtime detect whether architecture implements atomic cmpxchg for futex.
> POWER
> do implement the feature and hence we can enable the config instead of
> depending
> on runtime detection.
>
> We could possible enable this on everything. For now limitted to book3s_64
>
>
> I think everything implements it? Might as well do it all at once.
>
> I wouldn't mind putting in an explicit null dereference test if we take
> this out.
If the config is not selected we do that with futex_detect_cmpxchg()
right? Or are you suggesting something else?
>
> Thanks,
> Nick
>
>
>
> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
> ---
> arch/powerpc/platforms/Kconfig.cputype | 1 +
> 1 file changed, 1 insertion(+)
>
> diff --git a/arch/powerpc/platforms/Kconfig.cputype
> b/arch/powerpc/platforms/Kconfig.cputype
> index a429d859f15d..31bc2bd5dfd1 100644
> --- a/arch/powerpc/platforms/Kconfig.cputype
> +++ b/arch/powerpc/platforms/Kconfig.cputype
> @@ -75,6 +75,7 @@ config PPC_BOOK3S_64
> select ARCH_SUPPORTS_NUMA_BALANCING
> select IRQ_WORK
> select HAVE_KERNEL_XZ
> + select HAVE_FUTEX_CMPXCHG if FUTEX
>
> config PPC_BOOK3E_64
> bool "Embedded processors"
> --
> 2.14.3
^ permalink raw reply
* Re: [PATCH 15/27] cpufreq: powerenv: Don't validate the frequency table twice
From: Viresh Kumar @ 2018-02-27 3:45 UTC (permalink / raw)
To: Michael Ellerman
Cc: Rafael Wysocki, Benjamin Herrenschmidt, Paul Mackerras, linux-pm,
Vincent Guittot, linuxppc-dev
In-Reply-To: <871sh89dbr.fsf@concordia.ellerman.id.au>
On 26-02-18, 22:53, Michael Ellerman wrote:
> Viresh Kumar <viresh.kumar@linaro.org> writes:
> > Subject: Re: [PATCH 15/27] cpufreq: powerenv: Don't validate the frequency table twice
> ^
> powernv
>
> > The cpufreq core is already validating the CPU frequency table after
> > calling the ->init() callback of the cpufreq drivers and the drivers
> > don't need to do the same anymore. Though they need to set the
> > policy->freq_table field directly from the ->init() callback now.
> >
> > Stop validating the frequency table from powerenv driver.
powernv :)
Will fix both of them.
--
viresh
^ permalink raw reply
* Re: [PATCH v2] powerpc/npu: Cleanup MMIO ATSD flushing
From: Alistair Popple @ 2018-02-27 0:47 UTC (permalink / raw)
To: linuxppc-dev; +Cc: Balbir Singh, Michael Ellerman, Aneesh Kumar KV
In-Reply-To: <CAKTCnzkO+NWKDwj8RE_jX_N0uu-vY5HRf4AdkJyjsLvL1Loqhg@mail.gmail.com>
> @aneesh can you please look at this? @mpe can we pick this up if there
> are no objections?
@mpe any objections to picking this up for this release? Or do you want to wait
for the next one? (there are likely more bugfixes coming for ATS support).
- Alistair
> Balbir Singh
>
^ permalink raw reply
* Re: [PATCH] xmon: Setup xmon debugger hooks when first break-point is set
From: Balbir Singh @ 2018-02-27 0:26 UTC (permalink / raw)
To: Vaibhav Jain, linuxppc-dev, Michael Ellerman
Cc: Benjamin Herrenschmidt, Paul Mackerras, Nicholas Piggin,
Douglas Miller, Frederic Barrat
In-Reply-To: <20180226113607.20321-1-vaibhav@linux.vnet.ibm.com>
On Mon, 2018-02-26 at 17:06 +0530, Vaibhav Jain wrote:
> Presently sysrq key for xmon('x') is registered during kernel init
> irrespective of the value of kernel param 'xmon'. Thus xmon is enabled
> even if 'xmon=off' is passed on the kernel command line. However this
> doesn't enable the kernel debugger hooks needed for instruction or data
> breakpoints. Thus when a break-point is hit with xmon=off a kernel oops
> of the form below is reported:
>
> Oops: Exception in kernel mode, sig: 5 [#1]
> < snip >
> Trace/breakpoint trap
>
> To fix this the patch checks and enables debugger hooks when an
> instruction or data break-point is set via xmon console. It also clears
> all breakpoints when xmon is disabled via debugfs.
>
> Signed-off-by: Vaibhav Jain <vaibhav@linux.vnet.ibm.com>
> ---
> arch/powerpc/xmon/xmon.c | 34 +++++++++++++++++++++++++++++++++-
> 1 file changed, 33 insertions(+), 1 deletion(-)
>
> diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
> index 82e1a3ee6e0f..3679f5417a7e 100644
> --- a/arch/powerpc/xmon/xmon.c
> +++ b/arch/powerpc/xmon/xmon.c
> @@ -1295,6 +1295,7 @@ bpt_cmds(void)
> switch (cmd) {
> #ifndef CONFIG_PPC_8xx
> static const char badaddr[] = "Only kernel addresses are permitted for breakpoints\n";
> + static const char warnxmon[] = "xmon: Enabling debugger hooks\n";
> int mode;
> case 'd': /* bd - hardware data breakpoint */
> mode = 7;
> @@ -1315,6 +1316,11 @@ bpt_cmds(void)
> dabr.address &= ~HW_BRK_TYPE_DABR;
> dabr.enabled = mode | BP_DABR;
> }
> + /* Enable xmon hooks if needed */
> + if (!xmon_on) {
> + printf(warnxmon);
> + xmon_on = 1;
> + }
Can we get this three liner into an inline function?
> break;
>
> case 'i': /* bi - hardware instr breakpoint */
> @@ -1335,6 +1341,12 @@ bpt_cmds(void)
> if (bp != NULL) {
> bp->enabled |= BP_CIABR;
> iabr = bp;
> +
> + /* Enable xmon hooks if needed */
> + if (!xmon_on) {
> + printf(warnxmon);
> + xmon_on = 1;
> + }
> }
> break;
> #endif
> @@ -1399,8 +1411,15 @@ bpt_cmds(void)
> if (!check_bp_loc(a))
> break;
> bp = new_breakpoint(a);
> - if (bp != NULL)
> + if (bp != NULL) {
> bp->enabled |= BP_TRAP;
> +
> + /* Enable xmon hooks if needed */
> + if (!xmon_on) {
> + printf(warnxmon);
> + xmon_on = 1;
> + }
> + }
> break;
> }
> }
> @@ -3651,9 +3670,22 @@ device_initcall(setup_xmon_sysrq);
> #ifdef CONFIG_DEBUG_FS
> static int xmon_dbgfs_set(void *data, u64 val)
> {
> + int i;
> +
> xmon_on = !!val;
> xmon_init(xmon_on);
>
> + /* make sure all breakpoints removed when disabling */
> + if (!xmon_on) {
> + for (i = 0; i < NBPTS; ++i)
> + bpts[i].enabled = 0;
> + /* if anything set inform user that breakpoints are cleared */
> + if (iabr || dabr.enabled)
> + pr_info("xmon: All breakpoints cleared\n");
> +
> + iabr = NULL;
> + dabr.enabled = 0;
Is this sufficient or do we need remove_bpts()
Balbir Singh
^ permalink raw reply
* PASEMI: PCI_SCAN_ALL_PCIE_DEVS
From: Christian Zigotzky @ 2018-02-26 23:11 UTC (permalink / raw)
To: linuxppc-dev@lists.ozlabs.org; +Cc: Olof Johansson
In-Reply-To: <DB3PR0402MB3849C1D81C867CF2D5A65D0EECEB0@DB3PR0402MB3849.eurprd04.prod.outlook.com>
Hi All,
Could you please add Olof's patch?
---
arch/powerpc/platforms/pasemi/pci.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/arch/powerpc/platforms/pasemi/pci.c
b/arch/powerpc/platforms/pasemi/pci.c
index 5ff6108..ea54ed2 100644
--- a/arch/powerpc/platforms/pasemi/pci.c
+++ b/arch/powerpc/platforms/pasemi/pci.c
@@ -224,6 +224,8 @@ void __init pas_pci_init(void)
return;
}
+ pci_set_flags(PCI_SCAN_ALL_PCIE_DEVS);
+
for (np = NULL; (np = of_get_next_child(root, np)) != NULL;)
if (np->name && !strcmp(np->name, "pxp") && !pas_add_bridge(np))
of_node_get(np);
---
Thanks,
Christian
^ permalink raw reply related
* [PATCH v2 38/38] cxlflash: Enable OCXL operations
From: Uma Krishnan @ 2018-02-26 22:25 UTC (permalink / raw)
To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
Manoj N. Kumar
Cc: linuxppc-dev, Andrew Donnellan, Frederic Barrat,
Christophe Lombard
In-Reply-To: <1519683513-16731-1-git-send-email-ukrishn@linux.vnet.ibm.com>
This commit enables the OCXL operations for the OCXL devices.
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
---
drivers/scsi/cxlflash/main.c | 9 +++++++--
drivers/scsi/cxlflash/main.h | 1 +
2 files changed, 8 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/cxlflash/main.c b/drivers/scsi/cxlflash/main.c
index 8c55fcd..42a95b7 100644
--- a/drivers/scsi/cxlflash/main.c
+++ b/drivers/scsi/cxlflash/main.c
@@ -3168,7 +3168,8 @@ static struct dev_dependent_vals dev_corsa_vals = { CXLFLASH_MAX_SECTORS,
static struct dev_dependent_vals dev_flash_gt_vals = { CXLFLASH_MAX_SECTORS,
CXLFLASH_NOTIFY_SHUTDOWN };
static struct dev_dependent_vals dev_briard_vals = { CXLFLASH_MAX_SECTORS,
- CXLFLASH_NOTIFY_SHUTDOWN };
+ (CXLFLASH_NOTIFY_SHUTDOWN |
+ CXLFLASH_OCXL_DEV) };
/*
* PCI device binding table
@@ -3679,9 +3680,13 @@ static int cxlflash_probe(struct pci_dev *pdev,
cfg->init_state = INIT_STATE_NONE;
cfg->dev = pdev;
- cfg->ops = &cxlflash_cxl_ops;
cfg->cxl_fops = cxlflash_cxl_fops;
+ if (ddv->flags & CXLFLASH_OCXL_DEV)
+ cfg->ops = &cxlflash_ocxl_ops;
+ else
+ cfg->ops = &cxlflash_cxl_ops;
+
/*
* Promoted LUNs move to the top of the LUN table. The rest stay on
* the bottom half. The bottom half grows from the end (index = 255),
diff --git a/drivers/scsi/cxlflash/main.h b/drivers/scsi/cxlflash/main.h
index ba0108a..6f1be62 100644
--- a/drivers/scsi/cxlflash/main.h
+++ b/drivers/scsi/cxlflash/main.h
@@ -97,6 +97,7 @@ struct dev_dependent_vals {
u64 flags;
#define CXLFLASH_NOTIFY_SHUTDOWN 0x0000000000000001ULL
#define CXLFLASH_WWPN_VPD_REQUIRED 0x0000000000000002ULL
+#define CXLFLASH_OCXL_DEV 0x0000000000000004ULL
};
struct asyc_intr_info {
--
2.1.0
^ permalink raw reply related
* [PATCH v2 37/38] cxlflash: Support AFU reset
From: Uma Krishnan @ 2018-02-26 22:24 UTC (permalink / raw)
To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
Manoj N. Kumar
Cc: linuxppc-dev, Andrew Donnellan, Frederic Barrat,
Christophe Lombard
In-Reply-To: <1519683513-16731-1-git-send-email-ukrishn@linux.vnet.ibm.com>
The cxlflash core driver resets the AFU when the master contexts are
created in the initialization or recovery paths. Today, the OCXL
provider service to perform this operation is pending implementation.
To avoid a crash due to a missing fop, log an error once and return
success to continue with execution.
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
---
drivers/scsi/cxlflash/ocxl_hw.c | 17 +++++++++++++++++
1 file changed, 17 insertions(+)
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 9356672..3c311f3 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -468,6 +468,22 @@ static int ocxlflash_stop_context(void *ctx_cookie)
}
/**
+ * ocxlflash_afu_reset() - reset the AFU
+ * @ctx_cookie: Adapter context.
+ */
+static int ocxlflash_afu_reset(void *ctx_cookie)
+{
+ struct ocxlflash_context *ctx = ctx_cookie;
+ struct device *dev = ctx->hw_afu->dev;
+
+ /* Pending implementation from OCXL transport services */
+ dev_err_once(dev, "%s: afu_reset() fop not supported\n", __func__);
+
+ /* Silently return success until it is implemented */
+ return 0;
+}
+
+/**
* ocxlflash_set_master() - sets the context as master
* @ctx_cookie: Adapter context to set as master.
*/
@@ -1393,6 +1409,7 @@ const struct cxlflash_backend_ops cxlflash_ocxl_ops = {
.get_irq_objhndl = ocxlflash_get_irq_objhndl,
.start_context = ocxlflash_start_context,
.stop_context = ocxlflash_stop_context,
+ .afu_reset = ocxlflash_afu_reset,
.set_master = ocxlflash_set_master,
.get_context = ocxlflash_get_context,
.dev_context_init = ocxlflash_dev_context_init,
--
2.1.0
^ permalink raw reply related
* [PATCH v2 36/38] cxlflash: Register for translation errors
From: Uma Krishnan @ 2018-02-26 22:24 UTC (permalink / raw)
To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
Manoj N. Kumar
Cc: linuxppc-dev, Andrew Donnellan, Frederic Barrat,
Christophe Lombard
In-Reply-To: <1519683513-16731-1-git-send-email-ukrishn@linux.vnet.ibm.com>
While enabling a context on the link, a predefined callback can be
registered with the OCXL provider services to be notified on translation
errors. These errors can in turn be passed back to the user on a read
operation.
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
---
drivers/scsi/cxlflash/ocxl_hw.c | 31 +++++++++++++++++++++++++++++--
drivers/scsi/cxlflash/ocxl_hw.h | 4 ++++
2 files changed, 33 insertions(+), 2 deletions(-)
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index d707e4c..9356672 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -335,6 +335,25 @@ static u64 ocxlflash_get_irq_objhndl(void *ctx_cookie, int irq)
}
/**
+ * ocxlflash_xsl_fault() - callback when translation error is triggered
+ * @data: Private data provided at callback registration, the context.
+ * @addr: Address that triggered the error.
+ * @dsisr: Value of dsisr register.
+ */
+static void ocxlflash_xsl_fault(void *data, u64 addr, u64 dsisr)
+{
+ struct ocxlflash_context *ctx = data;
+
+ spin_lock(&ctx->slock);
+ ctx->fault_addr = addr;
+ ctx->fault_dsisr = dsisr;
+ ctx->pending_fault = true;
+ spin_unlock(&ctx->slock);
+
+ wake_up_all(&ctx->wq);
+}
+
+/**
* start_context() - local routine to start a context
* @ctx: Adapter context to be started.
*
@@ -378,7 +397,8 @@ static int start_context(struct ocxlflash_context *ctx)
mm = current->mm;
}
- rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm, NULL, NULL);
+ rc = ocxl_link_add_pe(link_token, ctx->pe, pid, 0, 0, mm,
+ ocxlflash_xsl_fault, ctx);
if (unlikely(rc)) {
dev_err(dev, "%s: ocxl_link_add_pe failed rc=%d\n",
__func__, rc);
@@ -512,6 +532,7 @@ static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
ctx->hw_afu = afu;
ctx->irq_bitmap = 0;
ctx->pending_irq = false;
+ ctx->pending_fault = false;
out:
return ctx;
err2:
@@ -957,7 +978,7 @@ static void *ocxlflash_create_afu(struct pci_dev *pdev)
*/
static inline bool ctx_event_pending(struct ocxlflash_context *ctx)
{
- if (ctx->pending_irq)
+ if (ctx->pending_irq || ctx->pending_fault)
return true;
return false;
@@ -1062,6 +1083,12 @@ static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
event.irq.irq = bit + 1;
if (bitmap_empty(&ctx->irq_bitmap, ctx->num_irqs))
ctx->pending_irq = false;
+ } else if (ctx->pending_fault) {
+ event.header.size += sizeof(struct cxl_event_data_storage);
+ event.header.type = CXL_EVENT_DATA_STORAGE;
+ event.fault.addr = ctx->fault_addr;
+ event.fault.dsisr = ctx->fault_dsisr;
+ ctx->pending_fault = false;
}
spin_unlock_irqrestore(&ctx->slock, lock_flags);
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index a4f3b90..eb1c24a 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -69,4 +69,8 @@ struct ocxlflash_context {
int num_irqs; /* Number of interrupts */
bool pending_irq; /* Pending interrupt on the context */
ulong irq_bitmap; /* Bits indicating pending irq num */
+
+ u64 fault_addr; /* Address that triggered the fault */
+ u64 fault_dsisr; /* Value of dsisr register at fault */
+ bool pending_fault; /* Pending translation fault */
};
--
2.1.0
^ permalink raw reply related
* [PATCH v2 35/38] cxlflash: Introduce OCXL context state machine
From: Uma Krishnan @ 2018-02-26 22:24 UTC (permalink / raw)
To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
Manoj N. Kumar
Cc: linuxppc-dev, Andrew Donnellan, Frederic Barrat,
Christophe Lombard
In-Reply-To: <1519683513-16731-1-git-send-email-ukrishn@linux.vnet.ibm.com>
In order to protect the OCXL hardware contexts from getting clobbered,
a simple state machine is added to indicate when a context is in open,
close or start state. The expected states are validated throughout the
code to prevent illegal operations on a context. A mutex is added to
protect writes to the context state field.
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
---
drivers/scsi/cxlflash/ocxl_hw.c | 59 ++++++++++++++++++++++++++++++++++++++---
drivers/scsi/cxlflash/ocxl_hw.h | 8 ++++++
2 files changed, 64 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/cxlflash/ocxl_hw.c b/drivers/scsi/cxlflash/ocxl_hw.c
index 0e21f79..d707e4c 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.c
+++ b/drivers/scsi/cxlflash/ocxl_hw.c
@@ -163,6 +163,16 @@ static struct file *ocxlflash_getfile(struct device *dev, const char *name,
static void __iomem *ocxlflash_psa_map(void *ctx_cookie)
{
struct ocxlflash_context *ctx = ctx_cookie;
+ struct device *dev = ctx->hw_afu->dev;
+
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state != STARTED) {
+ dev_err(dev, "%s: Context not started, state=%d\n", __func__,
+ ctx->state);
+ mutex_unlock(&ctx->state_mutex);
+ return NULL;
+ }
+ mutex_unlock(&ctx->state_mutex);
return ioremap(ctx->psn_phys, ctx->psn_size);
}
@@ -343,6 +353,14 @@ static int start_context(struct ocxlflash_context *ctx)
int rc = 0;
u32 pid;
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state != OPENED) {
+ dev_err(dev, "%s: Context state invalid, state=%d\n",
+ __func__, ctx->state);
+ rc = -EINVAL;
+ goto out;
+ }
+
if (master) {
ctx->psn_size = acfg->global_mmio_size;
ctx->psn_phys = afu->gmmio_phys;
@@ -366,7 +384,10 @@ static int start_context(struct ocxlflash_context *ctx)
__func__, rc);
goto out;
}
+
+ ctx->state = STARTED;
out:
+ mutex_unlock(&ctx->state_mutex);
return rc;
}
@@ -396,7 +417,15 @@ static int ocxlflash_stop_context(void *ctx_cookie)
struct ocxl_afu_config *acfg = &afu->acfg;
struct pci_dev *pdev = afu->pdev;
struct device *dev = afu->dev;
- int rc;
+ enum ocxlflash_ctx_state state;
+ int rc = 0;
+
+ mutex_lock(&ctx->state_mutex);
+ state = ctx->state;
+ ctx->state = CLOSED;
+ mutex_unlock(&ctx->state_mutex);
+ if (state != STARTED)
+ goto out;
rc = ocxl_config_terminate_pasid(pdev, acfg->dvsec_afu_control_pos,
ctx->pe);
@@ -474,7 +503,9 @@ static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
spin_lock_init(&ctx->slock);
init_waitqueue_head(&ctx->wq);
+ mutex_init(&ctx->state_mutex);
+ ctx->state = OPENED;
ctx->pe = rc;
ctx->master = false;
ctx->mapping = NULL;
@@ -499,11 +530,23 @@ static void *ocxlflash_dev_context_init(struct pci_dev *pdev, void *afu_cookie)
static int ocxlflash_release_context(void *ctx_cookie)
{
struct ocxlflash_context *ctx = ctx_cookie;
+ struct device *dev;
int rc = 0;
if (!ctx)
goto out;
+ dev = ctx->hw_afu->dev;
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state >= STARTED) {
+ dev_err(dev, "%s: Context in use, state=%d\n", __func__,
+ ctx->state);
+ mutex_unlock(&ctx->state_mutex);
+ rc = -EBUSY;
+ goto out;
+ }
+ mutex_unlock(&ctx->state_mutex);
+
idr_remove(&ctx->hw_afu->idr, ctx->pe);
ocxlflash_release_mapping(ctx);
kfree(ctx);
@@ -939,7 +982,7 @@ static unsigned int afu_poll(struct file *file, struct poll_table_struct *poll)
spin_lock_irqsave(&ctx->slock, lock_flags);
if (ctx_event_pending(ctx))
mask |= POLLIN | POLLRDNORM;
- else
+ else if (ctx->state == CLOSED)
mask |= POLLERR;
spin_unlock_irqrestore(&ctx->slock, lock_flags);
@@ -982,7 +1025,7 @@ static ssize_t afu_read(struct file *file, char __user *buf, size_t count,
for (;;) {
prepare_to_wait(&ctx->wq, &event_wait, TASK_INTERRUPTIBLE);
- if (ctx_event_pending(ctx))
+ if (ctx_event_pending(ctx) || (ctx->state == CLOSED))
break;
if (file->f_flags & O_NONBLOCK) {
@@ -1068,12 +1111,22 @@ static int ocxlflash_mmap_fault(struct vm_fault *vmf)
{
struct vm_area_struct *vma = vmf->vma;
struct ocxlflash_context *ctx = vma->vm_file->private_data;
+ struct device *dev = ctx->hw_afu->dev;
u64 mmio_area, offset;
offset = vmf->pgoff << PAGE_SHIFT;
if (offset >= ctx->psn_size)
return VM_FAULT_SIGBUS;
+ mutex_lock(&ctx->state_mutex);
+ if (ctx->state != STARTED) {
+ dev_err(dev, "%s: Context not started, state=%d\n",
+ __func__, ctx->state);
+ mutex_unlock(&ctx->state_mutex);
+ return VM_FAULT_SIGBUS;
+ }
+ mutex_unlock(&ctx->state_mutex);
+
mmio_area = ctx->psn_phys;
mmio_area += offset;
diff --git a/drivers/scsi/cxlflash/ocxl_hw.h b/drivers/scsi/cxlflash/ocxl_hw.h
index d0eac35..a4f3b90 100644
--- a/drivers/scsi/cxlflash/ocxl_hw.h
+++ b/drivers/scsi/cxlflash/ocxl_hw.h
@@ -45,6 +45,12 @@ struct ocxl_hw_afu {
int max_pasid; /* Maximum number of contexts */
};
+enum ocxlflash_ctx_state {
+ CLOSED,
+ OPENED,
+ STARTED
+};
+
struct ocxlflash_context {
struct ocxl_hw_afu *hw_afu; /* HW AFU back pointer */
struct address_space *mapping; /* Mapping for pseudo filesystem */
@@ -56,6 +62,8 @@ struct ocxlflash_context {
spinlock_t slock; /* Protects irq/fault/event updates */
wait_queue_head_t wq; /* Wait queue for poll and interrupts */
+ struct mutex state_mutex; /* Mutex to update context state */
+ enum ocxlflash_ctx_state state; /* Context state */
struct ocxlflash_irqs *irqs; /* Pointer to array of structures */
int num_irqs; /* Number of interrupts */
--
2.1.0
^ permalink raw reply related
* [PATCH v2 34/38] cxlflash: Update synchronous interrupt status bits
From: Uma Krishnan @ 2018-02-26 22:24 UTC (permalink / raw)
To: linux-scsi, James Bottomley, Martin K. Petersen, Matthew R. Ochs,
Manoj N. Kumar
Cc: linuxppc-dev, Andrew Donnellan, Frederic Barrat,
Christophe Lombard
In-Reply-To: <1519683513-16731-1-git-send-email-ukrishn@linux.vnet.ibm.com>
The SISLite specification has been updated to define new synchronous
interrupt status bits. These bits are set by the AFU when a given PASID or
EA is bad and a synchronous interrupt is triggered.
The SISLite header file is updated to support these new bits. Note that
there are also some formatting updates to some of the existing bits to
allow all of the definitions to line up uniformly.
Signed-off-by: Uma Krishnan <ukrishn@linux.vnet.ibm.com>
Acked-by: Matthew R. Ochs <mrochs@linux.vnet.ibm.com>
---
drivers/scsi/cxlflash/sislite.h | 35 +++++++++++++++++++++--------------
1 file changed, 21 insertions(+), 14 deletions(-)
diff --git a/drivers/scsi/cxlflash/sislite.h b/drivers/scsi/cxlflash/sislite.h
index c08b9d3..874abce 100644
--- a/drivers/scsi/cxlflash/sislite.h
+++ b/drivers/scsi/cxlflash/sislite.h
@@ -258,23 +258,30 @@ struct sisl_host_map {
* exit since there is no way to tell which
* command caused the error.
*/
-#define SISL_ISTATUS_PERM_ERR_CMDROOM 0x0010ULL /* b59, user error */
-#define SISL_ISTATUS_PERM_ERR_RCB_READ 0x0008ULL /* b60, user error */
-#define SISL_ISTATUS_PERM_ERR_SA_WRITE 0x0004ULL /* b61, user error */
-#define SISL_ISTATUS_PERM_ERR_RRQ_WRITE 0x0002ULL /* b62, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_3_EA 0x0400ULL /* b53, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_2_EA 0x0200ULL /* b54, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_1_EA 0x0100ULL /* b55, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_3_PASID 0x0080ULL /* b56, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_2_PASID 0x0040ULL /* b57, user error */
+#define SISL_ISTATUS_PERM_ERR_LISN_1_PASID 0x0020ULL /* b58, user error */
+#define SISL_ISTATUS_PERM_ERR_CMDROOM 0x0010ULL /* b59, user error */
+#define SISL_ISTATUS_PERM_ERR_RCB_READ 0x0008ULL /* b60, user error */
+#define SISL_ISTATUS_PERM_ERR_SA_WRITE 0x0004ULL /* b61, user error */
+#define SISL_ISTATUS_PERM_ERR_RRQ_WRITE 0x0002ULL /* b62, user error */
/* Page in wait accessing RCB/IOASA/RRQ is reported in b63.
* Same error in data/LXT/RHT access is reported via IOASA.
*/
-#define SISL_ISTATUS_TEMP_ERR_PAGEIN 0x0001ULL /* b63, can be generated
- * only when AFU auto
- * retry is disabled.
- * If user can determine
- * the command that
- * caused the error, it
- * can be retried.
- */
-#define SISL_ISTATUS_UNMASK (0x001FULL) /* 1 means unmasked */
-#define SISL_ISTATUS_MASK ~(SISL_ISTATUS_UNMASK) /* 1 means masked */
+#define SISL_ISTATUS_TEMP_ERR_PAGEIN 0x0001ULL /* b63, can only be
+ * generated when AFU
+ * auto retry is
+ * disabled. If user
+ * can determine the
+ * command that caused
+ * the error, it can
+ * be retried.
+ */
+#define SISL_ISTATUS_UNMASK (0x07FFULL) /* 1 means unmasked */
+#define SISL_ISTATUS_MASK ~(SISL_ISTATUS_UNMASK) /* 1 means masked */
__be64 intr_clear;
__be64 intr_mask;
--
2.1.0
^ permalink raw reply related
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