LinuxPPC-Dev Archive on lore.kernel.org
 help / color / mirror / Atom feed
* Re: [PATCH v14 3/9] powerpc/modules: Make module_alloc() Strict Module RWX aware
From: Christophe Leroy @ 2021-05-17 11:05 UTC (permalink / raw)
  To: Michael Ellerman, Jordan Niethe
  Cc: ajd, Aneesh Kumar K.V, Nicholas Piggin, cmr, naveen.n.rao,
	linuxppc-dev, Daniel Axtens
In-Reply-To: <87lf8dk4iw.fsf@mpe.ellerman.id.au>



Le 17/05/2021 à 13:01, Michael Ellerman a écrit :
> Jordan Niethe <jniethe5@gmail.com> writes:
>> On Mon, May 17, 2021 at 4:37 PM Christophe Leroy
>> <christophe.leroy@csgroup.eu> wrote:
>>> Le 17/05/2021 à 05:28, Jordan Niethe a écrit :
>>>> Make module_alloc() use PAGE_KERNEL protections instead of
>>>> PAGE_KERNEL_EXEX if Strict Module RWX is enabled.
>>>>
>>>> Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
>>>> ---
>>>> v14: - Split out from powerpc: Set ARCH_HAS_STRICT_MODULE_RWX
>>>>        - Add and use strict_module_rwx_enabled() helper
>>>> ---
>>>>    arch/powerpc/include/asm/mmu.h | 5 +++++
>>>>    arch/powerpc/kernel/module.c   | 4 +++-
>>>>    2 files changed, 8 insertions(+), 1 deletion(-)
>>>>
>>>> diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
>>>> index 607168b1aef4..7710bf0cbf8a 100644
>>>> --- a/arch/powerpc/include/asm/mmu.h
>>>> +++ b/arch/powerpc/include/asm/mmu.h
>>>> @@ -357,6 +357,11 @@ static inline bool strict_kernel_rwx_enabled(void)
>>>>        return false;
>>>>    }
>>>>    #endif
>>>> +
>>>> +static inline bool strict_module_rwx_enabled(void)
>>>> +{
>>>> +     return IS_ENABLED(CONFIG_STRICT_MODULE_RWX) && strict_kernel_rwx_enabled();
>>>> +}
>>>
>>> Looking at arch/Kconfig, I have the feeling that it is possible to select CONFIG_STRICT_MODULE_RWX
>>> without selecting CONFIG_STRICT_KERNEL_RWX.
>>>
>>> In that case, strict_kernel_rwx_enabled() will return false.
> 
>> Ok, if someone did that currently it would break things, e.g. code
>> patching. I think it should it be made impossible to
>> CONFIG_STRICT_MODULE_RWX without CONFIG_STRICT_KERNEL_RWX?
> 
> Yeah I don't see any reason to support that combination.
> 
> We should be moving to a world where both are on by default, or in fact
> are always enabled.
> 

Would it work if we add the following in arch/powerpc/Kconfig ? :

	select STRICT_KERNEL_RWX if STRICT_MODULE_RWX

There should be no dependency issue as powerpc only selects ARCH_HAS_STRICT_MODULE_RWX when 
ARCH_HAS_STRICT_KERNEL_RWX is also selected.

Christophe

^ permalink raw reply

* Re: [PATCH v14 3/9] powerpc/modules: Make module_alloc() Strict Module RWX aware
From: Michael Ellerman @ 2021-05-17 11:01 UTC (permalink / raw)
  To: Jordan Niethe, Christophe Leroy
  Cc: ajd, Aneesh Kumar K.V, Nicholas Piggin, cmr, naveen.n.rao,
	linuxppc-dev, Daniel Axtens
In-Reply-To: <CACzsE9rk7D_ocSsf74C1vX=oXgLa_pQTSusncXRPeGBVe+48Nw@mail.gmail.com>

Jordan Niethe <jniethe5@gmail.com> writes:
> On Mon, May 17, 2021 at 4:37 PM Christophe Leroy
> <christophe.leroy@csgroup.eu> wrote:
>> Le 17/05/2021 à 05:28, Jordan Niethe a écrit :
>> > Make module_alloc() use PAGE_KERNEL protections instead of
>> > PAGE_KERNEL_EXEX if Strict Module RWX is enabled.
>> >
>> > Signed-off-by: Jordan Niethe <jniethe5@gmail.com>
>> > ---
>> > v14: - Split out from powerpc: Set ARCH_HAS_STRICT_MODULE_RWX
>> >       - Add and use strict_module_rwx_enabled() helper
>> > ---
>> >   arch/powerpc/include/asm/mmu.h | 5 +++++
>> >   arch/powerpc/kernel/module.c   | 4 +++-
>> >   2 files changed, 8 insertions(+), 1 deletion(-)
>> >
>> > diff --git a/arch/powerpc/include/asm/mmu.h b/arch/powerpc/include/asm/mmu.h
>> > index 607168b1aef4..7710bf0cbf8a 100644
>> > --- a/arch/powerpc/include/asm/mmu.h
>> > +++ b/arch/powerpc/include/asm/mmu.h
>> > @@ -357,6 +357,11 @@ static inline bool strict_kernel_rwx_enabled(void)
>> >       return false;
>> >   }
>> >   #endif
>> > +
>> > +static inline bool strict_module_rwx_enabled(void)
>> > +{
>> > +     return IS_ENABLED(CONFIG_STRICT_MODULE_RWX) && strict_kernel_rwx_enabled();
>> > +}
>>
>> Looking at arch/Kconfig, I have the feeling that it is possible to select CONFIG_STRICT_MODULE_RWX
>> without selecting CONFIG_STRICT_KERNEL_RWX.
>>
>> In that case, strict_kernel_rwx_enabled() will return false.

> Ok, if someone did that currently it would break things, e.g. code
> patching. I think it should it be made impossible to
> CONFIG_STRICT_MODULE_RWX without CONFIG_STRICT_KERNEL_RWX?

Yeah I don't see any reason to support that combination.

We should be moving to a world where both are on by default, or in fact
are always enabled.

cheers

^ permalink raw reply

* Re: [PATCH v2] lockdown,selinux: avoid bogus SELinux lockdown permission checks
From: Michael Ellerman @ 2021-05-17 11:00 UTC (permalink / raw)
  To: Ondrej Mosnacek, linux-security-module, James Morris
  Cc: selinux, netdev, Stephen Smalley, linux-kernel, Steven Rostedt,
	Casey Schaufler, Ingo Molnar, linux-fsdevel, bpf, linuxppc-dev
In-Reply-To: <20210517092006.803332-1-omosnace@redhat.com>

Ondrej Mosnacek <omosnace@redhat.com> writes:
> Commit 59438b46471a ("security,lockdown,selinux: implement SELinux
> lockdown") added an implementation of the locked_down LSM hook to
> SELinux, with the aim to restrict which domains are allowed to perform
> operations that would breach lockdown.
>
> However, in several places the security_locked_down() hook is called in
> situations where the current task isn't doing any action that would
> directly breach lockdown, leading to SELinux checks that are basically
> bogus.
>
> Since in most of these situations converting the callers such that
> security_locked_down() is called in a context where the current task
> would be meaningful for SELinux is impossible or very non-trivial (and
> could lead to TOCTOU issues for the classic Lockdown LSM
> implementation), fix this by modifying the hook to accept a struct cred
> pointer as argument, where NULL will be interpreted as a request for a
> "global", task-independent lockdown decision only. Then modify SELinux
> to ignore calls with cred == NULL.
>
> Since most callers will just want to pass current_cred() as the cred
> parameter, rename the hook to security_cred_locked_down() and provide
> the original security_locked_down() function as a simple wrapper around
> the new hook.
>
> The callers migrated to the new hook, passing NULL as cred:
> 1. arch/powerpc/xmon/xmon.c
>      Here the hook seems to be called from non-task context and is only
>      used for redacting some sensitive values from output sent to
>      userspace.

It's hard to follow but it actually disables interactive use of xmon
entirely if lockdown is in confidentiality mode, and disables
modifications of the kernel in integrity mode.

But that's not really that important, the patch looks fine.

Acked-by: Michael Ellerman <mpe@ellerman.id.au> (powerpc)

cheers

^ permalink raw reply

* Re: Fwd: [Bug 213069] New: kernel BUG at arch/powerpc/include/asm/book3s/64/hash-4k.h:147! Oops: Exception in kernel mode, sig: 5 [#1]
From: Anshuman Khandual @ 2021-05-17 10:53 UTC (permalink / raw)
  To: Aneesh Kumar K.V, Christophe Leroy, linuxppc-dev@lists.ozlabs.org
In-Reply-To: <e0d2093d-56ec-5c7a-6887-22eecc5142b7@linux.ibm.com>



On 5/17/21 1:14 PM, Aneesh Kumar K.V wrote:
> On 5/17/21 12:55 PM, Anshuman Khandual wrote:
>>
>>
>> On 5/17/21 11:25 AM, Aneesh Kumar K.V wrote:
>>> On 5/17/21 11:17 AM, Christophe Leroy wrote:
>>>> +aneesh
>>>> +linuxppc-dev list
>>>>
>>>> Le 17/05/2021 à 07:44, Anshuman Khandual a écrit :
>>>>> Hello Christophe,
>>>>>
>>>>> DEBUG_VM_PGTABLE has now been re-enabled on powerpc recently ? was not
>>>>> aware about this. From the error log, it failed explicitly on 4K page
>>>>> size hash config.
>>>>>
>>>>> static inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
>>>>> {
>>>>>           BUG();        ------> Failed
>>>>>           return pmd;
>>>>> }
>>>>>
>>>>> static inline pmd_t __pmd_mkhuge(pmd_t pmd)
>>>>> {
>>>>>           if (radix_enabled())
>>>>>                   return radix__pmd_mkhuge(pmd);
>>>>>           return hash__pmd_mkhuge(pmd);
>>>>> }
>>>>>
>>>>> pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
>>>>> {
>>>>>           unsigned long pmdv;
>>>>>
>>>>>           pmdv = (pfn << PAGE_SHIFT) & PTE_RPN_MASK;
>>>>>
>>>>>           return __pmd_mkhuge(pmd_set_protbits(__pmd(pmdv), pgprot));
>>>>> }
>>>>>
>>>>> It seems like on powerpc, where pfn_pmd() makes a huge page but which
>>>>> is not supported on 4K hash config thus triggering the BUG(). But all
>>>>> pfn_pmd() call sites inside the debug_vm_pgtable() test are protected
>>>>> with CONFIG_TRANSPARENT_HUGEPAGE. IIUC unlike powerpc, pfn_pmd() does
>>>>> not directly make a huge page on other platforms.
>>>>>
>>>>> Looking at arch/powerpc/include/asm/book3s/64/hash-4k.h, all relevant
>>>>> THP helpers has BUG() or 0 which indicates THP might not be supported
>>>>> on 4K page size hash config ?
>>>>>
>>>>> But looking at arch/powerpc/platforms/Kconfig.cputype, it seems like
>>>>> HAVE_ARCH_TRANSPARENT_HUGEPAGE is invariably selected on PPC_BOOK3S_64
>>>>> platforms which I assume includes 4K page size hash config as well.
>>>>>
>>>>> Is THP some how getting enabled on this 4K page size hash config where
>>>>> it should not be (thus triggering the BUG) ? OR am I missing something
>>>>> here.
>>>>>
>>>>
>>>
>>> We should put those  pfn_pmd()  and pfn_pud() after
>>>
>>>      if (!has_transparent_hugepage())
>>>          return;
>>>
>>>
>>> On hash with 4K page size, we can't support leaf page table entry and PMD and PUD level. Hence we don't support THP for them.
>>
>> But could CONFIG_TRANSPARENT_HUGEPAGE be enabled on such configs ?
>> Otherwise, wondering how the BUG() just got triggered there.
>>
> 
> yes. We do support THP with radix translation and 4K page size.

I was actually wondering about whether 4K page size in hash config
supports THP and could enable CONFIG_TRANSPARENT_HUGEPAGE ? But as
there is a BUG() trigger on hash__pmd_mkhuge(), it seems like THP
config should not have been enabled for such platforms but it does
for some reason. Could not we disable it ?

^ permalink raw reply

* [PATCH v3 1/2] ASoC: dt-bindings: imx-card: Add binding doc for imx sound card
From: Shengjiu Wang @ 2021-05-17 10:31 UTC (permalink / raw)
  To: lgirdwood, broonie, perex, tiwai, timur, nicoleotsuka, Xiubo.Lee,
	festevam, shawnguo, s.hauer, kernel, linux-imx, linux-kernel,
	alsa-devel, linuxppc-dev, linux-arm-kernel, robh+dt, devicetree

Imx-card is a new added machine driver for supporting
ak4458/ak5558/ak5552/ak4497 codec on i.MX platforms. But these
DAC/ADCs are not only supported codecs. This machine driver is
designed to be a more common machine driver for i.MX platform,
it can support widely cpu dai interface and codec dai interface.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
---
changes in v3:
- use a generic compatible string as Rob's comments.
- change the file name

changes in v2:
- update doc accoring to Rob's comment, use the common porperties.

 .../bindings/sound/imx-audio-card.yaml        | 122 ++++++++++++++++++
 1 file changed, 122 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-card.yaml

diff --git a/Documentation/devicetree/bindings/sound/imx-audio-card.yaml b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
new file mode 100644
index 000000000000..d1816dd061cf
--- /dev/null
+++ b/Documentation/devicetree/bindings/sound/imx-audio-card.yaml
@@ -0,0 +1,122 @@
+# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/sound/imx-audio-card.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: NXP i.MX audio sound card.
+
+maintainers:
+  - Shengjiu Wang <shengjiu.wang@nxp.com>
+
+properties:
+  compatible:
+    enum:
+      - fsl,imx-audio-card
+
+  model:
+    $ref: /schemas/types.yaml#/definitions/string
+    description: User specified audio sound card name
+
+  audio-routing:
+    $ref: /schemas/types.yaml#/definitions/non-unique-string-array
+    description:
+      A list of the connections between audio components. Each entry is a
+      pair of strings, the first being the connection's sink, the second
+      being the connection's source. Valid names could be power supplies,
+      MicBias of codec and the jacks on the board.
+
+patternProperties:
+  ".*-dai-link$":
+    description:
+      Each subnode represents a dai link. Subnodes of each dai links would be
+      cpu/codec dais.
+
+    type: object
+
+    properties:
+      link-name:
+        description: Indicates dai-link name and PCM stream name.
+        $ref: /schemas/types.yaml#/definitions/string
+        maxItems: 1
+
+      format:
+        description: audio format.
+        items:
+          enum:
+            - i2s
+            - dsp_b
+
+      dai-tdm-slot-num:
+        description: see tdm-slot.txt.
+        $ref: /schemas/types.yaml#/definitions/uint32
+
+      dai-tdm-slot-width:
+        description: see tdm-slot.txt.
+        $ref: /schemas/types.yaml#/definitions/uint32
+
+      cpu:
+        description: Holds subnode which indicates cpu dai.
+        type: object
+        properties:
+          sound-dai: true
+
+      codec:
+        description: Holds subnode which indicates codec dai.
+        type: object
+        properties:
+          sound-dai: true
+
+      fsl,mclk-equal-bclk:
+        description: Indicates mclk can be equal to bclk, especially for sai interface
+        $ref: /schemas/types.yaml#/definitions/flag
+
+    required:
+      - link-name
+      - cpu
+
+    additionalProperties: false
+
+required:
+  - compatible
+  - model
+
+additionalProperties: false
+
+examples:
+  - |
+    sound-ak4458 {
+        compatible = "fsl,imx-audio-card";
+        model = "ak4458-audio";
+        pri-dai-link {
+            link-name = "akcodec";
+            format = "i2s";
+            fsl,mclk-equal-bclk;
+            cpu {
+                 sound-dai = <&sai1>;
+            };
+            codec {
+                 sound-dai = <&ak4458_1>, <&ak4458_2>;
+            };
+        };
+        fe-dai-link {
+            link-name = "HiFi-ASRC-FE";
+            format = "i2s";
+            cpu {
+                sound-dai = <&easrc>;
+            };
+        };
+        be-dai-link {
+            link-name = "HiFi-ASRC-BE";
+            format = "dsp_b";
+            dai-tdm-slot-num = <8>;
+            dai-tdm-slot-width = <32>;
+            fsl,mclk-equal-bclk;
+            cpu {
+                sound-dai = <&sai1>;
+            };
+            codec {
+                sound-dai = <&ak4458_1>, <&ak4458_2>;
+            };
+        };
+    };
-- 
2.27.0


^ permalink raw reply related

* [PATCH v3 2/2] ASoC: imx-card: Add imx-card machine driver
From: Shengjiu Wang @ 2021-05-17 10:31 UTC (permalink / raw)
  To: lgirdwood, broonie, perex, tiwai, timur, nicoleotsuka, Xiubo.Lee,
	festevam, shawnguo, s.hauer, kernel, linux-imx, linux-kernel,
	alsa-devel, linuxppc-dev, linux-arm-kernel, robh+dt, devicetree
In-Reply-To: <1621247488-21412-1-git-send-email-shengjiu.wang@nxp.com>

Add machine driver for i.MX boards, which supports
AK4458/AK5558/AK4497/AK5552 DAC/ADC attached to
SAI interface currently, but these DAC/ADCs are not
only supported codecs. This machine driver is designed
to be a more common machine driver for i.MX platform,
it can support widely cpu dai interface and codec
dai interface.

Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
Signed-off-by: Mihai Serban <mihai.serban@nxp.com>
Signed-off-by: Cosmin-Gabriel Samoila <cosmin.samoila@nxp.com>
Signed-off-by: Viorel Suman <viorel.suman@nxp.com>
Signed-off-by: Daniel Baluta <daniel.baluta@nxp.com>
Signed-off-by: Adrian Alonso <adrian.alonso@nxp.com>
---
changes in v3:
- update the code according to the change of binding doc
- change the file name.

changes in v2:
- update the code according to the change of binding doc

 sound/soc/fsl/Kconfig    |  13 +
 sound/soc/fsl/Makefile   |   2 +
 sound/soc/fsl/imx-card.c | 844 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 859 insertions(+)
 create mode 100644 sound/soc/fsl/imx-card.c

diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig
index 0917d65d6921..88542b270091 100644
--- a/sound/soc/fsl/Kconfig
+++ b/sound/soc/fsl/Kconfig
@@ -350,6 +350,19 @@ config SND_SOC_IMX_RPMSG
 	  Say Y if you want to add support for SoC audio on an i.MX board with
 	  a rpmsg devices.
 
+config SND_SOC_IMX_CARD
+	tristate "SoC Audio Graph Sound Card support for i.MX boards"
+	depends on OF && I2C
+	select SND_SOC_AK4458
+	select SND_SOC_AK5558
+	select SND_SOC_IMX_PCM_DMA
+	select SND_SOC_FSL_SAI
+	select SND_SIMPLE_CARD_UTILS
+	help
+	  This option enables audio sound card support for i.MX boards
+	  with OF-graph DT bindings.
+	  It also support DPCM of single CPU multi Codec ststem.
+
 endif # SND_IMX_SOC
 
 endmenu
diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile
index f146ce464acd..b54beb1a66fa 100644
--- a/sound/soc/fsl/Makefile
+++ b/sound/soc/fsl/Makefile
@@ -71,6 +71,7 @@ snd-soc-imx-spdif-objs := imx-spdif.o
 snd-soc-imx-audmix-objs := imx-audmix.o
 snd-soc-imx-hdmi-objs := imx-hdmi.o
 snd-soc-imx-rpmsg-objs := imx-rpmsg.o
+snd-soc-imx-card-objs := imx-card.o
 
 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o
 obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o
@@ -79,3 +80,4 @@ obj-$(CONFIG_SND_SOC_IMX_SPDIF) += snd-soc-imx-spdif.o
 obj-$(CONFIG_SND_SOC_IMX_AUDMIX) += snd-soc-imx-audmix.o
 obj-$(CONFIG_SND_SOC_IMX_HDMI) += snd-soc-imx-hdmi.o
 obj-$(CONFIG_SND_SOC_IMX_RPMSG) += snd-soc-imx-rpmsg.o
+obj-$(CONFIG_SND_SOC_IMX_CARD) += snd-soc-imx-card.o
diff --git a/sound/soc/fsl/imx-card.c b/sound/soc/fsl/imx-card.c
new file mode 100644
index 000000000000..ab424735bbfe
--- /dev/null
+++ b/sound/soc/fsl/imx-card.c
@@ -0,0 +1,844 @@
+// SPDX-License-Identifier: GPL-2.0+
+// Copyright 2017-2021 NXP
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/gpio/consumer.h>
+#include <linux/of_device.h>
+#include <linux/i2c.h>
+#include <linux/of_gpio.h>
+#include <linux/clk.h>
+#include <sound/soc.h>
+#include <sound/pcm_params.h>
+#include <sound/pcm.h>
+#include <sound/soc-dapm.h>
+#include <sound/simple_card_utils.h>
+
+#include "fsl_sai.h"
+
+enum codec_type {
+	CODEC_DUMMY = 0,
+	CODEC_AK5558 = 1,
+	CODEC_AK4458,
+	CODEC_AK4497,
+	CODEC_AK5552,
+};
+
+/*
+ * Mapping LRCK fs and frame width, table 3 & 4 in datasheet
+ * @rmin: min rate
+ * @rmax: max rate
+ * @wmin: min frame ratio
+ * @wmax: max frame ratio
+ */
+struct imx_akcodec_fs_mul {
+	unsigned int rmin;
+	unsigned int rmax;
+	unsigned int wmin;
+	unsigned int wmax;
+};
+
+/*
+ * Mapping TDM mode and frame width
+ */
+struct imx_akcodec_tdm_fs_mul {
+	unsigned int min;
+	unsigned int max;
+	unsigned int mul;
+};
+
+/*
+ * struct imx_card_plat_data - specific info for codecs
+ *
+ * @fs_mul: ratio of mclk/fs for normal mode
+ * @tdm_fs_mul: ratio of mclk/fs for tdm mode
+ * @support_rates: supported sample rate
+ * @support_tdm_rates: supported sample rate for tdm mode
+ * @support_channels: supported channels
+ * @support_tdm_channels: supported channels for tdm mode
+ * @num_fs_mul: ARRAY_SIZE of fs_mul
+ * @num_tdm_fs_mul: ARRAY_SIZE of tdm_fs_mul
+ * @num_rates: ARRAY_SIZE of support_rates
+ * @num_tdm_rates: ARRAY_SIZE of support_tdm_rates
+ * @num_channels: ARRAY_SIZE of support_channels
+ * @num_tdm_channels: ARRAY_SIZE of support_tdm_channels
+ * @type: codec type
+ */
+struct imx_card_plat_data {
+	struct imx_akcodec_fs_mul  *fs_mul;
+	struct imx_akcodec_tdm_fs_mul  *tdm_fs_mul;
+	const u32 *support_rates;
+	const u32 *support_tdm_rates;
+	const u32 *support_channels;
+	const u32 *support_tdm_channels;
+	unsigned int num_fs_mul;
+	unsigned int num_tdm_fs_mul;
+	unsigned int num_rates;
+	unsigned int num_tdm_rates;
+	unsigned int num_channels;
+	unsigned int num_tdm_channels;
+	unsigned int num_codecs;
+	enum codec_type type;
+};
+
+/*
+ * struct dai_link_data - specific info for dai link
+ *
+ * @slots: slot number
+ * @slot_width: slot width value
+ * @cpu_sysclk_id: sysclk id for cpu dai
+ * @one2one_ratio: true if mclk equal to bclk
+ */
+struct dai_link_data {
+	unsigned int slots;
+	unsigned int slot_width;
+	unsigned int cpu_sysclk_id;
+	bool one2one_ratio;
+};
+
+/*
+ * struct imx_card_data - platform device data
+ *
+ * @plat_data: pointer of imx_card_plat_data
+ * @dapm_routes: pointer of dapm_routes
+ * @link_data: private data for dai link
+ * @card: card instance
+ * @num_dapm_routes: number of dapm_routes
+ * @asrc_rate: asrc rates
+ * @asrc_format: asrc format
+ */
+struct imx_card_data {
+	struct imx_card_plat_data *plat_data;
+	struct snd_soc_dapm_route *dapm_routes;
+	struct dai_link_data *link_data;
+	struct snd_soc_card card;
+	int num_dapm_routes;
+	u32 asrc_rate;
+	u32 asrc_format;
+};
+
+struct imx_akcodec_fs_mul ak4458_fs_mul[] = {
+	/* Normal, < 32kHz */
+	{ .rmin = 8000,   .rmax = 24000,  .wmin = 1024, .wmax = 1024, },
+	/* Normal, 32kHz */
+	{ .rmin = 32000,  .rmax = 32000,  .wmin = 256,  .wmax = 1024, },
+	/* Normal */
+	{ .rmin = 44100,  .rmax = 48000,  .wmin = 256,  .wmax = 768,  },
+	/* Double */
+	{ .rmin = 88200,  .rmax = 96000,  .wmin = 256,  .wmax = 512,  },
+	/* Quad */
+	{ .rmin = 176400, .rmax = 192000, .wmin = 128,  .wmax = 256,  },
+	/* Oct */
+	{ .rmin = 352800, .rmax = 384000, .wmin = 32,   .wmax = 128,  },
+	/* Hex */
+	{ .rmin = 705600, .rmax = 768000, .wmin = 16,   .wmax = 64,   },
+};
+
+struct imx_akcodec_tdm_fs_mul ak4458_tdm_fs_mul[] = {
+	/*
+	 * Table 13	- Audio Interface Format
+	 * For TDM mode, MCLK should is set to
+	 * obtained from 2 * slots * slot_width
+	 */
+	{ .min = 128,	.max = 128,	.mul = 256  }, /* TDM128 */
+	{ .min = 256,	.max = 256,	.mul = 512  }, /* TDM256 */
+	{ .min = 512,	.max = 512,	.mul = 1024  }, /* TDM512 */
+};
+
+struct imx_akcodec_fs_mul ak4497_fs_mul[] = {
+	/**
+	 * Table 7      - mapping multiplier and speed mode
+	 * Tables 8 & 9 - mapping speed mode and LRCK fs
+	 */
+	{ .rmin = 8000,   .rmax = 32000,  .wmin = 1024, .wmax = 1024, }, /* Normal, <= 32kHz */
+	{ .rmin = 44100,  .rmax = 48000,  .wmin = 512,  .wmax = 512, }, /* Normal */
+	{ .rmin = 88200,  .rmax = 96000,  .wmin = 256,  .wmax = 256, }, /* Double */
+	{ .rmin = 176400, .rmax = 192000, .wmin = 128,  .wmax = 128, }, /* Quad */
+	{ .rmin = 352800, .rmax = 384000, .wmin = 128,  .wmax = 128, }, /* Oct */
+	{ .rmin = 705600, .rmax = 768000, .wmin = 64,   .wmax = 64, }, /* Hex */
+};
+
+/*
+ * Auto MCLK selection based on LRCK for Normal Mode
+ * (Table 4 from datasheet)
+ */
+struct imx_akcodec_fs_mul ak5558_fs_mul[] = {
+	{ .rmin = 8000,   .rmax = 32000,  .wmin = 1024, .wmax = 1024, },
+	{ .rmin = 44100,  .rmax = 48000,  .wmin = 512,  .wmax = 512, },
+	{ .rmin = 88200,  .rmax = 96000,  .wmin = 256,  .wmax = 256, },
+	{ .rmin = 176400, .rmax = 192000, .wmin = 128,  .wmax = 128, },
+	{ .rmin = 352800, .rmax = 384000, .wmin = 64,   .wmax = 64, },
+	{ .rmin = 705600, .rmax = 768000, .wmin = 32,   .wmax = 32, },
+};
+
+/*
+ * MCLK and BCLK selection based on TDM mode
+ * because of SAI we also add the restriction: MCLK >= 2 * BCLK
+ * (Table 9 from datasheet)
+ */
+struct imx_akcodec_tdm_fs_mul ak5558_tdm_fs_mul[] = {
+	{ .min = 128,	.max = 128,	.mul = 256 },
+	{ .min = 256,	.max = 256,	.mul = 512 },
+	{ .min = 512,	.max = 512,	.mul = 1024 },
+};
+
+static const u32 akcodec_rates[] = {
+	8000, 11025, 16000, 22050, 32000, 44100, 48000, 88200,
+	96000, 176400, 192000, 352800, 384000, 705600, 768000,
+};
+
+static const u32 akcodec_tdm_rates[] = {
+	8000, 16000, 32000, 48000, 96000,
+};
+
+static const u32 ak4458_channels[] = {
+	1, 2, 4, 6, 8, 10, 12, 14, 16,
+};
+
+static const u32 ak4458_tdm_channels[] = {
+	1, 2, 3, 4, 5, 6, 7, 8, 16,
+};
+
+static const u32 ak5558_channels[] = {
+	1, 2, 4, 6, 8,
+};
+
+static const u32 ak5558_tdm_channels[] = {
+	1, 2, 3, 4, 5, 6, 7, 8,
+};
+
+static bool format_is_dsd(struct snd_pcm_hw_params *params)
+{
+	snd_pcm_format_t format = params_format(params);
+
+	switch (format) {
+	case SNDRV_PCM_FORMAT_DSD_U8:
+	case SNDRV_PCM_FORMAT_DSD_U16_LE:
+	case SNDRV_PCM_FORMAT_DSD_U16_BE:
+	case SNDRV_PCM_FORMAT_DSD_U32_LE:
+	case SNDRV_PCM_FORMAT_DSD_U32_BE:
+		return true;
+	default:
+		return false;
+	}
+}
+
+static bool format_is_tdm(struct dai_link_data *link_data)
+{
+	if (link_data->slots > 2)
+		return true;
+	else
+		return false;
+}
+
+static bool codec_is_akcodec(unsigned int type)
+{
+	switch (type) {
+	case CODEC_AK4458:
+	case CODEC_AK4497:
+	case CODEC_AK5558:
+	case CODEC_AK5552:
+		return true;
+	default:
+		break;
+	}
+	return false;
+}
+
+static unsigned long akcodec_get_mclk_rate(struct snd_pcm_substream *substream,
+					   struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct imx_card_data *data = snd_soc_card_get_drvdata(rtd->card);
+	const struct imx_card_plat_data *plat_data = data->plat_data;
+	struct dai_link_data *link_data = &data->link_data[rtd->num];
+	unsigned int width = link_data->slots * link_data->slot_width;
+	unsigned int rate = params_rate(params);
+	int i;
+
+	if (format_is_tdm(link_data)) {
+		for (i = 0; i < plat_data->num_tdm_fs_mul; i++) {
+			/* min = max = slots * slots_width */
+			if (width != plat_data->tdm_fs_mul[i].min)
+				continue;
+			return rate * plat_data->tdm_fs_mul[i].mul;
+		}
+	} else {
+		for (i = 0; i < plat_data->num_fs_mul; i++) {
+			if (rate >= plat_data->fs_mul[i].rmin &&
+			    rate <= plat_data->fs_mul[i].rmax) {
+				width = max(width, plat_data->fs_mul[i].wmin);
+				width = min(width, plat_data->fs_mul[i].wmax);
+
+				/* Adjust SAI bclk:mclk ratio */
+				width *= link_data->one2one_ratio ? 1 : 2;
+
+				return rate * width;
+			}
+		}
+	}
+
+	/* Let DAI manage clk frequency by default */
+	return 0;
+}
+
+static int imx_aif_hw_params(struct snd_pcm_substream *substream,
+			     struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0);
+	struct snd_soc_card *card = rtd->card;
+	struct imx_card_data *data = snd_soc_card_get_drvdata(card);
+	struct dai_link_data *link_data = &data->link_data[rtd->num];
+	struct imx_card_plat_data *plat_data = data->plat_data;
+	struct device *dev = card->dev;
+	struct snd_soc_dai *codec_dai;
+	unsigned long mclk_freq;
+	unsigned int fmt = rtd->dai_link->dai_fmt;
+	unsigned int slots, slot_width;
+	int ret, i;
+
+	slots = link_data->slots;
+	slot_width = link_data->slot_width;
+
+	if (!format_is_tdm(link_data)) {
+		if (format_is_dsd(params)) {
+			slots = 1;
+			slot_width = params_width(params);
+			fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) |
+			      SND_SOC_DAIFMT_PDM;
+		} else {
+			slots = 2;
+			slot_width = params_physical_width(params);
+			fmt = (rtd->dai_link->dai_fmt & ~SND_SOC_DAIFMT_FORMAT_MASK) |
+			      SND_SOC_DAIFMT_I2S;
+		}
+	}
+
+	ret = snd_soc_dai_set_fmt(cpu_dai, fmt);
+	if (ret && ret != -ENOTSUPP) {
+		dev_err(dev, "failed to set cpu dai fmt: %d\n", ret);
+		return ret;
+	}
+	ret = snd_soc_dai_set_tdm_slot(cpu_dai,
+				       BIT(slots) - 1,
+				       BIT(slots) - 1,
+				       slots, slot_width);
+	if (ret && ret != -ENOTSUPP) {
+		dev_err(dev, "failed to set cpu dai tdm slot: %d\n", ret);
+		return ret;
+	}
+
+	for_each_rtd_codec_dais(rtd, i, codec_dai) {
+		ret = snd_soc_dai_set_fmt(codec_dai, fmt);
+		if (ret && ret != -ENOTSUPP) {
+			dev_err(dev, "failed to set codec dai[%d] fmt: %d\n", i, ret);
+			return ret;
+		}
+
+		ret = snd_soc_dai_set_tdm_slot(codec_dai,
+					       BIT(slots) - 1,
+					       BIT(slots) - 1,
+					       slots, slot_width);
+		if (ret && ret != -ENOTSUPP) {
+			dev_err(dev, "failed to set codec dai[%d] tdm slot: %d\n", i, ret);
+			return ret;
+		}
+	}
+
+	/* Set MCLK freq */
+	if (codec_is_akcodec(plat_data->type))
+		mclk_freq = akcodec_get_mclk_rate(substream, params);
+	else
+		mclk_freq = params_rate(params) * slots * slot_width;
+	/* Use the maximum freq from DSD512 (512*44100 = 22579200) */
+	if (format_is_dsd(params))
+		mclk_freq = 22579200;
+
+	ret = snd_soc_dai_set_sysclk(cpu_dai, link_data->cpu_sysclk_id, mclk_freq,
+				     SND_SOC_CLOCK_OUT);
+	if (ret && ret != -ENOTSUPP) {
+		dev_err(dev, "failed to set cpui dai mclk1 rate (%lu): %d\n", mclk_freq, ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static int ak5558_hw_rule_rate(struct snd_pcm_hw_params *p, struct snd_pcm_hw_rule *r)
+{
+	struct dai_link_data *link_data = r->private;
+	struct snd_interval t = { .min = 8000, .max = 8000, };
+	unsigned long mclk_freq;
+	unsigned int fs;
+	int i;
+
+	fs = hw_param_interval(p, SNDRV_PCM_HW_PARAM_SAMPLE_BITS)->min;
+	fs *= link_data->slots;
+
+	/* Identify maximum supported rate */
+	for (i = 0; i < ARRAY_SIZE(akcodec_rates); i++) {
+		mclk_freq = fs * akcodec_rates[i];
+		/* Adjust SAI bclk:mclk ratio */
+		mclk_freq *= link_data->one2one_ratio ? 1 : 2;
+
+		/* Skip rates for which MCLK is beyond supported value */
+		if (mclk_freq > 36864000)
+			continue;
+
+		if (t.max < akcodec_rates[i])
+			t.max = akcodec_rates[i];
+	}
+
+	return snd_interval_refine(hw_param_interval(p, r->var), &t);
+}
+
+static int imx_aif_startup(struct snd_pcm_substream *substream)
+{
+	struct snd_pcm_runtime *runtime = substream->runtime;
+	struct snd_soc_pcm_runtime *rtd = substream->private_data;
+	struct snd_soc_card *card = rtd->card;
+	struct imx_card_data *data = snd_soc_card_get_drvdata(card);
+	struct dai_link_data *link_data = &data->link_data[rtd->num];
+	static struct snd_pcm_hw_constraint_list constraint_rates;
+	static struct snd_pcm_hw_constraint_list constraint_channels;
+	int ret = 0;
+
+	if (format_is_tdm(link_data)) {
+		constraint_channels.list = data->plat_data->support_tdm_channels;
+		constraint_channels.count = data->plat_data->num_tdm_channels;
+		constraint_rates.list = data->plat_data->support_tdm_rates;
+		constraint_rates.count = data->plat_data->num_tdm_rates;
+	} else {
+		constraint_channels.list = data->plat_data->support_channels;
+		constraint_channels.count = data->plat_data->num_channels;
+		constraint_rates.list = data->plat_data->support_rates;
+		constraint_rates.count = data->plat_data->num_rates;
+	}
+
+	if (constraint_channels.count) {
+		ret = snd_pcm_hw_constraint_list(runtime, 0,
+						 SNDRV_PCM_HW_PARAM_CHANNELS,
+						 &constraint_channels);
+		if (ret)
+			return ret;
+	}
+
+	if (constraint_rates.count) {
+		ret = snd_pcm_hw_constraint_list(runtime, 0,
+						 SNDRV_PCM_HW_PARAM_RATE,
+						 &constraint_rates);
+		if (ret)
+			return ret;
+	}
+
+	if (data->plat_data->type == CODEC_AK5558)
+		ret = snd_pcm_hw_rule_add(substream->runtime, 0,
+					  SNDRV_PCM_HW_PARAM_RATE,
+					  ak5558_hw_rule_rate, link_data,
+					  SNDRV_PCM_HW_PARAM_SAMPLE_BITS, -1);
+
+	return ret;
+}
+
+static struct snd_soc_ops imx_aif_ops = {
+	.hw_params = imx_aif_hw_params,
+	.startup = imx_aif_startup,
+};
+
+static struct snd_soc_ops imx_aif_ops_be = {
+	.hw_params = imx_aif_hw_params,
+};
+
+static int be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd,
+			      struct snd_pcm_hw_params *params)
+{
+	struct snd_soc_card *card = rtd->card;
+	struct imx_card_data *data = snd_soc_card_get_drvdata(card);
+	struct snd_interval *rate;
+	struct snd_mask *mask;
+
+	rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE);
+	rate->max = data->asrc_rate;
+	rate->min = data->asrc_rate;
+
+	mask = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT);
+	snd_mask_none(mask);
+	snd_mask_set(mask, data->asrc_format);
+
+	return 0;
+}
+
+static int imx_card_parse_of(struct imx_card_data *data)
+{
+	struct imx_card_plat_data *plat_data = data->plat_data;
+	struct snd_soc_card *card = &data->card;
+	struct snd_soc_dai_link_component *dlc;
+	struct device_node *platform = NULL;
+	struct device_node *codec = NULL;
+	struct device_node *cpu = NULL;
+	struct device_node *np;
+	struct device *dev = card->dev;
+	struct snd_soc_dai_link *link;
+	struct dai_link_data *link_data;
+	struct of_phandle_args args;
+	int ret, num_links;
+	u32 width;
+
+	ret = snd_soc_of_parse_card_name(card, "model");
+	if (ret) {
+		dev_err(dev, "Error parsing card name: %d\n", ret);
+		return ret;
+	}
+
+	/* DAPM routes */
+	if (of_property_read_bool(dev->of_node, "audio-routing")) {
+		ret = snd_soc_of_parse_audio_routing(card, "audio-routing");
+		if (ret)
+			return ret;
+	}
+
+	/* Populate links */
+	num_links = of_get_child_count(dev->of_node);
+
+	/* Allocate the DAI link array */
+	card->dai_link = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
+	if (!card->dai_link)
+		return -ENOMEM;
+
+	data->link_data = devm_kcalloc(dev, num_links, sizeof(*link), GFP_KERNEL);
+	if (!data->link_data)
+		return -ENOMEM;
+
+	card->num_links = num_links;
+	link = card->dai_link;
+	link_data = data->link_data;
+
+	for_each_child_of_node(dev->of_node, np) {
+		dlc = devm_kzalloc(dev, 2 * sizeof(*dlc), GFP_KERNEL);
+		if (!dlc) {
+			ret = -ENOMEM;
+			goto err_put_np;
+		}
+
+		link->cpus	= &dlc[0];
+		link->platforms	= &dlc[1];
+
+		link->num_cpus		= 1;
+		link->num_platforms	= 1;
+
+		ret = of_property_read_string(np, "link-name", &link->name);
+		if (ret) {
+			dev_err(card->dev, "error getting codec dai_link name\n");
+			goto err_put_np;
+		}
+
+		cpu = of_get_child_by_name(np, "cpu");
+		if (!cpu) {
+			dev_err(dev, "%s: Can't find cpu DT node\n", link->name);
+			ret = -EINVAL;
+			goto err;
+		}
+
+		ret = of_parse_phandle_with_args(cpu, "sound-dai",
+						 "#sound-dai-cells", 0, &args);
+		if (ret) {
+			dev_err(card->dev, "%s: error getting cpu phandle\n", link->name);
+			goto err;
+		}
+
+		if (of_node_name_eq(args.np, "sai")) {
+			/* sai sysclk id */
+			link_data->cpu_sysclk_id = FSL_SAI_CLK_MAST1;
+
+			/* sai may support mclk/bclk = 1 */
+			if (of_find_property(np, "fsl,mclk-equal-bclk", NULL))
+				link_data->one2one_ratio = true;
+		}
+
+		link->cpus->of_node = args.np;
+		link->platforms->of_node = link->cpus->of_node;
+		link->id = args.args[0];
+
+		ret = snd_soc_of_get_dai_name(cpu, &link->cpus->dai_name);
+		if (ret) {
+			if (ret != -EPROBE_DEFER)
+				dev_err(card->dev, "%s: error getting cpu dai name: %d\n",
+					link->name, ret);
+			goto err;
+		}
+
+		codec = of_get_child_by_name(np, "codec");
+		if (codec) {
+			ret = snd_soc_of_get_dai_link_codecs(dev, codec, link);
+			if (ret < 0) {
+				if (ret != -EPROBE_DEFER)
+					dev_err(dev, "%s: codec dai not found: %d\n",
+						link->name, ret);
+				goto err;
+			}
+
+			plat_data->num_codecs = link->num_codecs;
+
+			/* Check the akcodec type */
+			if (!strcmp(link->codecs->dai_name, "ak4458-aif"))
+				plat_data->type = CODEC_AK4458;
+			else if (!strcmp(link->codecs->dai_name, "ak4497-aif"))
+				plat_data->type = CODEC_AK4497;
+			else if (!strcmp(link->codecs->dai_name, "ak5558-aif"))
+				plat_data->type = CODEC_AK5558;
+			else if (!strcmp(link->codecs->dai_name, "ak5552-aif"))
+				plat_data->type = CODEC_AK5552;
+
+		} else {
+			dlc = devm_kzalloc(dev, sizeof(*dlc), GFP_KERNEL);
+			if (!dlc) {
+				ret = -ENOMEM;
+				goto err;
+			}
+
+			link->codecs	 = dlc;
+			link->num_codecs = 1;
+
+			link->codecs->dai_name = "snd-soc-dummy-dai";
+			link->codecs->name = "snd-soc-dummy";
+		}
+
+		if (!strncmp(link->name, "HiFi-ASRC-FE", 12)) {
+			/* DPCM frontend */
+			link->dynamic = 1;
+			link->dpcm_merged_chan = 1;
+
+			ret = of_property_read_u32(args.np, "fsl,asrc-rate", &data->asrc_rate);
+			if (ret) {
+				dev_err(dev, "failed to get output rate\n");
+				ret = -EINVAL;
+				goto err;
+			}
+
+			ret = of_property_read_u32(args.np, "fsl,asrc-format", &data->asrc_format);
+			if (ret) {
+				/* Fallback to old binding; translate to asrc_format */
+				ret = of_property_read_u32(args.np, "fsl,asrc-width", &width);
+				if (ret) {
+					dev_err(dev,
+						"failed to decide output format\n");
+					goto err;
+				}
+
+				if (width == 24)
+					data->asrc_format = SNDRV_PCM_FORMAT_S24_LE;
+				else
+					data->asrc_format = SNDRV_PCM_FORMAT_S16_LE;
+			}
+		} else if (!strncmp(link->name, "HiFi-ASRC-BE", 12)) {
+			/* DPCM backend */
+			link->no_pcm = 1;
+			link->platforms->of_node = NULL;
+			link->platforms->name = "snd-soc-dummy";
+
+			link->be_hw_params_fixup = be_hw_params_fixup;
+			link->ops = &imx_aif_ops_be;
+		} else {
+			link->ops = &imx_aif_ops;
+		}
+
+		if (link->no_pcm || link->dynamic)
+			snd_soc_dai_link_set_capabilities(link);
+
+		/* Get dai fmt */
+		ret = asoc_simple_parse_daifmt(dev, np, codec,
+					       NULL, &link->dai_fmt);
+		if (ret)
+			link->dai_fmt = SND_SOC_DAIFMT_NB_NF |
+					SND_SOC_DAIFMT_CBS_CFS |
+					SND_SOC_DAIFMT_I2S;
+
+		/* Get tdm slot */
+		snd_soc_of_parse_tdm_slot(np, NULL, NULL,
+					  &link_data->slots,
+					  &link_data->slot_width);
+		/* default value */
+		if (!link_data->slots)
+			link_data->slots = 2;
+
+		if (!link_data->slot_width)
+			link_data->slot_width = 32;
+
+		link->ignore_pmdown_time = 1;
+		link->stream_name = link->name;
+		link++;
+		link_data++;
+
+		of_node_put(cpu);
+		of_node_put(codec);
+		of_node_put(platform);
+	}
+
+	return 0;
+err:
+	of_node_put(cpu);
+	of_node_put(codec);
+	of_node_put(platform);
+err_put_np:
+	of_node_put(np);
+	return ret;
+}
+
+static int imx_card_probe(struct platform_device *pdev)
+{
+	struct snd_soc_dai_link *link_be = NULL, *link;
+	struct imx_card_plat_data *plat_data;
+	struct imx_card_data *data;
+	int ret, i;
+
+	data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	plat_data = devm_kzalloc(&pdev->dev, sizeof(*plat_data), GFP_KERNEL);
+	if (!plat_data)
+		return -ENOMEM;
+
+	data->plat_data = plat_data;
+	data->card.dev = &pdev->dev;
+
+	dev_set_drvdata(&pdev->dev, &data->card);
+	snd_soc_card_set_drvdata(&data->card, data);
+	ret = imx_card_parse_of(data);
+	if (ret)
+		return ret;
+
+	data->num_dapm_routes = plat_data->num_codecs + 1;
+	data->dapm_routes = devm_kcalloc(&pdev->dev, data->num_dapm_routes,
+					 sizeof(struct snd_soc_dapm_route),
+					 GFP_KERNEL);
+	if (!data->dapm_routes)
+		return -ENOMEM;
+
+	/* configure the dapm routes */
+	switch (plat_data->type) {
+	case CODEC_AK4458:
+	case CODEC_AK4497:
+		if (plat_data->num_codecs == 1) {
+			data->dapm_routes[0].sink = "Playback";
+			data->dapm_routes[0].source = "CPU-Playback";
+			i = 1;
+		} else {
+			for (i = 0; i < plat_data->num_codecs; i++) {
+				data->dapm_routes[i].sink =
+					devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s",
+						       i + 1, "Playback");
+				data->dapm_routes[i].source = "CPU-Playback";
+			}
+		}
+		data->dapm_routes[i].sink = "CPU-Playback";
+		data->dapm_routes[i].source = "ASRC-Playback";
+		break;
+	case CODEC_AK5558:
+	case CODEC_AK5552:
+		if (plat_data->num_codecs == 1) {
+			data->dapm_routes[0].sink = "CPU-Capture";
+			data->dapm_routes[0].source = "Capture";
+			i = 1;
+		} else {
+			for (i = 0; i < plat_data->num_codecs; i++) {
+				data->dapm_routes[i].source =
+					devm_kasprintf(&pdev->dev, GFP_KERNEL, "%d %s",
+						       i + 1, "Capture");
+				data->dapm_routes[i].sink = "CPU-Capture";
+			}
+		}
+		data->dapm_routes[i].sink = "ASRC-Capture";
+		data->dapm_routes[i].source = "CPU-Capture";
+		break;
+	default:
+		break;
+	}
+
+	/* default platform data for akcodecs */
+	if (codec_is_akcodec(plat_data->type)) {
+		plat_data->support_rates = akcodec_rates;
+		plat_data->num_rates = ARRAY_SIZE(akcodec_rates);
+		plat_data->support_tdm_rates = akcodec_tdm_rates;
+		plat_data->num_tdm_rates = ARRAY_SIZE(akcodec_tdm_rates);
+
+		switch (plat_data->type) {
+		case CODEC_AK4458:
+			plat_data->fs_mul = ak4458_fs_mul;
+			plat_data->num_fs_mul = ARRAY_SIZE(ak4458_fs_mul);
+			plat_data->tdm_fs_mul = ak4458_tdm_fs_mul;
+			plat_data->num_tdm_fs_mul = ARRAY_SIZE(ak4458_tdm_fs_mul);
+			plat_data->support_channels = ak4458_channels;
+			plat_data->num_channels = ARRAY_SIZE(ak4458_channels);
+			plat_data->support_tdm_channels = ak4458_tdm_channels;
+			plat_data->num_tdm_channels = ARRAY_SIZE(ak4458_tdm_channels);
+			break;
+		case CODEC_AK4497:
+			plat_data->fs_mul = ak4497_fs_mul;
+			plat_data->num_fs_mul = ARRAY_SIZE(ak4497_fs_mul);
+			plat_data->support_channels = ak4458_channels;
+			plat_data->num_channels = ARRAY_SIZE(ak4458_channels);
+			break;
+		case CODEC_AK5558:
+		case CODEC_AK5552:
+			plat_data->fs_mul = ak5558_fs_mul;
+			plat_data->num_fs_mul = ARRAY_SIZE(ak5558_fs_mul);
+			plat_data->tdm_fs_mul = ak5558_tdm_fs_mul;
+			plat_data->num_tdm_fs_mul = ARRAY_SIZE(ak5558_tdm_fs_mul);
+			plat_data->support_channels = ak5558_channels;
+			plat_data->num_channels = ARRAY_SIZE(ak5558_channels);
+			plat_data->support_tdm_channels = ak5558_tdm_channels;
+			plat_data->num_tdm_channels = ARRAY_SIZE(ak5558_tdm_channels);
+			break;
+		default:
+			break;
+		}
+	}
+
+	/* with asrc as front end */
+	if (data->card.num_links == 3) {
+		data->card.dapm_routes = data->dapm_routes;
+		data->card.num_dapm_routes = data->num_dapm_routes;
+		for_each_card_prelinks(&data->card, i, link) {
+			if (link->no_pcm == 1)
+				link_be = link;
+		}
+		for_each_card_prelinks(&data->card, i, link) {
+			if (link->dynamic == 1 && link_be) {
+				link->dpcm_playback = link_be->dpcm_playback;
+				link->dpcm_capture = link_be->dpcm_capture;
+			}
+		}
+	}
+
+	ret = devm_snd_soc_register_card(&pdev->dev, &data->card);
+	if (ret) {
+		if (ret != -EPROBE_DEFER)
+			dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret);
+		return ret;
+	}
+
+	return 0;
+}
+
+static const struct of_device_id imx_card_dt_ids[] = {
+	{ .compatible = "fsl,imx-audio-card", },
+	{ },
+};
+MODULE_DEVICE_TABLE(of, imx_card_dt_ids);
+
+static struct platform_driver imx_card_driver = {
+	.driver = {
+		.name = "imx-card",
+		.pm = &snd_soc_pm_ops,
+		.of_match_table = imx_card_dt_ids,
+	},
+	.probe = imx_card_probe,
+};
+module_platform_driver(imx_card_driver);
+
+MODULE_DESCRIPTION("Freescale i.MX ASoC Machine Driver");
+MODULE_LICENSE("GPL v2");
+MODULE_ALIAS("platform:imx-card");
-- 
2.27.0


^ permalink raw reply related

* Re: [PATCH v2 2/2] ASoC: dt-bindings: imx-akcodec: Add binding doc for akcodec machine driver
From: Shengjiu Wang @ 2021-05-17 10:39 UTC (permalink / raw)
  To: Rob Herring
  Cc: open list:OPEN FIRMWARE AND FLATTENED DEVICE TREE BINDINGS,
	alsa-devel, Fabio Estevam, linux-kernel, Timur Tabi, Xiubo Li,
	linuxppc-dev, Shengjiu Wang, Takashi Iwai, Liam Girdwood,
	Nicolin Chen, Mark Brown, NXP Linux Team, Sascha Hauer, Shawn Guo,
	Sascha Hauer,
	moderated list:ARM/FREESCALE IMX / MXC ARM ARCHITECTURE
In-Reply-To: <20210511190057.GA2416585@robh.at.kernel.org>

On Thu, May 13, 2021 at 4:07 AM Rob Herring <robh@kernel.org> wrote:
>
> On Mon, May 10, 2021 at 03:07:21PM +0800, Shengjiu Wang wrote:
> > Imx-akcodec is a new added machine driver for supporting
> > ak4458/ak5558/ak5552/ak4497 codec on i.MX platforms.
> >
> > Signed-off-by: Shengjiu Wang <shengjiu.wang@nxp.com>
> > ---
> > changes in v2:
> > - update doc accoring to Rob's comment, use the common porperties.
> >
> >  .../bindings/sound/imx-audio-akcodec.yaml     | 107 ++++++++++++++++++
> >  1 file changed, 107 insertions(+)
> >  create mode 100644 Documentation/devicetree/bindings/sound/imx-audio-akcodec.yaml
> >
> > diff --git a/Documentation/devicetree/bindings/sound/imx-audio-akcodec.yaml b/Documentation/devicetree/bindings/sound/imx-audio-akcodec.yaml
> > new file mode 100644
> > index 000000000000..0812c4779b59
> > --- /dev/null
> > +++ b/Documentation/devicetree/bindings/sound/imx-audio-akcodec.yaml
> > @@ -0,0 +1,107 @@
> > +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
> > +%YAML 1.2
> > +---
> > +$id: http://devicetree.org/schemas/sound/imx-audio-akcodec.yaml#
> > +$schema: http://devicetree.org/meta-schemas/core.yaml#
> > +
> > +title: NXP i.MX audio complex with AK4458/AK5558/AK5552/AK4497 codec
> > +
> > +maintainers:
> > +  - Shengjiu Wang <shengjiu.wang@nxp.com>
> > +
> > +properties:
> > +  compatible:
> > +    enum:
> > +      - fsl,imx8mq-audio-akcodec
> > +      - fsl,imx-audio-akcodec
>
> We gone from individual codecs to a family of codecs. Is there something
> specific for the machine driver about this set of codecs? Why can't it
> be *any* codec?

Yes, there is something specific. but let me do further updates for this in the
next version, then the document name needs to be changed to
"imx-audio-card".

best regards
wang shengjiu

^ permalink raw reply

* [Bug 213069] kernel BUG at arch/powerpc/include/asm/book3s/64/hash-4k.h:147! Oops: Exception in kernel mode, sig: 5 [#1]
From: bugzilla-daemon @ 2021-05-17 10:36 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-213069-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=213069

Michael Ellerman (michael@ellerman.id.au) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
             Status|NEW                         |ASSIGNED
                 CC|                            |michael@ellerman.id.au

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* Re: [FSL P50x0] KVM HV doesn't work anymore
From: Christian Zigotzky @ 2021-05-17  9:42 UTC (permalink / raw)
  To: Nicholas Piggin, Christophe Leroy, kvm-ppc@vger.kernel.org,
	linuxppc-dev
  Cc: Darren Stevens, R.T.Dickinson, mad skateman, Christian Zigotzky
In-Reply-To: <1621236734.xfc1uw04eb.astroid@bobo.none>

On 17 May 2021 at 09:42am, Nicholas Piggin wrote:
> Excerpts from Christian Zigotzky's message of May 15, 2021 11:46 pm:
>> On 15 May 2021 at 12:08pm Christophe Leroy wrote:
>>>
>>> Le 15/05/2021 à 11:48, Christian Zigotzky a écrit :
>>>> Hi All,
>>>>
>>>> I bisected today [1] and the bisecting itself was OK but the
>>>> reverting of the bad commit doesn't solve the issue. Do you have an
>>>> idea which commit could be resposible for this issue? Maybe the
>>>> bisecting wasn't successful. I will look in the kernel git log. Maybe
>>>> there is a commit that affected KVM HV on FSL P50x0 machines.
>>> If the uImage doesn't load, it may be because of the size of uImage.
>>>
>>> See https://github.com/linuxppc/issues/issues/208
>>>
>>> Is there a significant size difference with and without KVM HV ?
>>>
>>> Maybe you can try to remove another option to reduce the size of the
>>> uImage.
>> I tried it but it doesn't solve the issue. The uImage works without KVM
>> HV in a virtual e5500 QEMU machine.
> Any more progress with this? I would say that bisect might have just
> been a bit unstable and maybe by chance some things did not crash so
> it's pointing to the wrong patch.
>
> Upstream merge of powerpc-5.13-1 was good and powerpc-5.13-2 was bad?
>
> Between that looks like some KVM MMU rework. You could try the patch
> before this one b1c5356e873c ("KVM: PPC: Convert to the gfn-based MMU
> notifier callbacks"). That won't revert cleanly so just try run the
> tree at that point. If it works, test the patch and see if it fails.
>
> Thanks,
> Nick
Hi Nick,

Thanks a lot for your answer. Yes, there is a little bit of progress. 
The RC2 of kernel 5.13 successfully boots with -smp 3 in a virtual e5500 
QEMU machine.
-smp 4 doesn't work anymore since the PowerPC updates 5.13-2. I used 
-smp 4 before 5.13 because my FSL P5040 machine has 4 cores.

Could you please post a patch for reverting the commit before 
b1c5356e873c ("KVM: PPC: Convert to the gfn-based MMU notifier callbacks")?

Thanks in advance,

Christian



^ permalink raw reply

* [Bug 206733] i2c i2c-3: i2c-powermac: modalias failure on /uni-n@f8000000/i2c@f8001000/cereal@1c0
From: bugzilla-daemon @ 2021-05-17  9:24 UTC (permalink / raw)
  To: linuxppc-dev
In-Reply-To: <bug-206733-206035@https.bugzilla.kernel.org/>

https://bugzilla.kernel.org/show_bug.cgi?id=206733

Paul Osmialowski (newchief@king.net.pl) changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |newchief@king.net.pl

--- Comment #4 from Paul Osmialowski (newchief@king.net.pl) ---
I've just updated to 5.10.27-gentoo on some old iBook G4, and of course I've
spotted this `i2c-powermac: modalias failure on
/uni-n@f8000000/i2c@f8001000/cereal@1c0` message. It is not worrying now after
I've found Ben's comment. I've also spotted one more error message (Flag
mismatch) that seems new to me, can you also make a judgement if it is also
harmless?:

[...]
[    4.515861] hid-generic 0003:17EF:602E.0001: input,hidraw0: USB HID v1.11
Mouse [USB Optical Mouse] on usb-0001:10:1b.0-1/input0
[    4.660923] input: PowerMac Beep as
/devices/pci0001:10/0001:10:17.0/input/input3
[    4.665549] genirq: Flags mismatch irq 21. 00000001 (i2sbus: i2s-a (tx)) vs.
00000001 (PMac Output)
[...]

-- 
You may reply to this email to add a comment.

You are receiving this mail because:
You are watching the assignee of the bug.

^ permalink raw reply

* [PATCH v2] lockdown, selinux: avoid bogus SELinux lockdown permission checks
From: Ondrej Mosnacek @ 2021-05-17  9:20 UTC (permalink / raw)
  To: linux-security-module, James Morris
  Cc: selinux, netdev, Stephen Smalley, linux-kernel, Steven Rostedt,
	Casey Schaufler, Ingo Molnar, linux-fsdevel, bpf, linuxppc-dev

Commit 59438b46471a ("security,lockdown,selinux: implement SELinux
lockdown") added an implementation of the locked_down LSM hook to
SELinux, with the aim to restrict which domains are allowed to perform
operations that would breach lockdown.

However, in several places the security_locked_down() hook is called in
situations where the current task isn't doing any action that would
directly breach lockdown, leading to SELinux checks that are basically
bogus.

Since in most of these situations converting the callers such that
security_locked_down() is called in a context where the current task
would be meaningful for SELinux is impossible or very non-trivial (and
could lead to TOCTOU issues for the classic Lockdown LSM
implementation), fix this by modifying the hook to accept a struct cred
pointer as argument, where NULL will be interpreted as a request for a
"global", task-independent lockdown decision only. Then modify SELinux
to ignore calls with cred == NULL.

Since most callers will just want to pass current_cred() as the cred
parameter, rename the hook to security_cred_locked_down() and provide
the original security_locked_down() function as a simple wrapper around
the new hook.

The callers migrated to the new hook, passing NULL as cred:
1. arch/powerpc/xmon/xmon.c
     Here the hook seems to be called from non-task context and is only
     used for redacting some sensitive values from output sent to
     userspace.
2. fs/tracefs/inode.c:tracefs_create_file()
     Here the call is used to prevent creating new tracefs entries when
     the kernel is locked down. Assumes that locking down is one-way -
     i.e. if the hook returns non-zero once, it will never return zero
     again, thus no point in creating these files.
3. kernel/trace/bpf_trace.c:bpf_probe_read_kernel{,_str}_common()
     Called when a BPF program calls a helper that could leak kernel
     memory. The task context is not relevant here, since the program
     may very well be run in the context of a different task than the
     consumer of the data.
     See: https://bugzilla.redhat.com/show_bug.cgi?id=1955585
4. net/xfrm/xfrm_user.c:copy_to_user_*()
     Here a cryptographic secret is redacted based on the value returned
     from the hook. There are two possible actions that may lead here:
     a) A netlink message XFRM_MSG_GETSA with NLM_F_DUMP set - here the
        task context is relevant, since the dumped data is sent back to
        the current task.
     b) When deleting an SA via XFRM_MSG_DELSA, the dumped SAs are
        broadcasted to tasks subscribed to XFRM events - here the
        SELinux check is not meningful as the current task's creds do
        not represent the tasks that could potentially see the secret.
     It really doesn't seem worth it to try to preserve the check in the
     a) case, since the eventual leak can be circumvented anyway via b),
     plus there is no way for the task to indicate that it doesn't care
     about the actual key value, so the check could generate a lot of
     noise.

Improvements-suggested-by: Casey Schaufler <casey@schaufler-ca.com>
Fixes: 59438b46471a ("security,lockdown,selinux: implement SELinux lockdown")
Signed-off-by: Ondrej Mosnacek <omosnace@redhat.com>
---

v2:
- change to a single hook based on suggestions by Casey Schaufler

v1: https://lore.kernel.org/lkml/20210507114048.138933-1-omosnace@redhat.com/

 arch/powerpc/xmon/xmon.c      |  4 ++--
 fs/tracefs/inode.c            |  2 +-
 include/linux/lsm_hook_defs.h |  3 ++-
 include/linux/lsm_hooks.h     |  3 ++-
 include/linux/security.h      | 11 ++++++++---
 kernel/trace/bpf_trace.c      |  4 ++--
 net/xfrm/xfrm_user.c          |  2 +-
 security/lockdown/lockdown.c  |  5 +++--
 security/security.c           |  6 +++---
 security/selinux/hooks.c      | 12 +++++++++---
 10 files changed, 33 insertions(+), 19 deletions(-)

diff --git a/arch/powerpc/xmon/xmon.c b/arch/powerpc/xmon/xmon.c
index c8173e92f19d..90992793b4c5 100644
--- a/arch/powerpc/xmon/xmon.c
+++ b/arch/powerpc/xmon/xmon.c
@@ -299,7 +299,7 @@ static bool xmon_is_locked_down(void)
 	static bool lockdown;
 
 	if (!lockdown) {
-		lockdown = !!security_locked_down(LOCKDOWN_XMON_RW);
+		lockdown = !!security_cred_locked_down(NULL, LOCKDOWN_XMON_RW);
 		if (lockdown) {
 			printf("xmon: Disabled due to kernel lockdown\n");
 			xmon_is_ro = true;
@@ -307,7 +307,7 @@ static bool xmon_is_locked_down(void)
 	}
 
 	if (!xmon_is_ro) {
-		xmon_is_ro = !!security_locked_down(LOCKDOWN_XMON_WR);
+		xmon_is_ro = !!security_cred_locked_down(NULL, LOCKDOWN_XMON_WR);
 		if (xmon_is_ro)
 			printf("xmon: Read-only due to kernel lockdown\n");
 	}
diff --git a/fs/tracefs/inode.c b/fs/tracefs/inode.c
index 1261e8b41edb..7edde3fc22f5 100644
--- a/fs/tracefs/inode.c
+++ b/fs/tracefs/inode.c
@@ -396,7 +396,7 @@ struct dentry *tracefs_create_file(const char *name, umode_t mode,
 	struct dentry *dentry;
 	struct inode *inode;
 
-	if (security_locked_down(LOCKDOWN_TRACEFS))
+	if (security_cred_locked_down(NULL, LOCKDOWN_TRACEFS))
 		return NULL;
 
 	if (!(mode & S_IFMT))
diff --git a/include/linux/lsm_hook_defs.h b/include/linux/lsm_hook_defs.h
index 2adeea44c0d5..0115d7e3db55 100644
--- a/include/linux/lsm_hook_defs.h
+++ b/include/linux/lsm_hook_defs.h
@@ -393,7 +393,8 @@ LSM_HOOK(int, 0, bpf_prog_alloc_security, struct bpf_prog_aux *aux)
 LSM_HOOK(void, LSM_RET_VOID, bpf_prog_free_security, struct bpf_prog_aux *aux)
 #endif /* CONFIG_BPF_SYSCALL */
 
-LSM_HOOK(int, 0, locked_down, enum lockdown_reason what)
+LSM_HOOK(int, 0, cred_locked_down, const struct cred *cred,
+	 enum lockdown_reason what)
 
 #ifdef CONFIG_PERF_EVENTS
 LSM_HOOK(int, 0, perf_event_open, struct perf_event_attr *attr, int type)
diff --git a/include/linux/lsm_hooks.h b/include/linux/lsm_hooks.h
index 5c4c5c0602cb..2d2d82ffea34 100644
--- a/include/linux/lsm_hooks.h
+++ b/include/linux/lsm_hooks.h
@@ -1539,10 +1539,11 @@
  * @bpf_prog_free_security:
  *	Clean up the security information stored inside bpf prog.
  *
- * @locked_down:
+ * @cred_locked_down:
  *     Determine whether a kernel feature that potentially enables arbitrary
  *     code execution in kernel space should be permitted.
  *
+ *     @cred: credential asociated with the operation, or NULL if not applicable
  *     @what: kernel feature being accessed
  *
  * Security hooks for perf events
diff --git a/include/linux/security.h b/include/linux/security.h
index 24eda04221e9..6a609787a03a 100644
--- a/include/linux/security.h
+++ b/include/linux/security.h
@@ -26,6 +26,7 @@
 #include <linux/kernel_read_file.h>
 #include <linux/key.h>
 #include <linux/capability.h>
+#include <linux/cred.h>
 #include <linux/fs.h>
 #include <linux/slab.h>
 #include <linux/err.h>
@@ -33,7 +34,6 @@
 #include <linux/mm.h>
 
 struct linux_binprm;
-struct cred;
 struct rlimit;
 struct kernel_siginfo;
 struct sembuf;
@@ -470,7 +470,7 @@ void security_inode_invalidate_secctx(struct inode *inode);
 int security_inode_notifysecctx(struct inode *inode, void *ctx, u32 ctxlen);
 int security_inode_setsecctx(struct dentry *dentry, void *ctx, u32 ctxlen);
 int security_inode_getsecctx(struct inode *inode, void **ctx, u32 *ctxlen);
-int security_locked_down(enum lockdown_reason what);
+int security_cred_locked_down(const struct cred *cred, enum lockdown_reason what);
 #else /* CONFIG_SECURITY */
 
 static inline int call_blocking_lsm_notifier(enum lsm_event event, void *data)
@@ -1343,12 +1343,17 @@ static inline int security_inode_getsecctx(struct inode *inode, void **ctx, u32
 {
 	return -EOPNOTSUPP;
 }
-static inline int security_locked_down(enum lockdown_reason what)
+static inline int security_cred_locked_down(struct cred *cred, enum lockdown_reason what)
 {
 	return 0;
 }
 #endif	/* CONFIG_SECURITY */
 
+static inline int security_locked_down(enum lockdown_reason what)
+{
+	return security_cred_locked_down(current_cred(), what);
+}
+
 #if defined(CONFIG_SECURITY) && defined(CONFIG_WATCH_QUEUE)
 int security_post_notification(const struct cred *w_cred,
 			       const struct cred *cred,
diff --git a/kernel/trace/bpf_trace.c b/kernel/trace/bpf_trace.c
index d2d7cf6cfe83..d8a242837c1e 100644
--- a/kernel/trace/bpf_trace.c
+++ b/kernel/trace/bpf_trace.c
@@ -215,7 +215,7 @@ const struct bpf_func_proto bpf_probe_read_user_str_proto = {
 static __always_inline int
 bpf_probe_read_kernel_common(void *dst, u32 size, const void *unsafe_ptr)
 {
-	int ret = security_locked_down(LOCKDOWN_BPF_READ);
+	int ret = security_cred_locked_down(NULL, LOCKDOWN_BPF_READ);
 
 	if (unlikely(ret < 0))
 		goto fail;
@@ -246,7 +246,7 @@ const struct bpf_func_proto bpf_probe_read_kernel_proto = {
 static __always_inline int
 bpf_probe_read_kernel_str_common(void *dst, u32 size, const void *unsafe_ptr)
 {
-	int ret = security_locked_down(LOCKDOWN_BPF_READ);
+	int ret = security_cred_locked_down(NULL, LOCKDOWN_BPF_READ);
 
 	if (unlikely(ret < 0))
 		goto fail;
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index f0aecee4d539..5f45848c4ff3 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -851,7 +851,7 @@ static int copy_user_offload(struct xfrm_state_offload *xso, struct sk_buff *skb
 static bool xfrm_redact(void)
 {
 	return IS_ENABLED(CONFIG_SECURITY) &&
-		security_locked_down(LOCKDOWN_XFRM_SECRET);
+		security_cred_locked_down(NULL, LOCKDOWN_XFRM_SECRET);
 }
 
 static int copy_to_user_auth(struct xfrm_algo_auth *auth, struct sk_buff *skb)
diff --git a/security/lockdown/lockdown.c b/security/lockdown/lockdown.c
index 87cbdc64d272..2a13c866c22a 100644
--- a/security/lockdown/lockdown.c
+++ b/security/lockdown/lockdown.c
@@ -55,7 +55,8 @@ early_param("lockdown", lockdown_param);
  * lockdown_is_locked_down - Find out if the kernel is locked down
  * @what: Tag to use in notice generated if lockdown is in effect
  */
-static int lockdown_is_locked_down(enum lockdown_reason what)
+static int lockdown_is_locked_down(const struct cred *cred,
+				   enum lockdown_reason what)
 {
 	if (WARN(what >= LOCKDOWN_CONFIDENTIALITY_MAX,
 		 "Invalid lockdown reason"))
@@ -72,7 +73,7 @@ static int lockdown_is_locked_down(enum lockdown_reason what)
 }
 
 static struct security_hook_list lockdown_hooks[] __lsm_ro_after_init = {
-	LSM_HOOK_INIT(locked_down, lockdown_is_locked_down),
+	LSM_HOOK_INIT(cred_locked_down, lockdown_is_locked_down),
 };
 
 static int __init lockdown_lsm_init(void)
diff --git a/security/security.c b/security/security.c
index 0c1c9796e3e4..c987b70bc16c 100644
--- a/security/security.c
+++ b/security/security.c
@@ -2592,11 +2592,11 @@ void security_bpf_prog_free(struct bpf_prog_aux *aux)
 }
 #endif /* CONFIG_BPF_SYSCALL */
 
-int security_locked_down(enum lockdown_reason what)
+int security_cred_locked_down(const struct cred *cred, enum lockdown_reason what)
 {
-	return call_int_hook(locked_down, 0, what);
+	return call_int_hook(cred_locked_down, 0, cred, what);
 }
-EXPORT_SYMBOL(security_locked_down);
+EXPORT_SYMBOL(security_cred_locked_down);
 
 #ifdef CONFIG_PERF_EVENTS
 int security_perf_event_open(struct perf_event_attr *attr, int type)
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index eaea837d89d1..c415e3ca4f24 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -7017,10 +7017,10 @@ static void selinux_bpf_prog_free(struct bpf_prog_aux *aux)
 }
 #endif
 
-static int selinux_lockdown(enum lockdown_reason what)
+static int selinux_lockdown(const struct cred *cred, enum lockdown_reason what)
 {
 	struct common_audit_data ad;
-	u32 sid = current_sid();
+	u32 sid;
 	int invalid_reason = (what <= LOCKDOWN_NONE) ||
 			     (what == LOCKDOWN_INTEGRITY_MAX) ||
 			     (what >= LOCKDOWN_CONFIDENTIALITY_MAX);
@@ -7032,6 +7032,12 @@ static int selinux_lockdown(enum lockdown_reason what)
 		return -EINVAL;
 	}
 
+	/* Ignore if there is no relevant cred to check against */
+	if (!cred)
+		return 0;
+
+	sid = cred_sid(cred);
+
 	ad.type = LSM_AUDIT_DATA_LOCKDOWN;
 	ad.u.reason = what;
 
@@ -7353,7 +7359,7 @@ static struct security_hook_list selinux_hooks[] __lsm_ro_after_init = {
 	LSM_HOOK_INIT(perf_event_write, selinux_perf_event_write),
 #endif
 
-	LSM_HOOK_INIT(locked_down, selinux_lockdown),
+	LSM_HOOK_INIT(cred_locked_down, selinux_lockdown),
 
 	/*
 	 * PUT "CLONING" (ACCESSING + ALLOCATING) HOOKS HERE
-- 
2.31.1


^ permalink raw reply related

* [PATCH v5] pseries/drmem: update LMBs after LPM
From: Laurent Dufour @ 2021-05-17  9:06 UTC (permalink / raw)
  To: mpe, benh, paulus
  Cc: Nathan Lynch, Aneesh Kumar K . V, linuxppc-dev, linux-kernel,
	Tyrel Datwyler

After a LPM, the device tree node ibm,dynamic-reconfiguration-memory may be
updated by the hypervisor in the case the NUMA topology of the LPAR's
memory is updated.

This is handled by the kernel, but the memory's node is not updated because
there is no way to move a memory block between nodes from the Linux kernel
point of view.

If later a memory block is added or removed, drmem_update_dt() is called
and it is overwriting the DT node ibm,dynamic-reconfiguration-memory to
match the added or removed LMB. But the LMB's associativity node has not
been updated after the DT node update and thus the node is overwritten by
the Linux's topology instead of the hypervisor one.

Introduce a hook called when the ibm,dynamic-reconfiguration-memory node is
updated to force an update of the LMB's associativity. However, ignore the
call to that hook when the update has been triggered by drmem_update_dt().
Because, in that case, the LMB tree has been used to set the DT property
and thus it doesn't need to be updated back. Since drmem_update_dt() is
called under the protection of the device_hotplug_lock and the hook is
called in the same context, use a simple boolean variable to detect that
call.

Cc: Nathan Lynch <nathanl@linux.ibm.com>
Cc: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
Cc: Tyrel Datwyler <tyreld@linux.ibm.com>
Signed-off-by: Laurent Dufour <ldufour@linux.ibm.com>
---

V5:
 - Reword the commit's description to address Nathan's comments.
V4:
 - Prevent the LMB to be updated back in the case the request came from the
 LMB tree's update.
V3:
 - Check rd->dn->name instead of rd->dn->full_name
V2:
 - Take Tyrel's idea to rely on OF_RECONFIG_UPDATE_PROPERTY instead of
 introducing a new hook mechanism.
---
 arch/powerpc/include/asm/drmem.h              |  1 +
 arch/powerpc/mm/drmem.c                       | 46 +++++++++++++++++++
 .../platforms/pseries/hotplug-memory.c        |  4 ++
 3 files changed, 51 insertions(+)

diff --git a/arch/powerpc/include/asm/drmem.h b/arch/powerpc/include/asm/drmem.h
index bf2402fed3e0..4265d5e95c2c 100644
--- a/arch/powerpc/include/asm/drmem.h
+++ b/arch/powerpc/include/asm/drmem.h
@@ -111,6 +111,7 @@ int drmem_update_dt(void);
 int __init
 walk_drmem_lmbs_early(unsigned long node, void *data,
 		      int (*func)(struct drmem_lmb *, const __be32 **, void *));
+void drmem_update_lmbs(struct property *prop);
 #endif
 
 static inline void invalidate_lmb_associativity_index(struct drmem_lmb *lmb)
diff --git a/arch/powerpc/mm/drmem.c b/arch/powerpc/mm/drmem.c
index 9af3832c9d8d..22197b18d85e 100644
--- a/arch/powerpc/mm/drmem.c
+++ b/arch/powerpc/mm/drmem.c
@@ -18,6 +18,7 @@ static int n_root_addr_cells, n_root_size_cells;
 
 static struct drmem_lmb_info __drmem_info;
 struct drmem_lmb_info *drmem_info = &__drmem_info;
+static bool in_drmem_update;
 
 u64 drmem_lmb_memory_max(void)
 {
@@ -178,6 +179,11 @@ int drmem_update_dt(void)
 	if (!memory)
 		return -1;
 
+	/*
+	 * Set in_drmem_update to prevent the notifier callback to process the
+	 * DT property back since the change is coming from the LMB tree.
+	 */
+	in_drmem_update = true;
 	prop = of_find_property(memory, "ibm,dynamic-memory", NULL);
 	if (prop) {
 		rc = drmem_update_dt_v1(memory, prop);
@@ -186,6 +192,7 @@ int drmem_update_dt(void)
 		if (prop)
 			rc = drmem_update_dt_v2(memory, prop);
 	}
+	in_drmem_update = false;
 
 	of_node_put(memory);
 	return rc;
@@ -307,6 +314,45 @@ int __init walk_drmem_lmbs_early(unsigned long node, void *data,
 	return ret;
 }
 
+/*
+ * Update the LMB associativity index.
+ */
+static int update_lmb(struct drmem_lmb *updated_lmb,
+		      __maybe_unused const __be32 **usm,
+		      __maybe_unused void *data)
+{
+	struct drmem_lmb *lmb;
+
+	for_each_drmem_lmb(lmb) {
+		if (lmb->drc_index != updated_lmb->drc_index)
+			continue;
+
+		lmb->aa_index = updated_lmb->aa_index;
+		break;
+	}
+	return 0;
+}
+
+/*
+ * Update the LMB associativity index.
+ *
+ * This needs to be called when the hypervisor is updating the
+ * dynamic-reconfiguration-memory node property.
+ */
+void drmem_update_lmbs(struct property *prop)
+{
+	/*
+	 * Don't update the LMBs if triggered by the update done in
+	 * drmem_update_dt(), the LMB values have been used to the update the DT
+	 * property in that case.
+	 */
+	if (in_drmem_update)
+		return;
+	if (!strcmp(prop->name, "ibm,dynamic-memory"))
+		__walk_drmem_v1_lmbs(prop->value, NULL, NULL, update_lmb);
+	else if (!strcmp(prop->name, "ibm,dynamic-memory-v2"))
+		__walk_drmem_v2_lmbs(prop->value, NULL, NULL, update_lmb);
+}
 #endif
 
 static int init_drmem_lmb_size(struct device_node *dn)
diff --git a/arch/powerpc/platforms/pseries/hotplug-memory.c b/arch/powerpc/platforms/pseries/hotplug-memory.c
index 8377f1f7c78e..672ffbee2e78 100644
--- a/arch/powerpc/platforms/pseries/hotplug-memory.c
+++ b/arch/powerpc/platforms/pseries/hotplug-memory.c
@@ -949,6 +949,10 @@ static int pseries_memory_notifier(struct notifier_block *nb,
 	case OF_RECONFIG_DETACH_NODE:
 		err = pseries_remove_mem_node(rd->dn);
 		break;
+	case OF_RECONFIG_UPDATE_PROPERTY:
+		if (!strcmp(rd->dn->name,
+			    "ibm,dynamic-reconfiguration-memory"))
+			drmem_update_lmbs(rd->prop);
 	}
 	return notifier_from_errno(err);
 }
-- 
2.31.1


^ permalink raw reply related

* Re: [PATCH v5 5/9] powerpc/mm/book3s64: Update tlb flush routines to take a page walk cache flush argument
From: Aneesh Kumar K.V @ 2021-05-17  8:40 UTC (permalink / raw)
  To: Guenter Roeck; +Cc: npiggin, linux-mm, kaleshsingh, joel, akpm, linuxppc-dev
In-Reply-To: <20210515163525.GA1106462@roeck-us.net>

On 5/15/21 10:05 PM, Guenter Roeck wrote:
> On Thu, Apr 22, 2021 at 11:13:19AM +0530, Aneesh Kumar K.V wrote:
>> No functional change in this patch
>>
>> Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.ibm.com>
>> ---
>>   .../include/asm/book3s/64/tlbflush-radix.h    | 19 +++++++-----
>>   arch/powerpc/include/asm/book3s/64/tlbflush.h | 23 ++++++++++++---
>>   arch/powerpc/mm/book3s64/radix_hugetlbpage.c  |  4 +--
>>   arch/powerpc/mm/book3s64/radix_tlb.c          | 29 +++++++------------
>>   4 files changed, 42 insertions(+), 33 deletions(-)
>>
>> diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
>> index 8b33601cdb9d..171441a43b35 100644
>> --- a/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
>> +++ b/arch/powerpc/include/asm/book3s/64/tlbflush-radix.h
>> @@ -56,15 +56,18 @@ static inline void radix__flush_all_lpid_guest(unsigned int lpid)
>>   }
>>   #endif
>>   
>> -extern void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma,
>> -					   unsigned long start, unsigned long end);
>> -extern void radix__flush_tlb_range_psize(struct mm_struct *mm, unsigned long start,
>> -					 unsigned long end, int psize);
>> -extern void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
>> -				       unsigned long start, unsigned long end);
>> -extern void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
>> +void radix__flush_hugetlb_tlb_range(struct vm_area_struct *vma,
>> +				    unsigned long start, unsigned long end,
>> +				    bool flush_pwc);
>> +void radix__flush_pmd_tlb_range(struct vm_area_struct *vma,
>> +				unsigned long start, unsigned long end,
>> +				bool flush_pwc);
>> +void radix__flush_tlb_pwc_range_psize(struct mm_struct *mm, unsigned long start,
>> +				      unsigned long end, int psize, bool flush_pwc);
>> +void radix__flush_tlb_range(struct vm_area_struct *vma, unsigned long start,
>>   			    unsigned long end);
>> -extern void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end);
>> +void radix__flush_tlb_kernel_range(unsigned long start, unsigned long end);
>> +
>>   
>>   extern void radix__local_flush_tlb_mm(struct mm_struct *mm);
>>   extern void radix__local_flush_all_mm(struct mm_struct *mm);
>> diff --git a/arch/powerpc/include/asm/book3s/64/tlbflush.h b/arch/powerpc/include/asm/book3s/64/tlbflush.h
>> index 215973b4cb26..f9f8a3a264f7 100644
>> --- a/arch/powerpc/include/asm/book3s/64/tlbflush.h
>> +++ b/arch/powerpc/include/asm/book3s/64/tlbflush.h
>> @@ -45,13 +45,30 @@ static inline void tlbiel_all_lpid(bool radix)
>>   		hash__tlbiel_all(TLB_INVAL_SCOPE_LPID);
>>   }
>>   
>> +static inline void flush_pmd_tlb_pwc_range(struct vm_area_struct *vma,
>                   ^^^^
>> +					   unsigned long start,
>> +					   unsigned long end,
>> +					   bool flush_pwc)
>> +{
>> +	if (radix_enabled())
>> +		return radix__flush_pmd_tlb_range(vma, start, end, flush_pwc);
>> +	return hash__flush_tlb_range(vma, start, end);
>          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
>> +}

In this specific case we won't have  build errors because,

static inline void hash__flush_tlb_range(struct vm_area_struct *vma,
				     unsigned long start, unsigned long end)
{


But I agree the below is better to read.

static inline void flush_pmd_tlb_pwc_range(struct vm_area_struct *vma,
					   unsigned long start,
					   unsigned long end,
					   bool flush_pwc)
{
	if (radix_enabled())
		radix__flush_pmd_tlb_range(vma, start, end, flush_pwc);
	else
		hash__flush_tlb_range(vma, start, end);
	return
}

> 
>>   
>>   #define __HAVE_ARCH_FLUSH_PMD_TLB_RANGE
>>   static inline void flush_pmd_tlb_range(struct vm_area_struct *vma,
>                   ^^^^
>>   				       unsigned long start, unsigned long end)
>> +{
>> +	return flush_pmd_tlb_pwc_range(vma, start, end, false);
>          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> 
> Doesn't that cause build warnings/errors all over the place ?
> 
> Guenter
> 


-aneesh

^ permalink raw reply

* Re: [PATCH] lockdown, selinux: fix bogus SELinux lockdown permission checks
From: Ondrej Mosnacek @ 2021-05-17  8:34 UTC (permalink / raw)
  To: Casey Schaufler
  Cc: SElinux list, network dev, Stephen Smalley, James Morris,
	Steven Rostedt, Linux kernel mailing list,
	Linux Security Module list, Ingo Molnar, Linux FS Devel, bpf,
	linuxppc-dev
In-Reply-To: <94486043-322f-74bd-dc33-83e43b531068@schaufler-ca.com>

On Sat, May 15, 2021 at 2:57 AM Casey Schaufler <casey@schaufler-ca.com> wrote:
> On 5/14/2021 8:12 AM, Ondrej Mosnacek wrote:
> > On Wed, May 12, 2021 at 7:12 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> >> On 5/12/2021 9:44 AM, Ondrej Mosnacek wrote:
> >>> On Wed, May 12, 2021 at 6:18 PM Casey Schaufler <casey@schaufler-ca.com> wrote:
> >>>> On 5/12/2021 6:21 AM, Ondrej Mosnacek wrote:
> >>>>> On Sat, May 8, 2021 at 12:17 AM Casey Schaufler <casey@schaufler-ca.com> wrote:
> >>>>>> On 5/7/2021 4:40 AM, Ondrej Mosnacek wrote:
> >>>>>>> Commit 59438b46471a ("security,lockdown,selinux: implement SELinux
> >>>>>>> lockdown") added an implementation of the locked_down LSM hook to
> >>>>>>> SELinux, with the aim to restrict which domains are allowed to perform
> >>>>>>> operations that would breach lockdown.
> >>>>>>>
> >>>>>>> However, in several places the security_locked_down() hook is called in
> >>>>>>> situations where the current task isn't doing any action that would
> >>>>>>> directly breach lockdown, leading to SELinux checks that are basically
> >>>>>>> bogus.
> >>>>>>>
> >>>>>>> Since in most of these situations converting the callers such that
> >>>>>>> security_locked_down() is called in a context where the current task
> >>>>>>> would be meaningful for SELinux is impossible or very non-trivial (and
> >>>>>>> could lead to TOCTOU issues for the classic Lockdown LSM
> >>>>>>> implementation), fix this by adding a separate hook
> >>>>>>> security_locked_down_globally()
> >>>>>> This is a poor solution to the stated problem. Rather than adding
> >>>>>> a new hook you should add the task as a parameter to the existing hook
> >>>>>> and let the security modules do as they will based on its value.
> >>>>>> If the caller does not have an appropriate task it should pass NULL.
> >>>>>> The lockdown LSM can ignore the task value and SELinux can make its
> >>>>>> own decision based on the task value passed.
> >>>>> The problem with that approach is that all callers would then need to
> >>>>> be updated and I intended to keep the patch small as I'd like it to go
> >>>>> to stable kernels as well.
> >>>>>
> >>>>> But it does seem to be a better long-term solution - would it work for
> >>>>> you (and whichever maintainer would be taking the patch(es)) if I just
> >>>>> added another patch that refactors it to use the task parameter?
> >>>> I can't figure out what you're suggesting. Are you saying that you
> >>>> want to add a new hook *and* add the task parameter?
> >>> No, just to keep this patch as-is (and let it go to stable in this
> >>> form) and post another (non-stable) patch on top of it that undoes the
> >>> new hook and re-implements the fix using your suggestion. (Yeah, it'll
> >>> look weird, but I'm not sure how better to handle such situation - I'm
> >>> open to doing it whatever different way the maintainers prefer.)
> >> James gets to make the call on this one. If it was my call I would
> >> tell you to make the task parameter change and accept the backport
> >> pain. I think that as a security developer community we spend way too
> >> much time and effort trying to avoid being noticed in source trees.
> > Hm... actually, what about this attached patch? It switches to a
> > single hook with a cred argument (I figured cred makes more sense than
> > task_struct, since the rest of task_struct should be irrelevant for
> > the LSM, anyway...) right from the start and keeps the original
> > security_locked_down() function only as a simple wrapper around the
> > main hook.
> >
> > At that point I think converting the other callers to call
> > security_cred_locked_down() directly isn't really worth it, since the
> > resulting calls would just be more verbose without much benefit. So
> > I'm tempted to just leave the security_locked_down() helper as is, so
> > that the more common pattern can be still achieved with a simpler
> > call.
> >
> > What do you think?
>
> It's still a bit kludgy, but a big improvement over the previous version.
> I wouldn't object to this approach.

Ok, thanks. I'll post it as a v2 then.

-- 
Ondrej Mosnacek
Software Engineer, Linux Security - SELinux kernel
Red Hat, Inc.


^ permalink raw reply

* [PATCH 0/9] tty: hvc_console: Fix some coding style issues
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm

Fix some issues reported by checkpatch.pl. All of them are
coding style issues, no function changes.

Xiaofei Tan (9):
  tty: hvc_console: Fix spaces required around that '='
  tty: hvc_console: Fix "foo * bar" should be "foo *bar"
  tty: hvc_console: Remove trailing whitespace
  tty: hvc_console: Fix issues of code indent should use tabs
  tty: hvc_console: Delete spaces prohibited around open parenthesis '('
    and ')'
  tty: hvc_console: Fix coding style issues of block comments
  tty: hvc_console: Add a blank line after declarations
  tty: hvc_console: Remove the repeated words 'no' and 'from'
  tty: hvc_console: Move open brace { on the previous line

 drivers/tty/hvc/hvc_console.c | 37 ++++++++++++++++++++++---------------
 1 file changed, 22 insertions(+), 15 deletions(-)

-- 
2.8.1


^ permalink raw reply

* [PATCH 5/9] tty: hvc_console: Delete spaces prohibited around open parenthesis '(' and ')'
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Delete spaces prohibited after that open parenthesis '(' and
before that close parenthesis ')', reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 2e5c133..39018e5 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -689,7 +689,7 @@ static int __hvc_poll(struct hvc_struct *hp, bool may_sleep)
 			spin_unlock_irqrestore(&hp->lock, flags);
 			tty_hangup(tty);
 			spin_lock_irqsave(&hp->lock, flags);
-		} else if ( n == -EAGAIN ) {
+		} else if (n == -EAGAIN) {
 			/*
 			 * Some back-ends can only ensure a certain min
 			 * num of bytes read, which may be > 'count'.
-- 
2.8.1


^ permalink raw reply related

* [PATCH 7/9] tty: hvc_console: Add a blank line after declarations
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Add a blank line after declarations, reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index a61cdf0..f31efeb 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -922,6 +922,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
 	/* We wait until a driver actually comes along */
 	if (atomic_inc_not_zero(&hvc_needs_init)) {
 		int err = hvc_init();
+
 		if (err)
 			return ERR_PTR(err);
 	}
-- 
2.8.1


^ permalink raw reply related

* [PATCH 2/9] tty: hvc_console: Fix "foo * bar" should be "foo *bar"
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Fix "foo * bar" should be "foo *bar", reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index a1eca9d..ddf07ff 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -344,7 +344,7 @@ static int hvc_install(struct tty_driver *driver, struct tty_struct *tty)
  * The TTY interface won't be used until after the vio layer has exposed the vty
  * adapter to the kernel.
  */
-static int hvc_open(struct tty_struct *tty, struct file * filp)
+static int hvc_open(struct tty_struct *tty, struct file *filp)
 {
 	struct hvc_struct *hp = tty->driver_data;
 	unsigned long flags;
@@ -386,7 +386,7 @@ static int hvc_open(struct tty_struct *tty, struct file * filp)
 	return rc;
 }
 
-static void hvc_close(struct tty_struct *tty, struct file * filp)
+static void hvc_close(struct tty_struct *tty, struct file *filp)
 {
 	struct hvc_struct *hp = tty->driver_data;
 	unsigned long flags;
-- 
2.8.1


^ permalink raw reply related

* [PATCH 8/9] tty: hvc_console: Remove the repeated words 'no' and 'from'
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Remove the repeated words 'no' and 'from', reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index f31efeb..b6720b0 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -293,7 +293,7 @@ int hvc_instantiate(uint32_t vtermno, int index, const struct hv_ops *ops)
 	if (vtermnos[index] != -1)
 		return -1;
 
-	/* make sure no no tty has been registered in this index */
+	/* make sure no tty has been registered in this index */
 	hp = hvc_get_by_index(index);
 	if (hp) {
 		tty_port_put(&hp->port);
@@ -622,7 +622,7 @@ static u32 timeout = MIN_TIMEOUT;
 /*
  * Maximum number of bytes to get from the console driver if hvc_poll is
  * called from driver (and can't sleep). Any more than this and we break
- * and start polling with khvcd. This value was derived from from an OpenBMC
+ * and start polling with khvcd. This value was derived from an OpenBMC
  * console with the OPAL driver that results in about 0.25ms interrupts off
  * latency.
  */
-- 
2.8.1


^ permalink raw reply related

* [PATCH 3/9] tty: hvc_console: Remove trailing whitespace
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Remove trailing whitespace, reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index ddf07ff..13f63d5 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -204,7 +204,7 @@ static struct tty_driver *hvc_console_device(struct console *c, int *index)
 }
 
 static int hvc_console_setup(struct console *co, char *options)
-{	
+{
 	if (co->index < 0 || co->index >= MAX_NR_HVC_CONSOLES)
 		return -ENODEV;
 
-- 
2.8.1


^ permalink raw reply related

* [PATCH 6/9] tty: hvc_console: Fix coding style issues of block comments
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Fix coding style issues of block comments, reported by checkpatch.pl.
Besides, add a period at the end of the sentenses.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 39018e5..a61cdf0 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -177,7 +177,8 @@ static void hvc_console_print(struct console *co, const char *b,
 			r = cons_ops[index]->put_chars(vtermnos[index], c, i);
 			if (r <= 0) {
 				/* throw away characters on error
-				 * but spin in case of -EAGAIN */
+				 * but spin in case of -EAGAIN.
+				 */
 				if (r != -EAGAIN) {
 					i = 0;
 				} else {
@@ -484,7 +485,8 @@ static int hvc_push(struct hvc_struct *hp)
 			return 0;
 		}
 		/* throw away output on error; this happens when
-		   there is no session connected to the vterm. */
+		 *  there is no session connected to the vterm.
+		 */
 		hp->n_outbuf = 0;
 	} else
 		hp->n_outbuf -= n;
@@ -707,7 +709,8 @@ static int __hvc_poll(struct hvc_struct *hp, bool may_sleep)
 			/* XXX should support a sequence */
 			if (buf[i] == '\x0f') {	/* ^O */
 				/* if ^O is pressed again, reset
-				 * sysrq_pressed and flip ^O char */
+				 * sysrq_pressed and flip ^O char.
+				 */
 				sysrq_pressed = !sysrq_pressed;
 				if (sysrq_pressed)
 					continue;
@@ -749,7 +752,8 @@ static int __hvc_poll(struct hvc_struct *hp, bool may_sleep)
 
 	if (read_total) {
 		/* Activity is occurring, so reset the polling backoff value to
-		   a minimum for performance. */
+		 * a minimum for performance.
+		 */
 		timeout = MIN_TIMEOUT;
 
 		tty_flip_buffer_push(&hp->port);
@@ -1037,7 +1041,8 @@ static int hvc_init(void)
 	tty_set_operations(drv, &hvc_ops);
 
 	/* Always start the kthread because there can be hotplug vty adapters
-	 * added later. */
+	 * added later.
+	 */
 	hvc_task = kthread_run(khvcd, NULL, "khvcd");
 	if (IS_ERR(hvc_task)) {
 		printk(KERN_ERR "Couldn't create kthread for console.\n");
-- 
2.8.1


^ permalink raw reply related

* [PATCH 1/9] tty: hvc_console: Fix spaces required around that '='
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Fix spaces required around that '=', reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index d0f0253..a1eca9d 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -944,7 +944,7 @@ struct hvc_struct *hvc_alloc(uint32_t vtermno, int data,
 	 * find index to use:
 	 * see if this vterm id matches one registered for console.
 	 */
-	for (i=0; i < MAX_NR_HVC_CONSOLES; i++)
+	for (i = 0; i < MAX_NR_HVC_CONSOLES; i++)
 		if (vtermnos[i] == hp->vtermno &&
 		    cons_ops[i] == hp->ops)
 			break;
-- 
2.8.1


^ permalink raw reply related

* [PATCH 4/9] tty: hvc_console: Fix issues of code indent should use tabs
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Fix issues of code indent should use tabs, reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index 13f63d5..2e5c133 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -268,7 +268,7 @@ static void hvc_check_console(int index)
 	if (hvc_console.flags & CON_ENABLED)
 		return;
 
- 	/* If this index is what the user requested, then register
+	/* If this index is what the user requested, then register
 	 * now (setup won't fail at this point).  It's ok to just
 	 * call register again if previously .setup failed.
 	 */
-- 
2.8.1


^ permalink raw reply related

* [PATCH 9/9] tty: hvc_console: Move open brace { on the previous line
From: Xiaofei Tan @ 2021-05-17  6:37 UTC (permalink / raw)
  To: gregkh, jirislaby; +Cc: Xiaofei Tan, linuxppc-dev, linux-kernel, linuxarm
In-Reply-To: <1621233433-27094-1-git-send-email-tanxiaofei@huawei.com>

Fix issues that open brace { should be on the previous line,
reported by checkpatch.pl.

Signed-off-by: Xiaofei Tan <tanxiaofei@huawei.com>
---
 drivers/tty/hvc/hvc_console.c | 5 +++--
 1 file changed, 3 insertions(+), 2 deletions(-)

diff --git a/drivers/tty/hvc/hvc_console.c b/drivers/tty/hvc/hvc_console.c
index b6720b0..b96399e 100644
--- a/drivers/tty/hvc/hvc_console.c
+++ b/drivers/tty/hvc/hvc_console.c
@@ -140,8 +140,9 @@ static int hvc_flush(struct hvc_struct *hp)
  * static because kmalloc will not work during early console init.
  */
 static const struct hv_ops *cons_ops[MAX_NR_HVC_CONSOLES];
-static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] =
-	{[0 ... MAX_NR_HVC_CONSOLES - 1] = -1};
+static uint32_t vtermnos[MAX_NR_HVC_CONSOLES] = {
+	[0 ... MAX_NR_HVC_CONSOLES - 1] = -1
+};
 
 /*
  * Console APIs, NOT TTY.  These APIs are available immediately when
-- 
2.8.1


^ permalink raw reply related

* Re: Fwd: [Bug 213069] New: kernel BUG at arch/powerpc/include/asm/book3s/64/hash-4k.h:147! Oops: Exception in kernel mode, sig: 5 [#1]
From: Aneesh Kumar K.V @ 2021-05-17  7:44 UTC (permalink / raw)
  To: Anshuman Khandual, Christophe Leroy,
	linuxppc-dev@lists.ozlabs.org
In-Reply-To: <c6372bac-c8c4-6f67-45e9-4deb062d303e@arm.com>

On 5/17/21 12:55 PM, Anshuman Khandual wrote:
> 
> 
> On 5/17/21 11:25 AM, Aneesh Kumar K.V wrote:
>> On 5/17/21 11:17 AM, Christophe Leroy wrote:
>>> +aneesh
>>> +linuxppc-dev list
>>>
>>> Le 17/05/2021 à 07:44, Anshuman Khandual a écrit :
>>>> Hello Christophe,
>>>>
>>>> DEBUG_VM_PGTABLE has now been re-enabled on powerpc recently ? was not
>>>> aware about this. From the error log, it failed explicitly on 4K page
>>>> size hash config.
>>>>
>>>> static inline pmd_t hash__pmd_mkhuge(pmd_t pmd)
>>>> {
>>>>           BUG();        ------> Failed
>>>>           return pmd;
>>>> }
>>>>
>>>> static inline pmd_t __pmd_mkhuge(pmd_t pmd)
>>>> {
>>>>           if (radix_enabled())
>>>>                   return radix__pmd_mkhuge(pmd);
>>>>           return hash__pmd_mkhuge(pmd);
>>>> }
>>>>
>>>> pmd_t pfn_pmd(unsigned long pfn, pgprot_t pgprot)
>>>> {
>>>>           unsigned long pmdv;
>>>>
>>>>           pmdv = (pfn << PAGE_SHIFT) & PTE_RPN_MASK;
>>>>
>>>>           return __pmd_mkhuge(pmd_set_protbits(__pmd(pmdv), pgprot));
>>>> }
>>>>
>>>> It seems like on powerpc, where pfn_pmd() makes a huge page but which
>>>> is not supported on 4K hash config thus triggering the BUG(). But all
>>>> pfn_pmd() call sites inside the debug_vm_pgtable() test are protected
>>>> with CONFIG_TRANSPARENT_HUGEPAGE. IIUC unlike powerpc, pfn_pmd() does
>>>> not directly make a huge page on other platforms.
>>>>
>>>> Looking at arch/powerpc/include/asm/book3s/64/hash-4k.h, all relevant
>>>> THP helpers has BUG() or 0 which indicates THP might not be supported
>>>> on 4K page size hash config ?
>>>>
>>>> But looking at arch/powerpc/platforms/Kconfig.cputype, it seems like
>>>> HAVE_ARCH_TRANSPARENT_HUGEPAGE is invariably selected on PPC_BOOK3S_64
>>>> platforms which I assume includes 4K page size hash config as well.
>>>>
>>>> Is THP some how getting enabled on this 4K page size hash config where
>>>> it should not be (thus triggering the BUG) ? OR am I missing something
>>>> here.
>>>>
>>>
>>
>> We should put those  pfn_pmd()  and pfn_pud() after
>>
>>      if (!has_transparent_hugepage())
>>          return;
>>
>>
>> On hash with 4K page size, we can't support leaf page table entry and PMD and PUD level. Hence we don't support THP for them.
> 
> But could CONFIG_TRANSPARENT_HUGEPAGE be enabled on such configs ?
> Otherwise, wondering how the BUG() just got triggered there.
> 

yes. We do support THP with radix translation and 4K page size.

-aneesh

^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox