From 04052a318fb93491f1f3b4d282cb806f588e9326 Mon Sep 17 00:00:00 2001 From: Alex Shi Date: Fri, 6 Nov 2020 16:10:37 +0800 Subject: [PATCH 0001/1091] net/ieee802154: remove unused macros to tame gcc Signed-off-by: Alex Shi Cc: Alexander Aring Cc: Stefan Schmidt Cc: "David S. Miller" Cc: Jakub Kicinski Cc: linux-wpan@vger.kernel.org Cc: netdev@vger.kernel.org Cc: linux-kernel@vger.kernel.org Link: https://lore.kernel.org/r/1604650237-22192-1-git-send-email-alex.shi@linux.alibaba.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 7c5a1aa5adb4..1cebdcedc48c 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -2098,11 +2098,7 @@ static int nl802154_del_llsec_seclevel(struct sk_buff *skb, #define NL802154_FLAG_NEED_NETDEV 0x02 #define NL802154_FLAG_NEED_RTNL 0x04 #define NL802154_FLAG_CHECK_NETDEV_UP 0x08 -#define NL802154_FLAG_NEED_NETDEV_UP (NL802154_FLAG_NEED_NETDEV |\ - NL802154_FLAG_CHECK_NETDEV_UP) #define NL802154_FLAG_NEED_WPAN_DEV 0x10 -#define NL802154_FLAG_NEED_WPAN_DEV_UP (NL802154_FLAG_NEED_WPAN_DEV |\ - NL802154_FLAG_CHECK_NETDEV_UP) static int nl802154_pre_doit(const struct genl_ops *ops, struct sk_buff *skb, struct genl_info *info) From 443f0bb8e29fa031ec4d5beb3c3143350438dc97 Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Fri, 12 Feb 2021 11:07:31 -0800 Subject: [PATCH 0002/1091] Revert "ARM: dts: bcm2711: Add the BSC interrupt controller" As Dave reported: This seems to have unintended side effects. GIC interrupt 117 is shared between the standard I2C controllers (i2c-bcm2835) and the l2-intc block handling the HDMI I2C interrupts. There is not a great way to share an interrupt between an interrupt controller using the chained IRQ handler which is an interrupt flow and another driver like i2c-bcm2835 which uses an interrupt handler (although it specifies IRQF_SHARED). Simply revert this change for now which will mean that HDMI I2C will be polled, like it was before. Reported-by: Dave Stevenson Acked-by: Maxime Ripard Acked-by: Nicolas Saenz Julienne Signed-off-by: Florian Fainelli --- arch/arm/boot/dts/bcm2711.dtsi | 12 ------------ 1 file changed, 12 deletions(-) diff --git a/arch/arm/boot/dts/bcm2711.dtsi b/arch/arm/boot/dts/bcm2711.dtsi index 462b1dfb0385..720beec54d61 100644 --- a/arch/arm/boot/dts/bcm2711.dtsi +++ b/arch/arm/boot/dts/bcm2711.dtsi @@ -308,14 +308,6 @@ #reset-cells = <1>; }; - bsc_intr: interrupt-controller@7ef00040 { - compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; - reg = <0x7ef00040 0x30>; - interrupts = ; - interrupt-controller; - #interrupt-cells = <1>; - }; - aon_intr: interrupt-controller@7ef00100 { compatible = "brcm,bcm2711-l2-intc", "brcm,l2-intc"; reg = <0x7ef00100 0x30>; @@ -362,8 +354,6 @@ reg = <0x7ef04500 0x100>, <0x7ef00b00 0x300>; reg-names = "bsc", "auto-i2c"; clock-frequency = <97500>; - interrupt-parent = <&bsc_intr>; - interrupts = <0>; status = "disabled"; }; @@ -405,8 +395,6 @@ reg = <0x7ef09500 0x100>, <0x7ef05b00 0x300>; reg-names = "bsc", "auto-i2c"; clock-frequency = <97500>; - interrupt-parent = <&bsc_intr>; - interrupts = <1>; status = "disabled"; }; }; From 7fb08871c38ba9e871d20d64f3a27409baf7b754 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 22 Feb 2021 17:00:56 +0800 Subject: [PATCH 0003/1091] ASoC: rt1015: fix i2c communication error Remove 0x100 cache re-sync to solve i2c communication error. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20210222090057.29532-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 37b5795b00d1..90767490af82 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -209,6 +209,7 @@ static bool rt1015_volatile_register(struct device *dev, unsigned int reg) case RT1015_VENDOR_ID: case RT1015_DEVICE_ID: case RT1015_PRO_ALT: + case RT1015_MAN_I2C: case RT1015_DAC3: case RT1015_VBAT_TEST_OUT1: case RT1015_VBAT_TEST_OUT2: From 2979ef760e73e2a1a34cd4da5d2c78371dfe1028 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 22 Feb 2021 17:00:57 +0800 Subject: [PATCH 0004/1091] ASoC: rt1015: enable BCLK detection after calibration Enable BCLK detection after calibration. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20210222090057.29532-2-jack.yu@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 90767490af82..844e4079d176 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -514,6 +514,7 @@ static void rt1015_calibrate(struct rt1015_priv *rt1015) msleep(300); regmap_write(regmap, RT1015_PWR_STATE_CTRL, 0x0008); regmap_write(regmap, RT1015_SYS_RST1, 0x05F5); + regmap_write(regmap, RT1015_CLK_DET, 0x8000); regcache_cache_bypass(regmap, false); regcache_mark_dirty(regmap); From 2d003ec15396cc8ffa2a887605c98a967de3078d Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 15 Feb 2021 16:33:13 +0000 Subject: [PATCH 0005/1091] ASoC: codecs: lpass-rx-macro: Fix uninitialized variable ec_tx There is potential read of the uninitialized variable ec_tx if the call to snd_soc_component_read fails or returns an unrecognized w->name. To avoid this corner case, initialize ec_tx to -1 so that it is caught later when ec_tx is bounds checked. Addresses-Coverity: ("Uninitialized scalar variable") Fixes: 4f692926f562 ("ASoC: codecs: lpass-rx-macro: add dapm widgets and route") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20210215163313.84026-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index c9c21d22c2c4..8c04b3b2c907 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -2895,7 +2895,7 @@ static int rx_macro_enable_echo(struct snd_soc_dapm_widget *w, { struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); u16 val, ec_hq_reg; - int ec_tx; + int ec_tx = -1; val = snd_soc_component_read(component, CDC_RX_INP_MUX_RX_MIX_CFG4); From 9fd914d917da05641b42cab7d40bdf8ab06dac3b Mon Sep 17 00:00:00 2001 From: Alexander Shiyan Date: Tue, 16 Feb 2021 14:42:21 +0300 Subject: [PATCH 0006/1091] ASoC: fsl_ssi: Fix TDM slot setup for I2S mode When using the driver in I2S TDM mode, the _fsl_ssi_set_dai_fmt() function rewrites the number of slots previously set by the fsl_ssi_set_dai_tdm_slot() function to 2 by default. To fix this, let's use the saved slot count value or, if TDM is not used and the slot count is not set, proceed as before. Fixes: 4f14f5c11db1 ("ASoC: fsl_ssi: Fix number of words per frame for I2S-slave mode") Signed-off-by: Alexander Shiyan Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20210216114221.26635-1-shc_work@mail.ru Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 57811743c294..ad8af3f450e2 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -878,6 +878,7 @@ static int fsl_ssi_hw_free(struct snd_pcm_substream *substream, static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) { u32 strcr = 0, scr = 0, stcr, srcr, mask; + unsigned int slots; ssi->dai_fmt = fmt; @@ -909,10 +910,11 @@ static int _fsl_ssi_set_dai_fmt(struct fsl_ssi *ssi, unsigned int fmt) return -EINVAL; } + slots = ssi->slots ? : 2; regmap_update_bits(ssi->regs, REG_SSI_STCCR, - SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2)); + SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots)); regmap_update_bits(ssi->regs, REG_SSI_SRCCR, - SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(2)); + SSI_SxCCR_DC_MASK, SSI_SxCCR_DC(slots)); /* Data on rising edge of bclk, frame low, 1clk before data */ strcr |= SSI_STCR_TFSI | SSI_STCR_TSCKP | SSI_STCR_TEFS; From 8fc0e3b6a8666d656923d214e4dc791e9a17164a Mon Sep 17 00:00:00 2001 From: Eyal Birger Date: Sat, 20 Feb 2021 15:01:15 +0200 Subject: [PATCH 0007/1091] xfrm: interface: fix ipv4 pmtu check to honor ip header df Frag needed should only be sent if the header enables DF. This fix allows packets larger than MTU to pass the xfrm interface and be fragmented after encapsulation, aligning behavior with non-interface xfrm. Fixes: f203b76d7809 ("xfrm: Add virtual xfrm interfaces") Signed-off-by: Eyal Birger Reviewed-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_interface.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/xfrm/xfrm_interface.c b/net/xfrm/xfrm_interface.c index 495b1f5c979b..8831f5a9e992 100644 --- a/net/xfrm/xfrm_interface.c +++ b/net/xfrm/xfrm_interface.c @@ -306,6 +306,8 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) icmpv6_ndo_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); } else { + if (!(ip_hdr(skb)->frag_off & htons(IP_DF))) + goto xmit; icmp_ndo_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); } @@ -314,6 +316,7 @@ xfrmi_xmit2(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) return -EMSGSIZE; } +xmit: xfrmi_scrub_packet(skb, !net_eq(xi->net, dev_net(dev))); skb_dst_set(skb, dst); skb->dev = tdev; From 37feaaf5ceb2245e474369312bb7b922ce7bce69 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:18 -0500 Subject: [PATCH 0008/1091] net: ieee802154: fix nl802154 del llsec key This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_KEY is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+ac5c11d2959a8b3c4806@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-1-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 1cebdcedc48c..f4a4d4a417e0 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1592,7 +1592,8 @@ static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; struct ieee802154_llsec_key_id id; - if (nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) + if (!info->attrs[NL802154_ATTR_SEC_KEY] || + nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) return -EINVAL; if (ieee802154_llsec_parse_key_id(attrs[NL802154_KEY_ATTR_ID], &id) < 0) From 3d1eac2f45585690d942cf47fd7fbd04093ebd1b Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:19 -0500 Subject: [PATCH 0009/1091] net: ieee802154: fix nl802154 del llsec dev This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_DEVICE is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+d946223c2e751d136c94@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-2-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index f4a4d4a417e0..460e53889781 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1758,7 +1758,8 @@ static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; __le64 extended_addr; - if (nla_parse_nested_deprecated(attrs, NL802154_DEV_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVICE], nl802154_dev_policy, info->extack)) + if (!info->attrs[NL802154_ATTR_SEC_DEVICE] || + nla_parse_nested_deprecated(attrs, NL802154_DEV_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVICE], nl802154_dev_policy, info->extack)) return -EINVAL; if (!attrs[NL802154_DEV_ATTR_EXTENDED_ADDR]) From 30be2641848b2450f0f1b62e3a8aea42e14db640 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 15 Feb 2021 15:21:15 +0100 Subject: [PATCH 0010/1091] ASoC: rt5670: Remove 'OUT Channel Switch' control The "OUT Channel Switch" control is a left over from code copied from thr rt5640 codec driver. With the rt5640 codec driver the output volume controls have 2 pairs of mute bits: bit 7, 15: Mute Control for Spk/Headphone/Line Output Port bit 6, 14: Mute Control for Spk/Headphone/Line Volume Channel Bits 7 and 15 are normal mute bits on the rt5670/5672 which are controlled by 2 dapm widgets: SND_SOC_DAPM_SWITCH("LOUT L Playback", SND_SOC_NOPM, 0, 0, &lout_l_enable_control), SND_SOC_DAPM_SWITCH("LOUT R Playback", SND_SOC_NOPM, 0, 0, &lout_r_enable_control), But on the 5670/5672 bit 6 is always reserved, where as bit 14 is "LOUT Differential Mode" on the 5670 and also reserved on the 5672. So the "OUT Channel Switch" control which is controlling bits 6+14 of the "LINE Output Control" register is bogus -> remove it. This should not cause any issues for userspace. AFAICT the rt567x codecs are only used on x86/ACPI devices and the UCM profiles used there do not use the "OUT Channel Switch" control. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210215142118.308516-2-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 2 -- sound/soc/codecs/rt5670.h | 4 ---- 2 files changed, 6 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index c29317ea5df2..2e799e21dbda 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -637,8 +637,6 @@ static const struct snd_kcontrol_new rt5670_snd_controls[] = { RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 39, 1, out_vol_tlv), /* OUTPUT Control */ - SOC_DOUBLE("OUT Channel Switch", RT5670_LOUT1, - RT5670_VOL_L_SFT, RT5670_VOL_R_SFT, 1, 1), SOC_DOUBLE_TLV("OUT Playback Volume", RT5670_LOUT1, RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 39, 1, out_vol_tlv), /* DAC Digital Volume */ diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index 56b13fe6bd3c..f9c4db156c80 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h @@ -212,12 +212,8 @@ /* global definition */ #define RT5670_L_MUTE (0x1 << 15) #define RT5670_L_MUTE_SFT 15 -#define RT5670_VOL_L_MUTE (0x1 << 14) -#define RT5670_VOL_L_SFT 14 #define RT5670_R_MUTE (0x1 << 7) #define RT5670_R_MUTE_SFT 7 -#define RT5670_VOL_R_MUTE (0x1 << 6) -#define RT5670_VOL_R_SFT 6 #define RT5670_L_VOL_MASK (0x3f << 8) #define RT5670_L_VOL_SFT 8 #define RT5670_R_VOL_MASK (0x3f) From 8022f09883e827855d86173756caa07b891100f0 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 15 Feb 2021 15:21:16 +0100 Subject: [PATCH 0011/1091] ASoC: rt5670: Remove 'HP Playback Switch' control The RT5670_L_MUTE_SFT and RT5670_R_MUTE_SFT bits (bits 15 and 7) of the RT5670_HP_VOL register are set / unset by the headphones deplop code run by rt5670_hp_event() on SND_SOC_DAPM_POST_PMU / SND_SOC_DAPM_PRE_PMD. So we should not also export a control to userspace which toggles these same bits. This should not cause any issues for userspace. AFAICT the rt567x codecs are only used on x86/ACPI devices and the UCM profiles used there do not use the "HP Playback Switch" control. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210215142118.308516-3-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 2e799e21dbda..932e4cd1e9a6 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -631,8 +631,6 @@ static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_enum, RT5670_DIG_INF1_DATA, static const struct snd_kcontrol_new rt5670_snd_controls[] = { /* Headphone Output Volume */ - SOC_DOUBLE("HP Playback Switch", RT5670_HP_VOL, - RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1), SOC_DOUBLE_TLV("HP Playback Volume", RT5670_HP_VOL, RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 39, 1, out_vol_tlv), From 674e4ff4c2326c6e3f8ddc73c61910bf32228720 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 15 Feb 2021 15:21:17 +0100 Subject: [PATCH 0012/1091] ASoC: rt5670: Remove ADC vol-ctrl mute bits poking from Sto1 ADC mixer settings The SND_SOC_DAPM_MIXER declaration for "Sto1 ADC MIXL" and "Sto1 ADC MIXR" was using the mute bits from the RT5670_STO1_ADC_DIG_VOL control as mixer master mute bits. But these bits are already exposed to userspace as controls as part of the "ADC Capture Volume" / "ADC Capture Switch" control pair: SOC_DOUBLE("ADC Capture Switch", RT5670_STO1_ADC_DIG_VOL, RT5670_L_MUTE_SFT, RT5670_R_MUTE_SFT, 1, 1), SOC_DOUBLE_TLV("ADC Capture Volume", RT5670_STO1_ADC_DIG_VOL, RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 127, 0, adc_vol_tlv), Both the fact that the mute bits belong to the same reg as the vol-ctrl and the "Digital Mixer Path" diagram in the datasheet clearly shows that these mute bits are not part of the mixer and having 2 separate controls poking at the same bits is a bad idea. Remove the master-mute bits settings from the "Sto1 ADC MIXL" and "Sto1 ADC MIXR" DAPM widget declarations, avoiding these bits getting poked from 2 different places. This should not cause any issues for userspace. AFAICT the rt567x codecs are only used on x86/ACPI devices and the UCM profiles used there already set the "ADC Capture Switch" as needed. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210215142118.308516-4-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 932e4cd1e9a6..2f015c24c637 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -1652,12 +1652,10 @@ static const struct snd_soc_dapm_widget rt5670_dapm_widgets[] = { RT5670_PWR_ADC_S1F_BIT, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("ADC Stereo2 Filter", RT5670_PWR_DIG2, RT5670_PWR_ADC_S2F_BIT, 0, NULL, 0), - SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", RT5670_STO1_ADC_DIG_VOL, - RT5670_L_MUTE_SFT, 1, rt5670_sto1_adc_l_mix, - ARRAY_SIZE(rt5670_sto1_adc_l_mix)), - SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", RT5670_STO1_ADC_DIG_VOL, - RT5670_R_MUTE_SFT, 1, rt5670_sto1_adc_r_mix, - ARRAY_SIZE(rt5670_sto1_adc_r_mix)), + SND_SOC_DAPM_MIXER("Sto1 ADC MIXL", SND_SOC_NOPM, 0, 0, + rt5670_sto1_adc_l_mix, ARRAY_SIZE(rt5670_sto1_adc_l_mix)), + SND_SOC_DAPM_MIXER("Sto1 ADC MIXR", SND_SOC_NOPM, 0, 0, + rt5670_sto1_adc_r_mix, ARRAY_SIZE(rt5670_sto1_adc_r_mix)), SND_SOC_DAPM_MIXER("Sto2 ADC MIXL", SND_SOC_NOPM, 0, 0, rt5670_sto2_adc_l_mix, ARRAY_SIZE(rt5670_sto2_adc_l_mix)), From 982042931c255e2e7f196c24f1e5d6de780e04f9 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Mon, 15 Feb 2021 15:21:18 +0100 Subject: [PATCH 0013/1091] ASoC: rt5670: Add emulated 'DAC1 Playback Switch' control For reliable output-mute LED control we need a "DAC1 Playback Switch" control. The "DAC Playback volume" control is the only control in the path from the DAC1 data input to the speaker output, so the UCM profile for the speaker output will have its PlaybackMixerElem set to "DAC1". But userspace (pulseaudio) will set the "DAC1 Playback Volume" control to its softest setting (which is not fully muted) while still showing the speaker as being enabled at a low volume in the UI. If we were to set the SNDRV_CTL_ELEM_ACCESS_SPK_LED on the "DAC1 Playback Volume" control, this would mean then what pressing KEY_VOLUMEDOWN the speaker-mute LED (embedded in the volume-mute toggle key) would light while the UI is still showing the speaker as being enabled at a low volume, meaning that the UI and the LED are out of sync. Only after an _extra_ KEY_VOLUMEDOWN press would the UI show the speaker as being muted. The path from DAC1 data input to the speaker output does have a digital mixer with DAC1's data as one of its inputs direclty after the "DAC1 Playback Volume" control. This commit adds an emulated "DAC1 Playback Switch" control by: 1. Declaring the enable flag for that mixers DAC1 input as well as the "DAC1 Playback Switch" control both as SND_SOC_NOPM controls. 2. Storing the settings of both controls as driver-private data 3. Only clearing the mute flag for the DAC1 input of that mixer if the stored values indicate both controls are enabled. This is a preparation patch for adding "audio-mute" LED trigger support. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210215142118.308516-5-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 96 +++++++++++++++++++++++++++++++++++++-- sound/soc/codecs/rt5670.h | 5 ++ 2 files changed, 97 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 2f015c24c637..4063aac2a443 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -629,6 +629,56 @@ static SOC_ENUM_SINGLE_DECL(rt5670_if2_dac_enum, RT5670_DIG_INF1_DATA, static SOC_ENUM_SINGLE_DECL(rt5670_if2_adc_enum, RT5670_DIG_INF1_DATA, RT5670_IF2_ADC_SEL_SFT, rt5670_data_select); +/* + * For reliable output-mute LED control we need a "DAC1 Playback Switch" control. + * We emulate this by only clearing the RT5670_M_DAC1_L/_R AD_DA_MIXER register + * bits when both our emulated DAC1 Playback Switch control and the DAC1 MIXL/R + * DAPM-mixer DAC1 input are enabled. + */ +static void rt5670_update_ad_da_mixer_dac1_m_bits(struct rt5670_priv *rt5670) +{ + int val = RT5670_M_DAC1_L | RT5670_M_DAC1_R; + + if (rt5670->dac1_mixl_dac1_switch && rt5670->dac1_playback_switch_l) + val &= ~RT5670_M_DAC1_L; + + if (rt5670->dac1_mixr_dac1_switch && rt5670->dac1_playback_switch_r) + val &= ~RT5670_M_DAC1_R; + + regmap_update_bits(rt5670->regmap, RT5670_AD_DA_MIXER, + RT5670_M_DAC1_L | RT5670_M_DAC1_R, val); +} + +static int rt5670_dac1_playback_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = rt5670->dac1_playback_switch_l; + ucontrol->value.integer.value[1] = rt5670->dac1_playback_switch_r; + + return 0; +} + +static int rt5670_dac1_playback_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_soc_kcontrol_component(kcontrol); + struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); + + if (rt5670->dac1_playback_switch_l == ucontrol->value.integer.value[0] && + rt5670->dac1_playback_switch_r == ucontrol->value.integer.value[1]) + return 0; + + rt5670->dac1_playback_switch_l = ucontrol->value.integer.value[0]; + rt5670->dac1_playback_switch_r = ucontrol->value.integer.value[1]; + + rt5670_update_ad_da_mixer_dac1_m_bits(rt5670); + + return 1; +} + static const struct snd_kcontrol_new rt5670_snd_controls[] = { /* Headphone Output Volume */ SOC_DOUBLE_TLV("HP Playback Volume", RT5670_HP_VOL, @@ -640,6 +690,8 @@ static const struct snd_kcontrol_new rt5670_snd_controls[] = { /* DAC Digital Volume */ SOC_DOUBLE("DAC2 Playback Switch", RT5670_DAC_CTRL, RT5670_M_DAC_L2_VOL_SFT, RT5670_M_DAC_R2_VOL_SFT, 1, 1), + SOC_DOUBLE_EXT("DAC1 Playback Switch", SND_SOC_NOPM, 0, 1, 1, 0, + rt5670_dac1_playback_switch_get, rt5670_dac1_playback_switch_put), SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5670_DAC1_DIG_VOL, RT5670_L_VOL_SFT, RT5670_R_VOL_SFT, 175, 0, dac_vol_tlv), @@ -909,18 +961,44 @@ static const struct snd_kcontrol_new rt5670_mono_adc_r_mix[] = { RT5670_M_MONO_ADC_R2_SFT, 1, 1), }; +/* See comment above rt5670_update_ad_da_mixer_dac1_m_bits() */ +static int rt5670_put_dac1_mix_dac1_switch(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct soc_mixer_control *mc = (struct soc_mixer_control *)kcontrol->private_value; + struct snd_soc_component *component = snd_soc_dapm_kcontrol_component(kcontrol); + struct rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); + int ret; + + if (mc->shift == 0) + rt5670->dac1_mixl_dac1_switch = ucontrol->value.integer.value[0]; + else + rt5670->dac1_mixr_dac1_switch = ucontrol->value.integer.value[0]; + + /* Apply the update (if any) */ + ret = snd_soc_dapm_put_volsw(kcontrol, ucontrol); + if (ret == 0) + return 0; + + rt5670_update_ad_da_mixer_dac1_m_bits(rt5670); + + return 1; +} + +#define SOC_DAPM_SINGLE_RT5670_DAC1_SW(name, shift) \ + SOC_SINGLE_EXT(name, SND_SOC_NOPM, shift, 1, 0, \ + snd_soc_dapm_get_volsw, rt5670_put_dac1_mix_dac1_switch) + static const struct snd_kcontrol_new rt5670_dac_l_mix[] = { SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER, RT5670_M_ADCMIX_L_SFT, 1, 1), - SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER, - RT5670_M_DAC1_L_SFT, 1, 1), + SOC_DAPM_SINGLE_RT5670_DAC1_SW("DAC1 Switch", 0), }; static const struct snd_kcontrol_new rt5670_dac_r_mix[] = { SOC_DAPM_SINGLE("Stereo ADC Switch", RT5670_AD_DA_MIXER, RT5670_M_ADCMIX_R_SFT, 1, 1), - SOC_DAPM_SINGLE("DAC1 Switch", RT5670_AD_DA_MIXER, - RT5670_M_DAC1_R_SFT, 1, 1), + SOC_DAPM_SINGLE_RT5670_DAC1_SW("DAC1 Switch", 1), }; static const struct snd_kcontrol_new rt5670_sto_dac_l_mix[] = { @@ -2993,6 +3071,16 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, dev_info(&i2c->dev, "quirk JD mode 3\n"); } + /* + * Enable the emulated "DAC1 Playback Switch" by default to avoid + * muting the output with older UCM profiles. + */ + rt5670->dac1_playback_switch_l = true; + rt5670->dac1_playback_switch_r = true; + /* The Power-On-Reset values for the DAC1 mixer have the DAC1 input enabled. */ + rt5670->dac1_mixl_dac1_switch = true; + rt5670->dac1_mixr_dac1_switch = true; + rt5670->regmap = devm_regmap_init_i2c(i2c, &rt5670_regmap); if (IS_ERR(rt5670->regmap)) { ret = PTR_ERR(rt5670->regmap); diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index f9c4db156c80..6fb3c369ee98 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h @@ -2013,6 +2013,11 @@ struct rt5670_priv { int dsp_rate; int jack_type; int jack_type_saved; + + bool dac1_mixl_dac1_switch; + bool dac1_mixr_dac1_switch; + bool dac1_playback_switch_l; + bool dac1_playback_switch_r; }; void rt5670_jack_suspend(struct snd_soc_component *component); From f84b4524005238fc9fd5cf615bb426fa40a99494 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Feb 2021 14:57:51 +0800 Subject: [PATCH 0014/1091] ASoC: ak4458: Add MODULE_DEVICE_TABLE Add missed MODULE_DEVICE_TABLE for the driver can be loaded automatically at boot. Fixes: 08660086eff9 ("ASoC: ak4458: Add support for AK4458 DAC driver") Cc: Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1614149872-25510-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak4458.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 472caad17012..85a1d00894a9 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -812,6 +812,7 @@ static const struct of_device_id ak4458_of_match[] = { { .compatible = "asahi-kasei,ak4497", .data = &ak4497_drvdata}, { }, }; +MODULE_DEVICE_TABLE(of, ak4458_of_match); static struct i2c_driver ak4458_i2c_driver = { .driver = { From 741c8397e5d0b339fb3e614a9ff5cb4bf7ae1a65 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Feb 2021 14:57:52 +0800 Subject: [PATCH 0015/1091] ASoC: ak5558: Add MODULE_DEVICE_TABLE Add missed MODULE_DEVICE_TABLE for the driver can be loaded automatically at boot. Fixes: 920884777480 ("ASoC: ak5558: Add support for AK5558 ADC driver") Cc: Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1614149872-25510-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 8a32b0139cb0..85bdd0534180 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -419,6 +419,7 @@ static const struct of_device_id ak5558_i2c_dt_ids[] __maybe_unused = { { .compatible = "asahi-kasei,ak5558"}, { } }; +MODULE_DEVICE_TABLE(of, ak5558_i2c_dt_ids); static struct i2c_driver ak5558_i2c_driver = { .driver = { From 20d5fe2d7103f5c43ad11a3d6d259e9d61165c35 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:20 -0500 Subject: [PATCH 0016/1091] net: ieee802154: fix nl802154 add llsec key This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_KEY is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+ce4e062c2d51977ddc50@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-3-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 460e53889781..4aa9000b7eea 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1544,7 +1544,8 @@ static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info) struct ieee802154_llsec_key_id id = { }; u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { }; - if (nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) + if (!info->attrs[NL802154_ATTR_SEC_KEY] || + nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) return -EINVAL; if (!attrs[NL802154_KEY_ATTR_USAGE_FRAMES] || From 27c746869e1a135dffc2f2a80715bb7aa00445b4 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 21 Feb 2021 12:43:21 -0500 Subject: [PATCH 0017/1091] net: ieee802154: fix nl802154 del llsec devkey This patch fixes a nullpointer dereference if NL802154_ATTR_SEC_DEVKEY is not set by the user. If this is the case nl802154 will return -EINVAL. Reported-by: syzbot+368672e0da240db53b5f@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210221174321.14210-4-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 4aa9000b7eea..1600edb98107 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1916,7 +1916,8 @@ static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info struct ieee802154_llsec_device_key key; __le64 extended_addr; - if (nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack)) + if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || + nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack)) return -EINVAL; if (!attrs[NL802154_DEVKEY_ATTR_EXTENDED_ADDR]) From 1045a5c04e16716870cc953872e703258e7896de Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Wed, 24 Feb 2021 11:50:52 +0100 Subject: [PATCH 0018/1091] ASoC: Intel: bytcr_rt5640: Fix HP Pavilion x2 10-p0XX OVCD current threshold When I added the quirk for the "HP Pavilion x2 10-p0XX" I copied the byt_rt5640_quirk_table[] entry for the HP Pavilion x2 10-k0XX / 10-n0XX models since these use almost the same settings. While doing this I accidentally also copied and kept the non-standard OVCD_TH_1500UA setting used on those models. This too low threshold is causing headsets to often be seen as headphones (without a headset-mic) and when correctly identified it is causing ghost play/pause button-presses to get detected. Correct the HP Pavilion x2 10-p0XX quirk to use the default OVCD_TH_2000UA setting, fixing these problems. Fixes: fbdae7d6d04d ("ASoC: Intel: bytcr_rt5640: Fix HP Pavilion x2 Detachable quirks") Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210224105052.42116-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 782f2b4d72ad..5d48cc359c3d 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -581,7 +581,7 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { }, .driver_data = (void *)(BYT_RT5640_DMIC1_MAP | BYT_RT5640_JD_SRC_JD1_IN4P | - BYT_RT5640_OVCD_TH_1500UA | + BYT_RT5640_OVCD_TH_2000UA | BYT_RT5640_OVCD_SF_0P75 | BYT_RT5640_MCLK_EN), }, From 24a7b77daed8f973bf8a5ed2f83344f44f9f6396 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Feb 2021 15:38:13 +0100 Subject: [PATCH 0019/1091] ASoC: rt5640: Fix dac- and adc- vol-tlv values being off by a factor of 10 The adc_vol_tlv volume-control has a range from -17.625 dB to +30 dB, not -176.25 dB to + 300 dB. This wrong scale is esp. a problem in userspace apps which translate the dB scale to a linear scale. With the logarithmic dB scale being of by a factor of 10 we loose all precision in the lower area of the range when apps translate things to a linear scale. E.g. the 0 dB default, which corresponds with a value of 47 of the 0 - 127 range for the control, would be shown as 0/100 in alsa-mixer. Since the centi-dB values used in the TLV struct cannot represent the 0.375 dB step size used by these controls, change the TLV definition for them to specify a min and max value instead of min + stepsize. Note this mirrors commit 3f31f7d9b540 ("ASoC: rt5670: Fix dac- and adc- vol-tlv values being off by a factor of 10") which made the exact same change to the rt5670 codec driver. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210226143817.84287-2-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 1414ad15d01c..a5674c227b3a 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -339,9 +339,9 @@ static bool rt5640_readable_register(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ From e4ffab875d32bf4ffa37b5cd725ace9e15d1707d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 26 Feb 2021 15:38:14 +0100 Subject: [PATCH 0020/1091] ASoC: rt5651: Fix dac- and adc- vol-tlv values being off by a factor of 10 The adc_vol_tlv volume-control has a range from -17.625 dB to +30 dB, not -176.25 dB to + 300 dB. This wrong scale is esp. a problem in userspace apps which translate the dB scale to a linear scale. With the logarithmic dB scale being of by a factor of 10 we loose all precision in the lower area of the range when apps translate things to a linear scale. E.g. the 0 dB default, which corresponds with a value of 47 of the 0 - 127 range for the control, would be shown as 0/100 in alsa-mixer. Since the centi-dB values used in the TLV struct cannot represent the 0.375 dB step size used by these controls, change the TLV definition for them to specify a min and max value instead of min + stepsize. Note this mirrors commit 3f31f7d9b540 ("ASoC: rt5670: Fix dac- and adc- vol-tlv values being off by a factor of 10") which made the exact same change to the rt5670 codec driver. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210226143817.84287-3-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index d198e191fb0c..e59fdc81dbd4 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -285,9 +285,9 @@ static bool rt5651_readable_register(struct device *dev, unsigned int reg) } static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -4650, 150, 0); -static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -65625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(dac_vol_tlv, -6562, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -3450, 150, 0); -static const DECLARE_TLV_DB_SCALE(adc_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_MINMAX(adc_vol_tlv, -1762, 3000); static const DECLARE_TLV_DB_SCALE(adc_bst_tlv, 0, 1200, 0); /* {0, +20, +24, +30, +35, +40, +44, +50, +52} dB */ From d74fcdc51afd431ca9d956e032e14d12f0ee4153 Mon Sep 17 00:00:00 2001 From: Benjamin Rood Date: Fri, 19 Feb 2021 13:33:08 -0500 Subject: [PATCH 0021/1091] ASoC: sgtl5000: set DAP_AVC_CTRL register to correct default value on probe According to the SGTL5000 datasheet [1], the DAP_AVC_CTRL register has the following bit field definitions: | BITS | FIELD | RW | RESET | DEFINITION | | 15 | RSVD | RO | 0x0 | Reserved | | 14 | RSVD | RW | 0x1 | Reserved | | 13:12 | MAX_GAIN | RW | 0x1 | Max Gain of AVC in expander mode | | 11:10 | RSVD | RO | 0x0 | Reserved | | 9:8 | LBI_RESP | RW | 0x1 | Integrator Response | | 7:6 | RSVD | RO | 0x0 | Reserved | | 5 | HARD_LMT_EN | RW | 0x0 | Enable hard limiter mode | | 4:1 | RSVD | RO | 0x0 | Reserved | | 0 | EN | RW | 0x0 | Enable/Disable AVC | The original default value written to the DAP_AVC_CTRL register during sgtl5000_i2c_probe() was 0x0510. This would incorrectly write values to bits 4 and 10, which are defined as RESERVED. It would also not set bits 12 and 14 to their correct RESET values of 0x1, and instead set them to 0x0. While the DAP_AVC module is effectively disabled because the EN bit is 0, this default value is still writing invalid values to registers that are marked as read-only and RESERVED as well as not setting bits 12 and 14 to their correct default values as defined by the datasheet. The correct value that should be written to the DAP_AVC_CTRL register is 0x5100, which configures the register bits to the default values defined by the datasheet, and prevents any writes to bits defined as 'read-only'. Generally speaking, it is best practice to NOT attempt to write values to registers/bits defined as RESERVED, as it generally produces unwanted/undefined behavior, or errors. Also, all credit for this patch should go to my colleague Dan MacDonald for finding this error in the first place. [1] https://www.nxp.com/docs/en/data-sheet/SGTL5000.pdf Signed-off-by: Benjamin Rood Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/20210219183308.GA2117@ubuntu-dev Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 73551e36695e..6d9bb256a2cf 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -71,7 +71,7 @@ static const struct reg_default sgtl5000_reg_defaults[] = { { SGTL5000_DAP_EQ_BASS_BAND4, 0x002f }, { SGTL5000_DAP_MAIN_CHAN, 0x8000 }, { SGTL5000_DAP_MIX_CHAN, 0x0000 }, - { SGTL5000_DAP_AVC_CTRL, 0x0510 }, + { SGTL5000_DAP_AVC_CTRL, 0x5100 }, { SGTL5000_DAP_AVC_THRESHOLD, 0x1473 }, { SGTL5000_DAP_AVC_ATTACK, 0x0028 }, { SGTL5000_DAP_AVC_DECAY, 0x0050 }, From 4d4e677a68e770b84c87d1438d9f4e161658536a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 28 Feb 2021 17:04:41 +0100 Subject: [PATCH 0022/1091] ASoC: es8316: Simplify adc_pga_gain_tlv table Most steps in this table are steps of 3dB (300 centi-dB), so we can simplify the table. This not only reduces the amount of space it takes inside the kernel, this also makes alsa-lib's mixer code actually accept the table, where as before this change alsa-lib saw the "ADC PGA Gain" control as a control without a dB scale. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210228160441.241110-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/es8316.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/es8316.c b/sound/soc/codecs/es8316.c index d632055370e0..067757d1d70a 100644 --- a/sound/soc/codecs/es8316.c +++ b/sound/soc/codecs/es8316.c @@ -63,13 +63,8 @@ static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(adc_pga_gain_tlv, 1, 1, TLV_DB_SCALE_ITEM(0, 0, 0), 2, 2, TLV_DB_SCALE_ITEM(250, 0, 0), 3, 3, TLV_DB_SCALE_ITEM(450, 0, 0), - 4, 4, TLV_DB_SCALE_ITEM(700, 0, 0), - 5, 5, TLV_DB_SCALE_ITEM(1000, 0, 0), - 6, 6, TLV_DB_SCALE_ITEM(1300, 0, 0), - 7, 7, TLV_DB_SCALE_ITEM(1600, 0, 0), - 8, 8, TLV_DB_SCALE_ITEM(1800, 0, 0), - 9, 9, TLV_DB_SCALE_ITEM(2100, 0, 0), - 10, 10, TLV_DB_SCALE_ITEM(2400, 0, 0), + 4, 7, TLV_DB_SCALE_ITEM(700, 300, 0), + 8, 10, TLV_DB_SCALE_ITEM(1800, 300, 0), ); static const SNDRV_CTL_TLVD_DECLARE_DB_RANGE(hpout_vol_tlv, From 290c323008db6e3a44d981a46b56f7f166979a04 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 1 Mar 2021 18:34:10 -0600 Subject: [PATCH 0023/1091] ASoC: SOF: Intel: unregister DMIC device on probe error We only unregister the platform device during the .remove operation, but if the probe fails we will never reach this sequence. Suggested-by: Bard Liao Fixes: dd96daca6c83e ("ASoC: SOF: Intel: Add APL/CNL HW DSP support") Signed-off-by: Pierre-Louis Bossart Reviewed-by: Ranjani Sridharan Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210302003410.1178535-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 0dc3a8c0f5e3..001fc9834a19 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -895,6 +895,7 @@ free_streams: /* dsp_unmap: not currently used */ iounmap(sdev->bar[HDA_DSP_BAR]); hdac_bus_unmap: + platform_device_unregister(hdev->dmic_dev); iounmap(bus->remap_addr); hda_codec_i915_exit(sdev); err: From 6f7f657f24405f426212c09260bf7fe8a52cef33 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 28 Feb 2021 10:18:03 -0500 Subject: [PATCH 0024/1091] net: ieee802154: nl-mac: fix check on panid This patch fixes a null pointer derefence for panid handle by move the check for the netlink variable directly before accessing them. Reported-by: syzbot+d4c07de0144f6f63be3a@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210228151817.95700-4-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl-mac.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/net/ieee802154/nl-mac.c b/net/ieee802154/nl-mac.c index 9c640d670ffe..0c1b0770c59e 100644 --- a/net/ieee802154/nl-mac.c +++ b/net/ieee802154/nl-mac.c @@ -551,9 +551,7 @@ ieee802154_llsec_parse_key_id(struct genl_info *info, desc->mode = nla_get_u8(info->attrs[IEEE802154_ATTR_LLSEC_KEY_MODE]); if (desc->mode == IEEE802154_SCF_KEY_IMPLICIT) { - if (!info->attrs[IEEE802154_ATTR_PAN_ID] && - !(info->attrs[IEEE802154_ATTR_SHORT_ADDR] || - info->attrs[IEEE802154_ATTR_HW_ADDR])) + if (!info->attrs[IEEE802154_ATTR_PAN_ID]) return -EINVAL; desc->device_addr.pan_id = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_PAN_ID]); @@ -562,6 +560,9 @@ ieee802154_llsec_parse_key_id(struct genl_info *info, desc->device_addr.mode = IEEE802154_ADDR_SHORT; desc->device_addr.short_addr = nla_get_shortaddr(info->attrs[IEEE802154_ATTR_SHORT_ADDR]); } else { + if (!info->attrs[IEEE802154_ATTR_HW_ADDR]) + return -EINVAL; + desc->device_addr.mode = IEEE802154_ADDR_LONG; desc->device_addr.extended_addr = nla_get_hwaddr(info->attrs[IEEE802154_ATTR_HW_ADDR]); } From c7c1abfd6d42be8f09d390ab912cd84983000fa2 Mon Sep 17 00:00:00 2001 From: Eyal Birger Date: Fri, 26 Feb 2021 23:35:05 +0200 Subject: [PATCH 0025/1091] vti: fix ipv4 pmtu check to honor ip header df Frag needed should only be sent if the header enables DF. This fix allows packets larger than MTU to pass the vti interface and be fragmented after encapsulation, aligning behavior with non-vti xfrm. Fixes: d6af1a31cc72 ("vti: Add pmtu handling to vti_xmit.") Signed-off-by: Eyal Birger Reviewed-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- net/ipv4/ip_vti.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_vti.c b/net/ipv4/ip_vti.c index abc171e79d3e..613741384490 100644 --- a/net/ipv4/ip_vti.c +++ b/net/ipv4/ip_vti.c @@ -218,7 +218,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, } if (dst->flags & DST_XFRM_QUEUE) - goto queued; + goto xmit; if (!vti_state_check(dst->xfrm, parms->iph.daddr, parms->iph.saddr)) { dev->stats.tx_carrier_errors++; @@ -238,6 +238,8 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, if (skb->len > mtu) { skb_dst_update_pmtu_no_confirm(skb, mtu); if (skb->protocol == htons(ETH_P_IP)) { + if (!(ip_hdr(skb)->frag_off & htons(IP_DF))) + goto xmit; icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); } else { @@ -251,7 +253,7 @@ static netdev_tx_t vti_xmit(struct sk_buff *skb, struct net_device *dev, goto tx_error; } -queued: +xmit: skb_scrub_packet(skb, !net_eq(tunnel->net, dev_net(dev))); skb_dst_set(skb, dst); skb->dev = skb_dst(skb)->dev; From 4c38255892c06b9de2fb3bf6aea63f4ebdff3d11 Mon Sep 17 00:00:00 2001 From: Eyal Birger Date: Fri, 26 Feb 2021 23:35:06 +0200 Subject: [PATCH 0026/1091] vti6: fix ipv4 pmtu check to honor ip header df Frag needed should only be sent if the header enables DF. This fix allows IPv4 packets larger than MTU to pass the vti6 interface and be fragmented after encapsulation, aligning behavior with non-vti6 xfrm. Fixes: ccd740cbc6e0 ("vti6: Add pmtu handling to vti6_xmit.") Signed-off-by: Eyal Birger Reviewed-by: Sabrina Dubroca Signed-off-by: Steffen Klassert --- net/ipv6/ip6_vti.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/net/ipv6/ip6_vti.c b/net/ipv6/ip6_vti.c index 0225fd694192..2f0be5ac021c 100644 --- a/net/ipv6/ip6_vti.c +++ b/net/ipv6/ip6_vti.c @@ -494,7 +494,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) } if (dst->flags & DST_XFRM_QUEUE) - goto queued; + goto xmit; x = dst->xfrm; if (!vti6_state_check(x, &t->parms.raddr, &t->parms.laddr)) @@ -523,6 +523,8 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) icmpv6_send(skb, ICMPV6_PKT_TOOBIG, 0, mtu); } else { + if (!(ip_hdr(skb)->frag_off & htons(IP_DF))) + goto xmit; icmp_send(skb, ICMP_DEST_UNREACH, ICMP_FRAG_NEEDED, htonl(mtu)); } @@ -531,7 +533,7 @@ vti6_xmit(struct sk_buff *skb, struct net_device *dev, struct flowi *fl) goto tx_err_dst_release; } -queued: +xmit: skb_scrub_packet(skb, !net_eq(t->net, dev_net(dev))); skb_dst_set(skb, dst); skb->dev = skb_dst(skb)->dev; From 9ab1265d52314fce1b51e8665ea6dbc9ac1a027c Mon Sep 17 00:00:00 2001 From: Evan Nimmo Date: Tue, 2 Mar 2021 08:00:04 +1300 Subject: [PATCH 0027/1091] xfrm: Use actual socket sk instead of skb socket for xfrm_output_resume A situation can occur where the interface bound to the sk is different to the interface bound to the sk attached to the skb. The interface bound to the sk is the correct one however this information is lost inside xfrm_output2 and instead the sk on the skb is used in xfrm_output_resume instead. This assumes that the sk bound interface and the bound interface attached to the sk within the skb are the same which can lead to lookup failures inside ip_route_me_harder resulting in the packet being dropped. We have an l2tp v3 tunnel with ipsec protection. The tunnel is in the global VRF however we have an encapsulated dot1q tunnel interface that is within a different VRF. We also have a mangle rule that marks the packets causing them to be processed inside ip_route_me_harder. Prior to commit 31c70d5956fc ("l2tp: keep original skb ownership") this worked fine as the sk attached to the skb was changed from the dot1q encapsulated interface to the sk for the tunnel which meant the interface bound to the sk and the interface bound to the skb were identical. Commit 46d6c5ae953c ("netfilter: use actual socket sk rather than skb sk when routing harder") fixed some of these issues however a similar problem existed in the xfrm code. Fixes: 31c70d5956fc ("l2tp: keep original skb ownership") Signed-off-by: Evan Nimmo Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 2 +- net/ipv4/ah4.c | 2 +- net/ipv4/esp4.c | 2 +- net/ipv6/ah6.c | 2 +- net/ipv6/esp6.c | 2 +- net/xfrm/xfrm_output.c | 10 +++++----- 6 files changed, 10 insertions(+), 10 deletions(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index b2a06f10b62c..bfbc7810df94 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1557,7 +1557,7 @@ int xfrm_trans_queue_net(struct net *net, struct sk_buff *skb, int xfrm_trans_queue(struct sk_buff *skb, int (*finish)(struct net *, struct sock *, struct sk_buff *)); -int xfrm_output_resume(struct sk_buff *skb, int err); +int xfrm_output_resume(struct sock *sk, struct sk_buff *skb, int err); int xfrm_output(struct sock *sk, struct sk_buff *skb); #if IS_ENABLED(CONFIG_NET_PKTGEN) diff --git a/net/ipv4/ah4.c b/net/ipv4/ah4.c index d99e1be94019..36ed85bf2ad5 100644 --- a/net/ipv4/ah4.c +++ b/net/ipv4/ah4.c @@ -141,7 +141,7 @@ static void ah_output_done(struct crypto_async_request *base, int err) } kfree(AH_SKB_CB(skb)->tmp); - xfrm_output_resume(skb, err); + xfrm_output_resume(skb->sk, skb, err); } static int ah_output(struct xfrm_state *x, struct sk_buff *skb) diff --git a/net/ipv4/esp4.c b/net/ipv4/esp4.c index a3271ec3e162..4b834bbf95e0 100644 --- a/net/ipv4/esp4.c +++ b/net/ipv4/esp4.c @@ -279,7 +279,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) esp_output_tail_tcp(x, skb); else - xfrm_output_resume(skb, err); + xfrm_output_resume(skb->sk, skb, err); } } diff --git a/net/ipv6/ah6.c b/net/ipv6/ah6.c index 440080da805b..080ee7f44c64 100644 --- a/net/ipv6/ah6.c +++ b/net/ipv6/ah6.c @@ -316,7 +316,7 @@ static void ah6_output_done(struct crypto_async_request *base, int err) } kfree(AH_SKB_CB(skb)->tmp); - xfrm_output_resume(skb, err); + xfrm_output_resume(skb->sk, skb, err); } static int ah6_output(struct xfrm_state *x, struct sk_buff *skb) diff --git a/net/ipv6/esp6.c b/net/ipv6/esp6.c index 153ad103ba74..727d791ed5e6 100644 --- a/net/ipv6/esp6.c +++ b/net/ipv6/esp6.c @@ -314,7 +314,7 @@ static void esp_output_done(struct crypto_async_request *base, int err) x->encap && x->encap->encap_type == TCP_ENCAP_ESPINTCP) esp_output_tail_tcp(x, skb); else - xfrm_output_resume(skb, err); + xfrm_output_resume(skb->sk, skb, err); } } diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index a7ab19353313..b81ca117dac7 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -503,22 +503,22 @@ out: return err; } -int xfrm_output_resume(struct sk_buff *skb, int err) +int xfrm_output_resume(struct sock *sk, struct sk_buff *skb, int err) { struct net *net = xs_net(skb_dst(skb)->xfrm); while (likely((err = xfrm_output_one(skb, err)) == 0)) { nf_reset_ct(skb); - err = skb_dst(skb)->ops->local_out(net, skb->sk, skb); + err = skb_dst(skb)->ops->local_out(net, sk, skb); if (unlikely(err != 1)) goto out; if (!skb_dst(skb)->xfrm) - return dst_output(net, skb->sk, skb); + return dst_output(net, sk, skb); err = nf_hook(skb_dst(skb)->ops->family, - NF_INET_POST_ROUTING, net, skb->sk, skb, + NF_INET_POST_ROUTING, net, sk, skb, NULL, skb_dst(skb)->dev, xfrm_output2); if (unlikely(err != 1)) goto out; @@ -534,7 +534,7 @@ EXPORT_SYMBOL_GPL(xfrm_output_resume); static int xfrm_output2(struct net *net, struct sock *sk, struct sk_buff *skb) { - return xfrm_output_resume(skb, 1); + return xfrm_output_resume(sk, skb, 1); } static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb) From c014170408bcd2e8fc726802ed16794d358742ff Mon Sep 17 00:00:00 2001 From: Jon Hunter Date: Wed, 3 Mar 2021 11:55:26 +0000 Subject: [PATCH 0028/1091] ASoC: soc-core: Prevent warning if no DMI table is present Many systems do not use ACPI and hence do not provide a DMI table. On non-ACPI systems a warning, such as the following, is printed on boot. WARNING KERN tegra-audio-graph-card sound: ASoC: no DMI vendor name! The variable 'dmi_available' is not exported and so currently cannot be used by kernel modules without adding an accessor. However, it is possible to use the function is_acpi_device_node() to determine if the sound card is an ACPI device and hence indicate if we expect a DMI table to be present. Therefore, call is_acpi_device_node() to see if we are using ACPI and only parse the DMI table if we are booting with ACPI. Signed-off-by: Jon Hunter Link: https://lore.kernel.org/r/20210303115526.419458-1-jonathanh@nvidia.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f6d4e99b590c..0cffc9527e28 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -1573,6 +1574,9 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) if (card->long_name) return 0; /* long name already set by driver or from DMI */ + if (!is_acpi_device_node(card->dev->fwnode)) + return 0; + /* make up dmi long name as: vendor-product-version-board */ vendor = dmi_get_system_info(DMI_BOARD_VENDOR); if (!vendor || !is_dmi_valid(vendor)) { From 30b3f68715595dee7fe4d9bd91a2252c3becdf0a Mon Sep 17 00:00:00 2001 From: Caleb Connolly Date: Sun, 7 Mar 2021 15:12:22 -0800 Subject: [PATCH 0029/1091] Input: s6sy761 - fix coordinate read bit shift The touch coordinate register contains the following: byte 3 byte 2 byte 1 +--------+--------+ +-----------------+ +-----------------+ | | | | | | | | X[3:0] | Y[3:0] | | Y[11:4] | | X[11:4] | | | | | | | | +--------+--------+ +-----------------+ +-----------------+ Bytes 2 and 1 need to be shifted left by 4 bits, the least significant nibble of each is stored in byte 3. Currently they are only being shifted by 3 causing the reported coordinates to be incorrect. This matches downstream examples, and has been confirmed on my device (OnePlus 7 Pro). Fixes: 0145a7141e59 ("Input: add support for the Samsung S6SY761 touchscreen") Signed-off-by: Caleb Connolly Reviewed-by: Andi Shyti Link: https://lore.kernel.org/r/20210305185710.225168-1-caleb@connolly.tech Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/s6sy761.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/s6sy761.c b/drivers/input/touchscreen/s6sy761.c index b63d7fdf0cd2..85a1f465c097 100644 --- a/drivers/input/touchscreen/s6sy761.c +++ b/drivers/input/touchscreen/s6sy761.c @@ -145,8 +145,8 @@ static void s6sy761_report_coordinates(struct s6sy761_data *sdata, u8 major = event[4]; u8 minor = event[5]; u8 z = event[6] & S6SY761_MASK_Z; - u16 x = (event[1] << 3) | ((event[3] & S6SY761_MASK_X) >> 4); - u16 y = (event[2] << 3) | (event[3] & S6SY761_MASK_Y); + u16 x = (event[1] << 4) | ((event[3] & S6SY761_MASK_X) >> 4); + u16 y = (event[2] << 4) | (event[3] & S6SY761_MASK_Y); input_mt_slot(sdata->input, tid); From 140a776833957539c84301dbdb4c3013876de118 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 8 Mar 2021 11:26:25 +0200 Subject: [PATCH 0030/1091] ARM: dts: Drop duplicate sha2md5_fck to fix clk_disable race We have a duplicate legacy clock defined for sha2md5_fck that can sometimes race with clk_disable() with the dts configured clock for OMAP4_SHA2MD5_CLKCTRL when unused clocks are disabled during boot causing an "Unhandled fault: imprecise external abort". Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap44xx-clocks.dtsi | 8 -------- 1 file changed, 8 deletions(-) diff --git a/arch/arm/boot/dts/omap44xx-clocks.dtsi b/arch/arm/boot/dts/omap44xx-clocks.dtsi index 532868591107..1f1c04d8f472 100644 --- a/arch/arm/boot/dts/omap44xx-clocks.dtsi +++ b/arch/arm/boot/dts/omap44xx-clocks.dtsi @@ -770,14 +770,6 @@ ti,max-div = <2>; }; - sha2md5_fck: sha2md5_fck@15c8 { - #clock-cells = <0>; - compatible = "ti,gate-clock"; - clocks = <&l3_div_ck>; - ti,bit-shift = <1>; - reg = <0x15c8>; - }; - usb_phy_cm_clk32k: usb_phy_cm_clk32k@640 { #clock-cells = <0>; compatible = "ti,gate-clock"; From 77335a040178a0456d4eabc8bf17a7ca3ee4a327 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Mon, 8 Mar 2021 11:30:45 +0200 Subject: [PATCH 0031/1091] ARM: dts: Fix moving mmc devices with aliases for omap4 & 5 Fix moving mmc devices with dts aliases as discussed on the lists. Without this we now have internal eMMC mmc1 show up as mmc2 compared to the earlier order of devices. Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap4.dtsi | 5 +++++ arch/arm/boot/dts/omap5.dtsi | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/arch/arm/boot/dts/omap4.dtsi b/arch/arm/boot/dts/omap4.dtsi index 72e4f6481776..4a9f9496a867 100644 --- a/arch/arm/boot/dts/omap4.dtsi +++ b/arch/arm/boot/dts/omap4.dtsi @@ -22,6 +22,11 @@ i2c1 = &i2c2; i2c2 = &i2c3; i2c3 = &i2c4; + mmc0 = &mmc1; + mmc1 = &mmc2; + mmc2 = &mmc3; + mmc3 = &mmc4; + mmc4 = &mmc5; serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; diff --git a/arch/arm/boot/dts/omap5.dtsi b/arch/arm/boot/dts/omap5.dtsi index e025b7c9a357..ee821d0ab364 100644 --- a/arch/arm/boot/dts/omap5.dtsi +++ b/arch/arm/boot/dts/omap5.dtsi @@ -25,6 +25,11 @@ i2c2 = &i2c3; i2c3 = &i2c4; i2c4 = &i2c5; + mmc0 = &mmc1; + mmc1 = &mmc2; + mmc2 = &mmc3; + mmc3 = &mmc4; + mmc4 = &mmc5; serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; From 36b87cf302a4f13f8b4344bcf98f67405a145e2f Mon Sep 17 00:00:00 2001 From: Shou-Chieh Hsu Date: Tue, 2 Mar 2021 11:58:01 +0800 Subject: [PATCH 0032/1091] HID: google: add don USB id Add 1 additional hammer-like device. Signed-off-by: Shou-Chieh Hsu Signed-off-by: Jiri Kosina --- drivers/hid/hid-google-hammer.c | 2 ++ drivers/hid/hid-ids.h | 1 + 2 files changed, 3 insertions(+) diff --git a/drivers/hid/hid-google-hammer.c b/drivers/hid/hid-google-hammer.c index d9319622da44..e60c31dd05ff 100644 --- a/drivers/hid/hid-google-hammer.c +++ b/drivers/hid/hid-google-hammer.c @@ -573,6 +573,8 @@ static void hammer_remove(struct hid_device *hdev) } static const struct hid_device_id hammer_devices[] = { + { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, + USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_DON) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, USB_VENDOR_ID_GOOGLE, USB_DEVICE_ID_GOOGLE_HAMMER) }, { HID_DEVICE(BUS_USB, HID_GROUP_GENERIC, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index e42aaae3138f..0b4929258478 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -493,6 +493,7 @@ #define USB_DEVICE_ID_GOOGLE_MASTERBALL 0x503c #define USB_DEVICE_ID_GOOGLE_MAGNEMITE 0x503d #define USB_DEVICE_ID_GOOGLE_MOONBALL 0x5044 +#define USB_DEVICE_ID_GOOGLE_DON 0x5050 #define USB_VENDOR_ID_GOTOP 0x08f2 #define USB_DEVICE_ID_SUPER_Q2 0x007f From 9a0b44fbfea1932196a4879b44a37dd182e984c5 Mon Sep 17 00:00:00 2001 From: Luke D Jones Date: Fri, 19 Feb 2021 10:10:02 +1300 Subject: [PATCH 0033/1091] HID: asus: Add support for 2021 ASUS N-Key keyboard Some new 2021 version of ASUS gamer laptops are using an updated N-Key keyboard with the PID of 0x19b6. This version is using the same init sequence and brightness control as the 0x1866 keyboard. Signed-off-by: Luke D Jones Signed-off-by: Jiri Kosina --- drivers/hid/hid-asus.c | 3 +++ drivers/hid/hid-ids.h | 1 + 2 files changed, 4 insertions(+) diff --git a/drivers/hid/hid-asus.c b/drivers/hid/hid-asus.c index 1dfe184ebf5a..2ab22b925941 100644 --- a/drivers/hid/hid-asus.c +++ b/drivers/hid/hid-asus.c @@ -1221,6 +1221,9 @@ static const struct hid_device_id asus_devices[] = { { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD), QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, + { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, + USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2), + QUIRK_USE_KBD_BACKLIGHT | QUIRK_ROG_NKEY_KEYBOARD }, { HID_USB_DEVICE(USB_VENDOR_ID_ASUSTEK, USB_DEVICE_ID_ASUSTEK_T100TA_KEYBOARD), QUIRK_T100_KEYBOARD | QUIRK_NO_CONSUMER_USAGES }, diff --git a/drivers/hid/hid-ids.h b/drivers/hid/hid-ids.h index 0b4929258478..67fd8a2f5aba 100644 --- a/drivers/hid/hid-ids.h +++ b/drivers/hid/hid-ids.h @@ -194,6 +194,7 @@ #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD2 0x1837 #define USB_DEVICE_ID_ASUSTEK_ROG_KEYBOARD3 0x1822 #define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD 0x1866 +#define USB_DEVICE_ID_ASUSTEK_ROG_NKEY_KEYBOARD2 0x19b6 #define USB_DEVICE_ID_ASUSTEK_FX503VD_KEYBOARD 0x1869 #define USB_VENDOR_ID_ATEN 0x0557 From fa8ba6e5dc0e78e409e503ddcfceef5dd96527f4 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Thu, 4 Mar 2021 05:19:57 -0800 Subject: [PATCH 0034/1091] HID: alps: fix error return code in alps_input_configured() When input_register_device() fails, no error return code is assigned. To fix this bug, ret is assigned with -ENOENT as error return code. Reported-by: TOTE Robot Signed-off-by: Jia-Ju Bai Signed-off-by: Jiri Kosina --- drivers/hid/hid-alps.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/hid/hid-alps.c b/drivers/hid/hid-alps.c index 3feaece13ade..6b665931147d 100644 --- a/drivers/hid/hid-alps.c +++ b/drivers/hid/hid-alps.c @@ -761,6 +761,7 @@ static int alps_input_configured(struct hid_device *hdev, struct hid_input *hi) if (input_register_device(data->input2)) { input_free_device(input2); + ret = -ENOENT; goto exit; } } From 7c911f9de7abb89f46254d2fecb11dcb4a7a6c30 Mon Sep 17 00:00:00 2001 From: Benjamin Li Date: Mon, 8 Mar 2021 15:09:15 +0200 Subject: [PATCH 0035/1091] interconnect: qcom: msm8939: remove rpm-ids from non-RPM nodes Some nodes are incorrectly marked as RPM-controlled (they have RPM master and slave ids assigned), but are actually controlled by the application CPU instead. The RPM complains when we send requests for resources that it can't control. Let's fix this by replacing the IDs, with the default "-1" in which case no requests are sent. See commit c497f9322af9 ("interconnect: qcom: msm8916: Remove rpm-ids from non-RPM nodes") where this was done for msm8916. Signed-off-by: Benjamin Li Reviewed-by: Jun Nie Link: https://lore.kernel.org/r/20210205015205.22947-3-benl@squareup.com Signed-off-by: Georgi Djakov --- drivers/interconnect/qcom/msm8939.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/interconnect/qcom/msm8939.c b/drivers/interconnect/qcom/msm8939.c index dfbec30ed149..20f31a1b4192 100644 --- a/drivers/interconnect/qcom/msm8939.c +++ b/drivers/interconnect/qcom/msm8939.c @@ -131,7 +131,7 @@ DEFINE_QNODE(mas_pcnoc_sdcc_1, MSM8939_MASTER_SDCC_1, 8, -1, -1, MSM8939_PNOC_IN DEFINE_QNODE(mas_pcnoc_sdcc_2, MSM8939_MASTER_SDCC_2, 8, -1, -1, MSM8939_PNOC_INT_1); DEFINE_QNODE(mas_qdss_bam, MSM8939_MASTER_QDSS_BAM, 8, -1, -1, MSM8939_SNOC_QDSS_INT); DEFINE_QNODE(mas_qdss_etr, MSM8939_MASTER_QDSS_ETR, 8, -1, -1, MSM8939_SNOC_QDSS_INT); -DEFINE_QNODE(mas_snoc_cfg, MSM8939_MASTER_SNOC_CFG, 4, 20, -1, MSM8939_SLAVE_SRVC_SNOC); +DEFINE_QNODE(mas_snoc_cfg, MSM8939_MASTER_SNOC_CFG, 4, -1, -1, MSM8939_SLAVE_SRVC_SNOC); DEFINE_QNODE(mas_spdm, MSM8939_MASTER_SPDM, 4, -1, -1, MSM8939_PNOC_MAS_0); DEFINE_QNODE(mas_tcu0, MSM8939_MASTER_TCU0, 16, -1, -1, MSM8939_SLAVE_EBI_CH0, MSM8939_BIMC_SNOC_MAS, MSM8939_SLAVE_AMPSS_L2); DEFINE_QNODE(mas_usb_hs1, MSM8939_MASTER_USB_HS1, 4, -1, -1, MSM8939_PNOC_MAS_1); @@ -156,14 +156,14 @@ DEFINE_QNODE(pcnoc_snoc_mas, MSM8939_PNOC_SNOC_MAS, 8, 29, -1, MSM8939_PNOC_SNOC DEFINE_QNODE(pcnoc_snoc_slv, MSM8939_PNOC_SNOC_SLV, 8, -1, 45, MSM8939_SNOC_INT_0, MSM8939_SNOC_INT_BIMC, MSM8939_SNOC_INT_1); DEFINE_QNODE(qdss_int, MSM8939_SNOC_QDSS_INT, 8, -1, -1, MSM8939_SNOC_INT_0, MSM8939_SNOC_INT_BIMC); DEFINE_QNODE(slv_apps_l2, MSM8939_SLAVE_AMPSS_L2, 16, -1, -1, 0); -DEFINE_QNODE(slv_apss, MSM8939_SLAVE_APSS, 4, -1, 20, 0); +DEFINE_QNODE(slv_apss, MSM8939_SLAVE_APSS, 4, -1, -1, 0); DEFINE_QNODE(slv_audio, MSM8939_SLAVE_LPASS, 4, -1, -1, 0); DEFINE_QNODE(slv_bimc_cfg, MSM8939_SLAVE_BIMC_CFG, 4, -1, -1, 0); DEFINE_QNODE(slv_blsp_1, MSM8939_SLAVE_BLSP_1, 4, -1, -1, 0); DEFINE_QNODE(slv_boot_rom, MSM8939_SLAVE_BOOT_ROM, 4, -1, -1, 0); DEFINE_QNODE(slv_camera_cfg, MSM8939_SLAVE_CAMERA_CFG, 4, -1, -1, 0); -DEFINE_QNODE(slv_cats_0, MSM8939_SLAVE_CATS_128, 16, -1, 106, 0); -DEFINE_QNODE(slv_cats_1, MSM8939_SLAVE_OCMEM_64, 8, -1, 107, 0); +DEFINE_QNODE(slv_cats_0, MSM8939_SLAVE_CATS_128, 16, -1, -1, 0); +DEFINE_QNODE(slv_cats_1, MSM8939_SLAVE_OCMEM_64, 8, -1, -1, 0); DEFINE_QNODE(slv_clk_ctl, MSM8939_SLAVE_CLK_CTL, 4, -1, -1, 0); DEFINE_QNODE(slv_crypto_0_cfg, MSM8939_SLAVE_CRYPTO_0_CFG, 4, -1, -1, 0); DEFINE_QNODE(slv_dehr_cfg, MSM8939_SLAVE_DEHR_CFG, 4, -1, -1, 0); @@ -187,20 +187,20 @@ DEFINE_QNODE(slv_sdcc_2, MSM8939_SLAVE_SDCC_2, 4, -1, -1, 0); DEFINE_QNODE(slv_security, MSM8939_SLAVE_SECURITY, 4, -1, -1, 0); DEFINE_QNODE(slv_snoc_cfg, MSM8939_SLAVE_SNOC_CFG, 4, -1, -1, 0); DEFINE_QNODE(slv_spdm, MSM8939_SLAVE_SPDM, 4, -1, -1, 0); -DEFINE_QNODE(slv_srvc_snoc, MSM8939_SLAVE_SRVC_SNOC, 8, -1, 29, 0); +DEFINE_QNODE(slv_srvc_snoc, MSM8939_SLAVE_SRVC_SNOC, 8, -1, -1, 0); DEFINE_QNODE(slv_tcsr, MSM8939_SLAVE_TCSR, 4, -1, -1, 0); DEFINE_QNODE(slv_tlmm, MSM8939_SLAVE_TLMM, 4, -1, -1, 0); DEFINE_QNODE(slv_usb_hs1, MSM8939_SLAVE_USB_HS1, 4, -1, -1, 0); DEFINE_QNODE(slv_usb_hs2, MSM8939_SLAVE_USB_HS2, 4, -1, -1, 0); DEFINE_QNODE(slv_venus_cfg, MSM8939_SLAVE_VENUS_CFG, 4, -1, -1, 0); -DEFINE_QNODE(snoc_bimc_0_mas, MSM8939_SNOC_BIMC_0_MAS, 16, 3, -1, MSM8939_SNOC_BIMC_0_SLV); -DEFINE_QNODE(snoc_bimc_0_slv, MSM8939_SNOC_BIMC_0_SLV, 16, -1, 24, MSM8939_SLAVE_EBI_CH0); +DEFINE_QNODE(snoc_bimc_0_mas, MSM8939_SNOC_BIMC_0_MAS, 16, -1, -1, MSM8939_SNOC_BIMC_0_SLV); +DEFINE_QNODE(snoc_bimc_0_slv, MSM8939_SNOC_BIMC_0_SLV, 16, -1, -1, MSM8939_SLAVE_EBI_CH0); DEFINE_QNODE(snoc_bimc_1_mas, MSM8939_SNOC_BIMC_1_MAS, 16, 76, -1, MSM8939_SNOC_BIMC_1_SLV); DEFINE_QNODE(snoc_bimc_1_slv, MSM8939_SNOC_BIMC_1_SLV, 16, -1, 104, MSM8939_SLAVE_EBI_CH0); DEFINE_QNODE(snoc_bimc_2_mas, MSM8939_SNOC_BIMC_2_MAS, 16, -1, -1, MSM8939_SNOC_BIMC_2_SLV); DEFINE_QNODE(snoc_bimc_2_slv, MSM8939_SNOC_BIMC_2_SLV, 16, -1, -1, MSM8939_SLAVE_EBI_CH0); DEFINE_QNODE(snoc_int_0, MSM8939_SNOC_INT_0, 8, 99, 130, MSM8939_SLAVE_QDSS_STM, MSM8939_SLAVE_IMEM, MSM8939_SNOC_PNOC_MAS); -DEFINE_QNODE(snoc_int_1, MSM8939_SNOC_INT_1, 8, 100, 131, MSM8939_SLAVE_APSS, MSM8939_SLAVE_CATS_128, MSM8939_SLAVE_OCMEM_64); +DEFINE_QNODE(snoc_int_1, MSM8939_SNOC_INT_1, 8, -1, -1, MSM8939_SLAVE_APSS, MSM8939_SLAVE_CATS_128, MSM8939_SLAVE_OCMEM_64); DEFINE_QNODE(snoc_int_bimc, MSM8939_SNOC_INT_BIMC, 8, 101, 132, MSM8939_SNOC_BIMC_1_MAS); DEFINE_QNODE(snoc_pcnoc_mas, MSM8939_SNOC_PNOC_MAS, 8, -1, -1, MSM8939_SNOC_PNOC_SLV); DEFINE_QNODE(snoc_pcnoc_slv, MSM8939_SNOC_PNOC_SLV, 8, -1, -1, MSM8939_PNOC_INT_0); From 715ea61532e731c62392221238906704e63d75b6 Mon Sep 17 00:00:00 2001 From: Jia-Ju Bai Date: Mon, 8 Mar 2021 15:09:15 +0200 Subject: [PATCH 0036/1091] interconnect: core: fix error return code of icc_link_destroy() When krealloc() fails and new is NULL, no error return code of icc_link_destroy() is assigned. To fix this bug, ret is assigned with -ENOMEM hen new is NULL. Reported-by: TOTE Robot Signed-off-by: Jia-Ju Bai Link: https://lore.kernel.org/r/20210306132857.17020-1-baijiaju1990@gmail.com Signed-off-by: Georgi Djakov --- drivers/interconnect/core.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/interconnect/core.c b/drivers/interconnect/core.c index 5ad519c9f239..8a1e70e00876 100644 --- a/drivers/interconnect/core.c +++ b/drivers/interconnect/core.c @@ -942,6 +942,8 @@ int icc_link_destroy(struct icc_node *src, struct icc_node *dst) GFP_KERNEL); if (new) src->links = new; + else + ret = -ENOMEM; out: mutex_unlock(&icc_lock); From 2a2b09c867fdac63f430a45051e7bd0c46edc381 Mon Sep 17 00:00:00 2001 From: Douglas Gilbert Date: Sat, 9 Jan 2021 17:36:58 -0500 Subject: [PATCH 0037/1091] HID cp2112: fix support for multiple gpiochips In lk 5.11.0-rc2 connecting a USB based Silicon Labs HID to I2C bridge evaluation board (CP2112EK) causes this warning: gpio gpiochip0: (cp2112_gpio): detected irqchip that is shared with multiple gpiochips: please fix the driver Simply copy what other gpio related drivers do to fix this particular warning: replicate the struct irq_chip object in each device instance rather than have a static object which makes that object (incorrectly) shared by each device. Signed-off-by: Douglas Gilbert Signed-off-by: Jiri Kosina --- drivers/hid/hid-cp2112.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/hid/hid-cp2112.c b/drivers/hid/hid-cp2112.c index 21e15627a461..477baa30889c 100644 --- a/drivers/hid/hid-cp2112.c +++ b/drivers/hid/hid-cp2112.c @@ -161,6 +161,7 @@ struct cp2112_device { atomic_t read_avail; atomic_t xfer_avail; struct gpio_chip gc; + struct irq_chip irq; u8 *in_out_buffer; struct mutex lock; @@ -1175,16 +1176,6 @@ static int cp2112_gpio_irq_type(struct irq_data *d, unsigned int type) return 0; } -static struct irq_chip cp2112_gpio_irqchip = { - .name = "cp2112-gpio", - .irq_startup = cp2112_gpio_irq_startup, - .irq_shutdown = cp2112_gpio_irq_shutdown, - .irq_ack = cp2112_gpio_irq_ack, - .irq_mask = cp2112_gpio_irq_mask, - .irq_unmask = cp2112_gpio_irq_unmask, - .irq_set_type = cp2112_gpio_irq_type, -}; - static int __maybe_unused cp2112_allocate_irq(struct cp2112_device *dev, int pin) { @@ -1339,8 +1330,17 @@ static int cp2112_probe(struct hid_device *hdev, const struct hid_device_id *id) dev->gc.can_sleep = 1; dev->gc.parent = &hdev->dev; + dev->irq.name = "cp2112-gpio"; + dev->irq.irq_startup = cp2112_gpio_irq_startup; + dev->irq.irq_shutdown = cp2112_gpio_irq_shutdown; + dev->irq.irq_ack = cp2112_gpio_irq_ack; + dev->irq.irq_mask = cp2112_gpio_irq_mask; + dev->irq.irq_unmask = cp2112_gpio_irq_unmask; + dev->irq.irq_set_type = cp2112_gpio_irq_type; + dev->irq.flags = IRQCHIP_MASK_ON_SUSPEND; + girq = &dev->gc.irq; - girq->chip = &cp2112_gpio_irqchip; + girq->chip = &dev->irq; /* The event comes from the outside so no parent handler */ girq->parent_handler = NULL; girq->num_parents = 0; From e29c62ffb008829dc8bcc0a2ec438adc25a8255e Mon Sep 17 00:00:00 2001 From: Jiapeng Zhong Date: Wed, 20 Jan 2021 15:34:30 +0800 Subject: [PATCH 0038/1091] HID: wacom: Assign boolean values to a bool variable Fix the following coccicheck warnings: ./drivers/hid/wacom_wac.c:2536:2-6: WARNING: Assignment of 0/1 to bool variable. Reported-by: Abaci Robot Signed-off-by: Jiapeng Zhong Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index 44d715c12f6a..bdd9ba577150 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -2533,7 +2533,7 @@ static void wacom_wac_finger_slot(struct wacom_wac *wacom_wac, !wacom_wac->shared->is_touch_on) { if (!wacom_wac->shared->touch_down) return; - prox = 0; + prox = false; } wacom_wac->hid_data.num_received++; From 97e2b5e5dcd543cd4d85ecb1bfa2a9721a08f411 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 5 Mar 2021 17:34:28 +0000 Subject: [PATCH 0039/1091] ASoC: cs42l42: Fix Bitclock polarity inversion The driver was setting bit clock polarity opposite to intended polarity. Also simplify the code by grouping ADC and DAC clock configurations into a single field. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210305173442.195740-2-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 20 ++++++++------------ sound/soc/codecs/cs42l42.h | 11 ++++++----- 2 files changed, 14 insertions(+), 17 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 210fcbedf241..df0d5fec0287 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -797,27 +797,23 @@ static int cs42l42_set_dai_fmt(struct snd_soc_dai *codec_dai, unsigned int fmt) /* Bitclock/frame inversion */ switch (fmt & SND_SOC_DAIFMT_INV_MASK) { case SND_SOC_DAIFMT_NB_NF: + asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT; break; case SND_SOC_DAIFMT_NB_IF: - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_LCPOL_IN_SHIFT; + asp_cfg_val |= CS42L42_ASP_SCPOL_NOR << CS42L42_ASP_SCPOL_SHIFT; + asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT; break; case SND_SOC_DAIFMT_IB_NF: - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_SCPOL_IN_DAC_SHIFT; break; case SND_SOC_DAIFMT_IB_IF: - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_LCPOL_IN_SHIFT; - asp_cfg_val |= CS42L42_ASP_POL_INV << - CS42L42_ASP_SCPOL_IN_DAC_SHIFT; + asp_cfg_val |= CS42L42_ASP_LCPOL_INV << CS42L42_ASP_LCPOL_SHIFT; break; } - snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG, - CS42L42_ASP_MODE_MASK | - CS42L42_ASP_SCPOL_IN_DAC_MASK | - CS42L42_ASP_LCPOL_IN_MASK, asp_cfg_val); + snd_soc_component_update_bits(component, CS42L42_ASP_CLK_CFG, CS42L42_ASP_MODE_MASK | + CS42L42_ASP_SCPOL_MASK | + CS42L42_ASP_LCPOL_MASK, + asp_cfg_val); return 0; } diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 9e3cc528dcff..1f0d67c95a9a 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -258,11 +258,12 @@ #define CS42L42_ASP_SLAVE_MODE 0x00 #define CS42L42_ASP_MODE_SHIFT 4 #define CS42L42_ASP_MODE_MASK (1 << CS42L42_ASP_MODE_SHIFT) -#define CS42L42_ASP_SCPOL_IN_DAC_SHIFT 2 -#define CS42L42_ASP_SCPOL_IN_DAC_MASK (1 << CS42L42_ASP_SCPOL_IN_DAC_SHIFT) -#define CS42L42_ASP_LCPOL_IN_SHIFT 0 -#define CS42L42_ASP_LCPOL_IN_MASK (1 << CS42L42_ASP_LCPOL_IN_SHIFT) -#define CS42L42_ASP_POL_INV 1 +#define CS42L42_ASP_SCPOL_SHIFT 2 +#define CS42L42_ASP_SCPOL_MASK (3 << CS42L42_ASP_SCPOL_SHIFT) +#define CS42L42_ASP_SCPOL_NOR 3 +#define CS42L42_ASP_LCPOL_SHIFT 0 +#define CS42L42_ASP_LCPOL_MASK (3 << CS42L42_ASP_LCPOL_SHIFT) +#define CS42L42_ASP_LCPOL_INV 3 #define CS42L42_ASP_FRM_CFG (CS42L42_PAGE_12 + 0x08) #define CS42L42_ASP_STP_SHIFT 4 From 3656667e66858fef45017c8e7c73e9918ed23915 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 5 Mar 2021 17:34:29 +0000 Subject: [PATCH 0040/1091] ASoC: cs42l42: Fix channel width support Remove the hard coded 32 bits width and replace with the correct width calculated by params_width. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210305173442.195740-3-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 47 ++++++++++++++++++-------------------- sound/soc/codecs/cs42l42.h | 1 - 2 files changed, 22 insertions(+), 26 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index df0d5fec0287..4f9ad9547929 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -691,24 +691,6 @@ static int cs42l42_pll_config(struct snd_soc_component *component) CS42L42_CLK_OASRC_SEL_MASK, CS42L42_CLK_OASRC_SEL_12 << CS42L42_CLK_OASRC_SEL_SHIFT); - /* channel 1 on low LRCLK, 32 bit */ - snd_soc_component_update_bits(component, - CS42L42_ASP_RX_DAI0_CH1_AP_RES, - CS42L42_ASP_RX_CH_AP_MASK | - CS42L42_ASP_RX_CH_RES_MASK, - (CS42L42_ASP_RX_CH_AP_LOW << - CS42L42_ASP_RX_CH_AP_SHIFT) | - (CS42L42_ASP_RX_CH_RES_32 << - CS42L42_ASP_RX_CH_RES_SHIFT)); - /* Channel 2 on high LRCLK, 32 bit */ - snd_soc_component_update_bits(component, - CS42L42_ASP_RX_DAI0_CH2_AP_RES, - CS42L42_ASP_RX_CH_AP_MASK | - CS42L42_ASP_RX_CH_RES_MASK, - (CS42L42_ASP_RX_CH_AP_HI << - CS42L42_ASP_RX_CH_AP_SHIFT) | - (CS42L42_ASP_RX_CH_RES_32 << - CS42L42_ASP_RX_CH_RES_SHIFT)); if (pll_ratio_table[i].mclk_src_sel == 0) { /* Pass the clock straight through */ snd_soc_component_update_bits(component, @@ -824,14 +806,29 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); - int retval; + unsigned int width = (params_width(params) / 8) - 1; + unsigned int val = 0; cs42l42->srate = params_rate(params); - cs42l42->swidth = params_width(params); - retval = cs42l42_pll_config(component); + switch(substream->stream) { + case SNDRV_PCM_STREAM_PLAYBACK: + val |= width << CS42L42_ASP_RX_CH_RES_SHIFT; + /* channel 1 on low LRCLK */ + snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH1_AP_RES, + CS42L42_ASP_RX_CH_AP_MASK | + CS42L42_ASP_RX_CH_RES_MASK, val); + /* Channel 2 on high LRCLK */ + val |= CS42L42_ASP_RX_CH_AP_HI << CS42L42_ASP_RX_CH_AP_SHIFT; + snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_CH2_AP_RES, + CS42L42_ASP_RX_CH_AP_MASK | + CS42L42_ASP_RX_CH_RES_MASK, val); + break; + default: + break; + } - return retval; + return cs42l42_pll_config(component); } static int cs42l42_set_sysclk(struct snd_soc_dai *dai, @@ -896,9 +893,9 @@ static int cs42l42_mute(struct snd_soc_dai *dai, int mute, int direction) return 0; } -#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S18_3LE | \ - SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S24_LE | \ - SNDRV_PCM_FMTBIT_S32_LE) +#define CS42L42_FORMATS (SNDRV_PCM_FMTBIT_S16_LE |\ + SNDRV_PCM_FMTBIT_S24_LE |\ + SNDRV_PCM_FMTBIT_S32_LE ) static const struct snd_soc_dai_ops cs42l42_ops = { diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 1f0d67c95a9a..9b017b76828a 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -757,7 +757,6 @@ struct cs42l42_private { struct completion pdn_done; u32 sclk; u32 srate; - u32 swidth; u8 plug_state; u8 hs_type; u8 ts_inv; From a2ddc577ee4641889bf105d4d6e05be415bd4462 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 5 Mar 2021 17:34:30 +0000 Subject: [PATCH 0041/1091] ASoC: cs42l42: Fix mixer volume control The minimum value is 0x3f (-63dB), which also is mute Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210305173442.195740-4-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 4f9ad9547929..d5078ce79fad 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -401,7 +401,7 @@ static const struct regmap_config cs42l42_regmap = { }; static DECLARE_TLV_DB_SCALE(adc_tlv, -9600, 100, false); -static DECLARE_TLV_DB_SCALE(mixer_tlv, -6200, 100, false); +static DECLARE_TLV_DB_SCALE(mixer_tlv, -6300, 100, true); static const char * const cs42l42_hpf_freq_text[] = { "1.86Hz", "120Hz", "235Hz", "466Hz" @@ -458,7 +458,7 @@ static const struct snd_kcontrol_new cs42l42_snd_controls[] = { CS42L42_DAC_HPF_EN_SHIFT, true, false), SOC_DOUBLE_R_TLV("Mixer Volume", CS42L42_MIXER_CHA_VOL, CS42L42_MIXER_CHB_VOL, CS42L42_MIXER_CH_VOL_SHIFT, - 0x3e, 1, mixer_tlv) + 0x3f, 1, mixer_tlv) }; static int cs42l42_hpdrv_evt(struct snd_soc_dapm_widget *w, From 9ad4f9ea976e05d4eba62ea58c7c7c45705b80a1 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 5 Mar 2021 17:34:31 +0000 Subject: [PATCH 0042/1091] ASoC: cs42l42: Don't enable/disable regulator at Bias Level dev_pm_ops already enable/disable the codec if not in use Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210305173442.195740-5-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index d5078ce79fad..eee3fc320030 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -511,43 +511,6 @@ static const struct snd_soc_dapm_route cs42l42_audio_map[] = { {"HP", NULL, "HPDRV"} }; -static int cs42l42_set_bias_level(struct snd_soc_component *component, - enum snd_soc_bias_level level) -{ - struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); - int ret; - - switch (level) { - case SND_SOC_BIAS_ON: - break; - case SND_SOC_BIAS_PREPARE: - break; - case SND_SOC_BIAS_STANDBY: - if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF) { - regcache_cache_only(cs42l42->regmap, false); - regcache_sync(cs42l42->regmap); - ret = regulator_bulk_enable( - ARRAY_SIZE(cs42l42->supplies), - cs42l42->supplies); - if (ret != 0) { - dev_err(component->dev, - "Failed to enable regulators: %d\n", - ret); - return ret; - } - } - break; - case SND_SOC_BIAS_OFF: - - regcache_cache_only(cs42l42->regmap, true); - regulator_bulk_disable(ARRAY_SIZE(cs42l42->supplies), - cs42l42->supplies); - break; - } - - return 0; -} - static int cs42l42_component_probe(struct snd_soc_component *component) { struct cs42l42_private *cs42l42 = @@ -560,7 +523,6 @@ static int cs42l42_component_probe(struct snd_soc_component *component) static const struct snd_soc_component_driver soc_component_dev_cs42l42 = { .probe = cs42l42_component_probe, - .set_bias_level = cs42l42_set_bias_level, .dapm_widgets = cs42l42_dapm_widgets, .num_dapm_widgets = ARRAY_SIZE(cs42l42_dapm_widgets), .dapm_routes = cs42l42_audio_map, From ddaa9bea4ffaba50f814585f294a5d98641b41ad Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Fri, 5 Mar 2021 17:34:32 +0000 Subject: [PATCH 0043/1091] ASoC: cs42l42: Always wait at least 3ms after reset This delay is part of the power-up sequence defined in the datasheet. A runtime_resume is a power-up so must also include the delay. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210305173442.195740-6-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 3 ++- sound/soc/codecs/cs42l42.h | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index eee3fc320030..811b7b1c9732 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -1756,7 +1756,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, dev_dbg(&i2c_client->dev, "Found reset GPIO\n"); gpiod_set_value_cansleep(cs42l42->reset_gpio, 1); } - mdelay(3); + usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); /* Request IRQ */ ret = devm_request_threaded_irq(&i2c_client->dev, @@ -1881,6 +1881,7 @@ static int cs42l42_runtime_resume(struct device *dev) } gpiod_set_value_cansleep(cs42l42->reset_gpio, 1); + usleep_range(CS42L42_BOOT_TIME_US, CS42L42_BOOT_TIME_US * 2); regcache_cache_only(cs42l42->regmap, false); regcache_sync(cs42l42->regmap); diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 9b017b76828a..866d7c873e3c 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -740,6 +740,7 @@ #define CS42L42_FRAC2_VAL(val) (((val) & 0xff0000) >> 16) #define CS42L42_NUM_SUPPLIES 5 +#define CS42L42_BOOT_TIME_US 3000 static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = { "VA", From a9e54f4b62dcfed4432a5a89b1cd5903737f6e83 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 28 Jan 2021 13:12:17 +0100 Subject: [PATCH 0044/1091] AMD_SFH: Removed unused activecontrolstatus member from the amd_mp2_dev struct This value is only used once inside amd_mp2_get_sensor_num(), so there is no need to store this in the amd_mp2_dev struct, amd_mp2_get_sensor_num() can simple use a local variable for this. Fixes: 4f567b9f8141 ("SFH: PCIe driver to add support of AMD sensor fusion hub") Signed-off-by: Hans de Goede Acked-by: Sandeep Singh --- drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 6 ++++-- drivers/hid/amd-sfh-hid/amd_sfh_pcie.h | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c index dbac16641662..f3cdb4ea33da 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c @@ -76,9 +76,11 @@ void amd_stop_all_sensors(struct amd_mp2_dev *privdata) int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) { int activestatus, num_of_sensors = 0; + u32 activecontrolstatus; + + activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3); + activestatus = activecontrolstatus >> 4; - privdata->activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3); - activestatus = privdata->activecontrolstatus >> 4; if (ACEL_EN & activestatus) sensor_id[num_of_sensors++] = accel_idx; diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h index 8f8d19b2cfe5..489415f7c22c 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.h @@ -61,7 +61,6 @@ struct amd_mp2_dev { struct pci_dev *pdev; struct amdtp_cl_data *cl_data; void __iomem *mmio; - u32 activecontrolstatus; }; struct amd_mp2_sensor_info { From 952f7d10c6b1685c6700fb24cf4ecbcf26ede77e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 28 Jan 2021 13:12:18 +0100 Subject: [PATCH 0045/1091] AMD_SFH: Add sensor_mask module parameter Add a sensor_mask module parameter which can be used to override the sensor-mask read from the activestatus bits of the AMD_P2C_MSG3 registers. Some BIOS-es do not program the activestatus bits, leading to the AMD-SFH driver not registering any HID devices even though the laptop in question does actually have sensors. While at it also fix the wrong indentation of the MAGNO_EN define. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199715 BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1651886 Fixes: 4f567b9f8141 ("SFH: PCIe driver to add support of AMD sensor fusion hub") Suggested-by: Richard Neumann Signed-off-by: Hans de Goede Acked-by: Sandeep Singh --- drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c index f3cdb4ea33da..ab0a9443e252 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c @@ -22,9 +22,13 @@ #define ACEL_EN BIT(0) #define GYRO_EN BIT(1) -#define MAGNO_EN BIT(2) +#define MAGNO_EN BIT(2) #define ALS_EN BIT(19) +static int sensor_mask_override = -1; +module_param_named(sensor_mask, sensor_mask_override, int, 0444); +MODULE_PARM_DESC(sensor_mask, "override the detected sensors mask"); + void amd_start_sensor(struct amd_mp2_dev *privdata, struct amd_mp2_sensor_info info) { union sfh_cmd_param cmd_param; @@ -78,8 +82,12 @@ int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) int activestatus, num_of_sensors = 0; u32 activecontrolstatus; - activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3); - activestatus = activecontrolstatus >> 4; + if (sensor_mask_override >= 0) { + activestatus = sensor_mask_override; + } else { + activecontrolstatus = readl(privdata->mmio + AMD_P2C_MSG3); + activestatus = activecontrolstatus >> 4; + } if (ACEL_EN & activestatus) sensor_id[num_of_sensors++] = accel_idx; From 25615e454a0ec198254f17d2ed79b607cb755d0e Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 28 Jan 2021 13:12:19 +0100 Subject: [PATCH 0046/1091] AMD_SFH: Add DMI quirk table for BIOS-es which don't set the activestatus bits Some BIOS-es do not initialize the activestatus bits of the AMD_P2C_MSG3 register. This cause the AMD_SFH driver to not register any sensors even though the laptops in question do have sensors. Add a DMI quirk-table for specifying sensor-mask overrides based on DMI match, to make the sensors work OOTB on these laptop models. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=199715 BugLink: https://bugzilla.redhat.com/show_bug.cgi?id=1651886 Fixes: 4f567b9f8141 ("SFH: PCIe driver to add support of AMD sensor fusion hub") Signed-off-by: Hans de Goede Acked-by: Sandeep Singh --- drivers/hid/amd-sfh-hid/amd_sfh_pcie.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c index ab0a9443e252..ddecc84fd6f0 100644 --- a/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c +++ b/drivers/hid/amd-sfh-hid/amd_sfh_pcie.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -77,11 +78,34 @@ void amd_stop_all_sensors(struct amd_mp2_dev *privdata) writel(cmd_base.ul, privdata->mmio + AMD_C2P_MSG0); } +static const struct dmi_system_id dmi_sensor_mask_overrides[] = { + { + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY x360 Convertible 13-ag0xxx"), + }, + .driver_data = (void *)(ACEL_EN | MAGNO_EN), + }, + { + .matches = { + DMI_MATCH(DMI_PRODUCT_NAME, "HP ENVY x360 Convertible 15-cp0xxx"), + }, + .driver_data = (void *)(ACEL_EN | MAGNO_EN), + }, + { } +}; + int amd_mp2_get_sensor_num(struct amd_mp2_dev *privdata, u8 *sensor_id) { int activestatus, num_of_sensors = 0; + const struct dmi_system_id *dmi_id; u32 activecontrolstatus; + if (sensor_mask_override == -1) { + dmi_id = dmi_first_match(dmi_sensor_mask_overrides); + if (dmi_id) + sensor_mask_override = (long)dmi_id->driver_data; + } + if (sensor_mask_override >= 0) { activestatus = sensor_mask_override; } else { From 7029e783027706b427bbfbdf8558252c1dac6fa0 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Sun, 3 Jan 2021 14:56:12 +0100 Subject: [PATCH 0047/1091] remoteproc: qcom: pil_info: avoid 64-bit division On 32-bit machines with 64-bit resource_size_t, the driver causes a link failure because of the 64-bit division: arm-linux-gnueabi-ld: drivers/remoteproc/qcom_pil_info.o: in function `qcom_pil_info_store': qcom_pil_info.c:(.text+0x1ec): undefined reference to `__aeabi_uldivmod' Add a cast to an u32 to avoid this. If the resource exceeds 4GB, there are bigger problems. Fixes: 549b67da660d ("remoteproc: qcom: Introduce helper to store pil info in IMEM") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210103135628.3702427-1-arnd@kernel.org Signed-off-by: Bjorn Andersson --- drivers/remoteproc/qcom_pil_info.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/qcom_pil_info.c b/drivers/remoteproc/qcom_pil_info.c index 5521c4437ffa..7c007dd7b200 100644 --- a/drivers/remoteproc/qcom_pil_info.c +++ b/drivers/remoteproc/qcom_pil_info.c @@ -56,7 +56,7 @@ static int qcom_pil_info_init(void) memset_io(base, 0, resource_size(&imem)); _reloc.base = base; - _reloc.num_entries = resource_size(&imem) / PIL_RELOC_ENTRY_SIZE; + _reloc.num_entries = (u32)resource_size(&imem) / PIL_RELOC_ENTRY_SIZE; return 0; } From 5f140174988edc739530ed9f2220e458a488b10a Mon Sep 17 00:00:00 2001 From: Mathieu Poirier Date: Mon, 4 Jan 2021 10:16:18 -0700 Subject: [PATCH 0048/1091] MAINTAINERS: Add co-maintainer for remoteproc/RPMSG subsystems After discussing with Bjorn, stepping forward to help with the maintenance of the remoteproc and RPMSG subsystems. Signed-off-by: Mathieu Poirier Link: https://lore.kernel.org/r/20210104171618.2702461-1-mathieu.poirier@linaro.org Signed-off-by: Bjorn Andersson --- MAINTAINERS | 2 ++ 1 file changed, 2 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index d92f85ca831d..b75658c9797c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15205,6 +15205,7 @@ F: fs/reiserfs/ REMOTE PROCESSOR (REMOTEPROC) SUBSYSTEM M: Ohad Ben-Cohen M: Bjorn Andersson +M: Mathieu Poirier L: linux-remoteproc@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git rproc-next @@ -15218,6 +15219,7 @@ F: include/linux/remoteproc/ REMOTE PROCESSOR MESSAGING (RPMSG) SUBSYSTEM M: Ohad Ben-Cohen M: Bjorn Andersson +M: Mathieu Poirier L: linux-remoteproc@vger.kernel.org S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/andersson/remoteproc.git rpmsg-next From e6d9423d31b2f9bdd0220fd0584e3bb6ed2c4e52 Mon Sep 17 00:00:00 2001 From: Dimitar Dimitrov Date: Wed, 30 Dec 2020 12:50:05 +0200 Subject: [PATCH 0049/1091] remoteproc: pru: Fix loading of GNU Binutils ELF PRU port of GNU Binutils lacks support for separate address spaces. PRU IRAM addresses are marked with artificial offset to differentiate them from DRAM addresses. Hence remoteproc must mask IRAM addresses coming from GNU ELF in order to get the true hardware address. PRU firmware used for testing was the example in: https://github.com/dinuxbg/pru-gcc-examples/tree/master/blinking-led/pru Signed-off-by: Dimitar Dimitrov Link: https://lore.kernel.org/r/20201230105005.30492-1-dimitar@dinux.eu Signed-off-by: Bjorn Andersson --- drivers/remoteproc/pru_rproc.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 2667919d76b3..5fad787ba012 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -450,6 +450,24 @@ static void *pru_i_da_to_va(struct pru_rproc *pru, u32 da, size_t len) if (len == 0) return NULL; + /* + * GNU binutils do not support multiple address spaces. The GNU + * linker's default linker script places IRAM at an arbitrary high + * offset, in order to differentiate it from DRAM. Hence we need to + * strip the artificial offset in the IRAM addresses coming from the + * ELF file. + * + * The TI proprietary linker would never set those higher IRAM address + * bits anyway. PRU architecture limits the program counter to 16-bit + * word-address range. This in turn corresponds to 18-bit IRAM + * byte-address range for ELF. + * + * Two more bits are added just in case to make the final 20-bit mask. + * Idea is to have a safeguard in case TI decides to add banking + * in future SoCs. + */ + da &= 0xfffff; + if (da >= PRU_IRAM_DA && da + len <= PRU_IRAM_DA + pru->mem_regions[PRU_IOMEM_IRAM].size) { offset = da - PRU_IRAM_DA; From 77e141266c8e72e4a586fe42eaab1b4b047655ed Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 8 Mar 2021 18:49:10 +0200 Subject: [PATCH 0050/1091] pinctrl: intel: Show the GPIO base calculation explicitly During the split of intel_pinctrl_add_padgroups(), the _by_size() variant missed the GPIO base calculations and hence made unable to retrieve proper GPIO number. Assign the gpio_base explicitly in _by_size() variant. While at it, differentiate NOMAP case with the rest in _by_gpps() variant. Fixes: 036e126c72eb ("pinctrl: intel: Split intel_pinctrl_add_padgroups() for better maintenance") Reported-and-tested-by: Maximilian Luz Signed-off-by: Andy Shevchenko Acked-by: Mika Westerberg --- drivers/pinctrl/intel/pinctrl-intel.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 8085782cd8f9..7283203861ae 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1357,6 +1357,7 @@ static int intel_pinctrl_add_padgroups_by_gpps(struct intel_pinctrl *pctrl, gpps[i].gpio_base = 0; break; case INTEL_GPIO_BASE_NOMAP: + break; default: break; } @@ -1393,6 +1394,7 @@ static int intel_pinctrl_add_padgroups_by_size(struct intel_pinctrl *pctrl, gpps[i].size = min(gpp_size, npins); npins -= gpps[i].size; + gpps[i].gpio_base = gpps[i].base; gpps[i].padown_num = padown_num; /* From ab5eb336411f18fd449a1fb37d36a55ec422603f Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Thu, 25 Feb 2021 11:42:46 -0800 Subject: [PATCH 0051/1091] xtensa: move coprocessor_flush to the .text section coprocessor_flush is not a part of fast exception handlers, but it uses parts of fast coprocessor handling code that's why it's in the same source file. It uses call0 opcode to invoke those parts so there are no limitations on their relative location, but the rest of the code calls coprocessor_flush with call8 and that doesn't work when vectors are placed in a different gigabyte-aligned area than the rest of the kernel. Move coprocessor_flush from the .exception.text section to the .text so that it's reachable from the rest of the kernel with call8. Cc: stable@vger.kernel.org Signed-off-by: Max Filippov --- arch/xtensa/kernel/coprocessor.S | 64 ++++++++++++++++---------------- 1 file changed, 33 insertions(+), 31 deletions(-) diff --git a/arch/xtensa/kernel/coprocessor.S b/arch/xtensa/kernel/coprocessor.S index c426b846beef..45cc0ae0af6f 100644 --- a/arch/xtensa/kernel/coprocessor.S +++ b/arch/xtensa/kernel/coprocessor.S @@ -99,37 +99,6 @@ LOAD_CP_REGS_TAB(6) LOAD_CP_REGS_TAB(7) -/* - * coprocessor_flush(struct thread_info*, index) - * a2 a3 - * - * Save coprocessor registers for coprocessor 'index'. - * The register values are saved to or loaded from the coprocessor area - * inside the task_info structure. - * - * Note that this function doesn't update the coprocessor_owner information! - * - */ - -ENTRY(coprocessor_flush) - - /* reserve 4 bytes on stack to save a0 */ - abi_entry(4) - - s32i a0, a1, 0 - movi a0, .Lsave_cp_regs_jump_table - addx8 a3, a3, a0 - l32i a4, a3, 4 - l32i a3, a3, 0 - add a2, a2, a4 - beqz a3, 1f - callx0 a3 -1: l32i a0, a1, 0 - - abi_ret(4) - -ENDPROC(coprocessor_flush) - /* * Entry condition: * @@ -245,6 +214,39 @@ ENTRY(fast_coprocessor) ENDPROC(fast_coprocessor) + .text + +/* + * coprocessor_flush(struct thread_info*, index) + * a2 a3 + * + * Save coprocessor registers for coprocessor 'index'. + * The register values are saved to or loaded from the coprocessor area + * inside the task_info structure. + * + * Note that this function doesn't update the coprocessor_owner information! + * + */ + +ENTRY(coprocessor_flush) + + /* reserve 4 bytes on stack to save a0 */ + abi_entry(4) + + s32i a0, a1, 0 + movi a0, .Lsave_cp_regs_jump_table + addx8 a3, a3, a0 + l32i a4, a3, 4 + l32i a3, a3, 0 + add a2, a2, a4 + beqz a3, 1f + callx0 a3 +1: l32i a0, a1, 0 + + abi_ret(4) + +ENDPROC(coprocessor_flush) + .data ENTRY(coprocessor_owner) From 2d8aaa1720c6128ce263a2afcd3f8ee2e5551af8 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Mon, 8 Mar 2021 11:40:30 -0800 Subject: [PATCH 0052/1091] Input: n64joy - fix return value check in n64joy_probe() In case of error, the function devm_platform_ioremap_resource() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Fixes: 3bdffa8ffb45 ("Input: Add N64 controller driver") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Reviewed-by: Lauri Kasanen Link: https://lore.kernel.org/r/20210308122856.2177071-1-weiyongjun1@huawei.com Signed-off-by: Dmitry Torokhov --- drivers/input/joystick/n64joy.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/input/joystick/n64joy.c b/drivers/input/joystick/n64joy.c index 8bcc529942bc..9dbca366613e 100644 --- a/drivers/input/joystick/n64joy.c +++ b/drivers/input/joystick/n64joy.c @@ -252,8 +252,8 @@ static int __init n64joy_probe(struct platform_device *pdev) mutex_init(&priv->n64joy_mutex); priv->reg_base = devm_platform_ioremap_resource(pdev, 0); - if (!priv->reg_base) { - err = -EINVAL; + if (IS_ERR(priv->reg_base)) { + err = PTR_ERR(priv->reg_base); goto fail; } From 8106efdce03673d5ba963ced2db47d669d2dec82 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:07 -0600 Subject: [PATCH 0053/1091] ASoC: qcom: lpass-hdmi: remove useless return cppcheck warning: sound/soc/qcom/lpass-hdmi.c:189:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/qcom/lpass-hdmi.c:186:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/qcom/lpass-hdmi.c:189:9: note: Returning identical expression 'ret' return ret; ^ sound/soc/qcom/lpass-hdmi.c:206:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/qcom/lpass-hdmi.c:203:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/qcom/lpass-hdmi.c:206:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-hdmi.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/qcom/lpass-hdmi.c b/sound/soc/qcom/lpass-hdmi.c index abfb8737a89f..24b1a7523adb 100644 --- a/sound/soc/qcom/lpass-hdmi.c +++ b/sound/soc/qcom/lpass-hdmi.c @@ -183,8 +183,6 @@ static int lpass_hdmi_daiops_hw_params(struct snd_pcm_substream *substream, return ret; ret = regmap_field_write(sstream_ctl->dp_staffing_en, LPASS_SSTREAM_DEFAULT_ENABLE); - if (ret) - return ret; return ret; } @@ -200,8 +198,6 @@ static int lpass_hdmi_daiops_prepare(struct snd_pcm_substream *substream, return ret; ret = regmap_field_write(drvdata->meta_ctl->mute, LPASS_MUTE_DISABLE); - if (ret) - return ret; return ret; } From 64298706dcc99d1d1fe0882f1ddeb9a3ab5526da Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:08 -0600 Subject: [PATCH 0054/1091] ASoC: qcom: lpass-platform: remove useless assignment cppcheck warning: sound/soc/qcom/lpass-platform.c:791:10: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int ret = -EINVAL; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/lpass-platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/lpass-platform.c b/sound/soc/qcom/lpass-platform.c index 0074b7f2dbc1..0df9481ea4c6 100644 --- a/sound/soc/qcom/lpass-platform.c +++ b/sound/soc/qcom/lpass-platform.c @@ -788,7 +788,7 @@ static int lpass_platform_pcm_new(struct snd_soc_component *component, { struct snd_pcm *pcm = soc_runtime->pcm; struct snd_pcm_substream *psubstream, *csubstream; - int ret = -EINVAL; + int ret; size_t size = lpass_platform_pcm_hardware.buffer_bytes_max; psubstream = pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream; From 18bcac6ed7464844bc18eaa362b0920f6d48bef6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:09 -0600 Subject: [PATCH 0055/1091] ASoC: qcom: q6dsp-dai: clarify expression cppcheck warning: sound/soc/qcom/qdsp6/q6afe-dai.c:264:35: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] tdm->slot_mask = (dai->id & 0x1 ? tx_mask : rx_mask) & cap_mask; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6afe-dai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 4e1f101281e7..3b52abec6a93 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -261,7 +261,7 @@ static int q6tdm_set_tdm_slot(struct snd_soc_dai *dai, tdm->nslots_per_frame = slots; tdm->slot_width = slot_width; /* TDM RX dais ids are even and tx are odd */ - tdm->slot_mask = (dai->id & 0x1 ? tx_mask : rx_mask) & cap_mask; + tdm->slot_mask = ((dai->id & 0x1) ? tx_mask : rx_mask) & cap_mask; break; default: dev_err(dai->dev, "%s: invalid dai id 0x%x\n", From 12900bacb4f358f8921e4dcf7e3f28aac3a37d8b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:10 -0600 Subject: [PATCH 0056/1091] ASoC: qcom: q6afe: remove useless assignments cppcheck warnings: sound/soc/qcom/qdsp6/q6afe.c:848:25: note: Assignment 'p=NULL', assigned value is 0 struct q6afe_port *p = NULL; ^ sound/soc/qcom/qdsp6/q6afe.c:854:7: note: Null pointer dereference if (p->token == token) { ^ sound/soc/qcom/qdsp6/q6afe.c:939:8: style: Redundant initialization for 'wait'. The initialized value is overwritten before it is read. [redundantInitialization] wait = &port->wait; ^ sound/soc/qcom/qdsp6/q6afe.c:933:26: note: wait is initialized wait_queue_head_t *wait = &port->wait; ^ sound/soc/qcom/qdsp6/q6afe.c:939:8: note: wait is overwritten wait = &port->wait; ^ sound/soc/qcom/qdsp6/q6afe.c:1191:10: style: Redundant initialization for 'port_id'. The initialized value is overwritten before it is read. [redundantInitialization] port_id = port->id; ^ sound/soc/qcom/qdsp6/q6afe.c:1186:14: note: port_id is initialized int port_id = port->id; ^ sound/soc/qcom/qdsp6/q6afe.c:1191:10: note: port_id is overwritten port_id = port->id; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6afe.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index cad1cd1bfdf0..6f700c311337 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -845,7 +845,7 @@ static void q6afe_port_free(struct kref *ref) static struct q6afe_port *q6afe_find_port(struct q6afe *afe, int token) { - struct q6afe_port *p = NULL; + struct q6afe_port *p; struct q6afe_port *ret = NULL; unsigned long flags; @@ -930,7 +930,7 @@ EXPORT_SYMBOL_GPL(q6afe_get_port_id); static int afe_apr_send_pkt(struct q6afe *afe, struct apr_pkt *pkt, struct q6afe_port *port, uint32_t rsp_opcode) { - wait_queue_head_t *wait = &port->wait; + wait_queue_head_t *wait; struct aprv2_ibasic_rsp_result_t *result; int ret; @@ -1188,7 +1188,6 @@ int q6afe_port_stop(struct q6afe_port *port) int index, pkt_size; void *p; - port_id = port->id; index = port->token; if (index < 0 || index >= AFE_PORT_MAX) { dev_err(afe->dev, "AFE port index[%d] invalid!\n", index); From 32d4e59cb39de508698ae4db5707af23c3835e4c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:11 -0600 Subject: [PATCH 0057/1091] ASoC: qcom: q6afe: align function prototype cppcheck warning: sound/soc/qcom/qdsp6/q6afe.c:1101:63: style:inconclusive: Function 'q6afe_set_lpass_clock' argument 3 names different: declaration 'clk_src' definition 'attri'. [funcArgNamesDifferent] int q6afe_set_lpass_clock(struct device *dev, int clk_id, int attri, ^ sound/soc/qcom/qdsp6/q6afe.h:236:63: note: Function 'q6afe_set_lpass_clock' argument 3 names different: declaration 'clk_src' definition 'attri'. int q6afe_set_lpass_clock(struct device *dev, int clk_id, int clk_src, ^ sound/soc/qcom/qdsp6/q6afe.c:1101:63: note: Function 'q6afe_set_lpass_clock' argument 3 names different: declaration 'clk_src' definition 'attri'. int q6afe_set_lpass_clock(struct device *dev, int clk_id, int attri, ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6afe.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 22e10269aa10..41133f8797c9 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -233,7 +233,7 @@ void q6afe_cdc_dma_port_prepare(struct q6afe_port *port, int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id, int clk_src, int clk_root, unsigned int freq, int dir); -int q6afe_set_lpass_clock(struct device *dev, int clk_id, int clk_src, +int q6afe_set_lpass_clock(struct device *dev, int clk_id, int attri, int clk_root, unsigned int freq); int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, char *client_name, uint32_t *client_handle); From be79e73e3adbcb8912b005c6485ed0e1590480e4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:12 -0600 Subject: [PATCH 0058/1091] ASoC: qcom: q6asm: align function prototypes cppcheck warnings: sound/soc/qcom/qdsp6/q6asm.c:502:16: style:inconclusive: Function 'q6asm_map_memory_regions' argument 4 names different: declaration 'bufsz' definition 'period_sz'. [funcArgNamesDifferent] size_t period_sz, unsigned int periods) ^ sound/soc/qcom/qdsp6/q6asm.h:150:16: note: Function 'q6asm_map_memory_regions' argument 4 names different: declaration 'bufsz' definition 'period_sz'. size_t bufsz, unsigned int bufcnt); ^ sound/soc/qcom/qdsp6/q6asm.c:502:16: note: Function 'q6asm_map_memory_regions' argument 4 names different: declaration 'bufsz' definition 'period_sz'. size_t period_sz, unsigned int periods) ^ sound/soc/qcom/qdsp6/q6asm.c:502:40: style:inconclusive: Function 'q6asm_map_memory_regions' argument 5 names different: declaration 'bufcnt' definition 'periods'. [funcArgNamesDifferent] size_t period_sz, unsigned int periods) ^ sound/soc/qcom/qdsp6/q6asm.h:150:36: note: Function 'q6asm_map_memory_regions' argument 5 names different: declaration 'bufcnt' definition 'periods'. size_t bufsz, unsigned int bufcnt); ^ sound/soc/qcom/qdsp6/q6asm.c:502:40: note: Function 'q6asm_map_memory_regions' argument 5 names different: declaration 'bufcnt' definition 'periods'. size_t period_sz, unsigned int periods) ^ sound/soc/qcom/qdsp6/q6asm.c:823:47: style:inconclusive: Function 'q6asm_get_session_id' argument 1 names different: declaration 'ac' definition 'c'. [funcArgNamesDifferent] int q6asm_get_session_id(struct audio_client *c) ^ sound/soc/qcom/qdsp6/q6asm.h:146:47: note: Function 'q6asm_get_session_id' argument 1 names different: declaration 'ac' definition 'c'. int q6asm_get_session_id(struct audio_client *ac); ^ sound/soc/qcom/qdsp6/q6asm.c:823:47: note: Function 'q6asm_get_session_id' argument 1 names different: declaration 'ac' definition 'c'. int q6asm_get_session_id(struct audio_client *c) ^ sound/soc/qcom/qdsp6/q6asm.c:1573:52: style:inconclusive: Function 'q6asm_write_async' argument 6 names different: declaration 'flags' definition 'wflags'. [funcArgNamesDifferent] uint32_t msw_ts, uint32_t lsw_ts, uint32_t wflags) ^ sound/soc/qcom/qdsp6/q6asm.h:100:52: note: Function 'q6asm_write_async' argument 6 names different: declaration 'flags' definition 'wflags'. uint32_t msw_ts, uint32_t lsw_ts, uint32_t flags); ^ sound/soc/qcom/qdsp6/q6asm.c:1573:52: note: Function 'q6asm_write_async' argument 6 names different: declaration 'flags' definition 'wflags'. uint32_t msw_ts, uint32_t lsw_ts, uint32_t wflags) ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6asm.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6asm.h b/sound/soc/qcom/qdsp6/q6asm.h index 82e584aa534f..394604c34943 100644 --- a/sound/soc/qcom/qdsp6/q6asm.h +++ b/sound/soc/qcom/qdsp6/q6asm.h @@ -97,7 +97,7 @@ struct audio_client *q6asm_audio_client_alloc(struct device *dev, int session_id, int perf_mode); void q6asm_audio_client_free(struct audio_client *ac); int q6asm_write_async(struct audio_client *ac, uint32_t stream_id, uint32_t len, - uint32_t msw_ts, uint32_t lsw_ts, uint32_t flags); + uint32_t msw_ts, uint32_t lsw_ts, uint32_t wflags); int q6asm_open_write(struct audio_client *ac, uint32_t stream_id, uint32_t format, u32 codec_profile, uint16_t bits_per_sample, bool is_gapless); @@ -143,10 +143,10 @@ int q6asm_stream_remove_trailing_silence(struct audio_client *ac, uint32_t trailing_samples); int q6asm_cmd(struct audio_client *ac, uint32_t stream_id, int cmd); int q6asm_cmd_nowait(struct audio_client *ac, uint32_t stream_id, int cmd); -int q6asm_get_session_id(struct audio_client *ac); +int q6asm_get_session_id(struct audio_client *c); int q6asm_map_memory_regions(unsigned int dir, struct audio_client *ac, phys_addr_t phys, - size_t bufsz, unsigned int bufcnt); + size_t period_sz, unsigned int periods); int q6asm_unmap_memory_regions(unsigned int dir, struct audio_client *ac); #endif /* __Q6_ASM_H__ */ From 77af06de30139fbddae67dd9db70d7ccc53b1955 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:13 -0600 Subject: [PATCH 0059/1091] ASoC: wcd-clsh-v2: align function prototypes cppcheck warnings: sound/soc/codecs/wcd-clsh-v2.c:523:28: style:inconclusive: Function 'wcd_clsh_ctrl_set_state' argument 2 names different: declaration 'event' definition 'clsh_event'. [funcArgNamesDifferent] enum wcd_clsh_event clsh_event, ^ sound/soc/codecs/wcd-clsh-v2.h:45:28: note: Function 'wcd_clsh_ctrl_set_state' argument 2 names different: declaration 'event' definition 'clsh_event'. enum wcd_clsh_event event, ^ sound/soc/codecs/wcd-clsh-v2.c:523:28: note: Function 'wcd_clsh_ctrl_set_state' argument 2 names different: declaration 'event' definition 'clsh_event'. enum wcd_clsh_event clsh_event, ^ sound/soc/codecs/wcd-clsh-v2.c:524:12: style:inconclusive: Function 'wcd_clsh_ctrl_set_state' argument 3 names different: declaration 'state' definition 'nstate'. [funcArgNamesDifferent] int nstate, ^ sound/soc/codecs/wcd-clsh-v2.h:46:12: note: Function 'wcd_clsh_ctrl_set_state' argument 3 names different: declaration 'state' definition 'nstate'. int state, ^ sound/soc/codecs/wcd-clsh-v2.c:524:12: note: Function 'wcd_clsh_ctrl_set_state' argument 3 names different: declaration 'state' definition 'nstate'. int nstate, ^ sound/soc/codecs/wcd-clsh-v2.c:557:69: style:inconclusive: Function 'wcd_clsh_ctrl_alloc' argument 1 names different: declaration 'component' definition 'comp'. [funcArgNamesDifferent] struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp, ^ sound/soc/codecs/wcd-clsh-v2.h:40:31: note: Function 'wcd_clsh_ctrl_alloc' argument 1 names different: declaration 'component' definition 'comp'. struct snd_soc_component *component, ^ sound/soc/codecs/wcd-clsh-v2.c:557:69: note: Function 'wcd_clsh_ctrl_alloc' argument 1 names different: declaration 'component' definition 'comp'. struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc(struct snd_soc_component *comp, ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd-clsh-v2.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/wcd-clsh-v2.h b/sound/soc/codecs/wcd-clsh-v2.h index a902f9893467..a6d0f2d0e9e3 100644 --- a/sound/soc/codecs/wcd-clsh-v2.h +++ b/sound/soc/codecs/wcd-clsh-v2.h @@ -37,13 +37,13 @@ enum wcd_clsh_mode { struct wcd_clsh_ctrl; extern struct wcd_clsh_ctrl *wcd_clsh_ctrl_alloc( - struct snd_soc_component *component, + struct snd_soc_component *comp, int version); extern void wcd_clsh_ctrl_free(struct wcd_clsh_ctrl *ctrl); extern int wcd_clsh_ctrl_get_state(struct wcd_clsh_ctrl *ctrl); extern int wcd_clsh_ctrl_set_state(struct wcd_clsh_ctrl *ctrl, - enum wcd_clsh_event event, - int state, + enum wcd_clsh_event clsh_event, + int nstate, enum wcd_clsh_mode mode); #endif /* _WCD_CLSH_V2_H_ */ From 8d2f2d7ff3c69e1b7a2d1424e4d2dc8a6fe77849 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:14 -0600 Subject: [PATCH 0060/1091] ASoC: wcd9335: clarify return value cppcheck warning: sound/soc/codecs/wcd9335.c:5216:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/codecs/wcd9335.c:5211:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/codecs/wcd9335.c:5216:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index 9ddfed797b7e..adb325fac930 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -5213,7 +5213,7 @@ static int wcd9335_slim_status(struct slim_device *sdev, wcd9335_probe(wcd); - return ret; + return 0; } static const struct slim_device_id wcd9335_slim_id[] = { From 7faaea14feeeb88177ecf8a640a203c319960d43 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:15 -0600 Subject: [PATCH 0061/1091] ASoC: wcd934x: remove useless return cppcheck warning: sound/soc/codecs/wcd934x.c:1571:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/codecs/wcd934x.c:1568:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/codecs/wcd934x.c:1571:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index d18ae5e3ee80..2c4818dc2e6d 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1565,8 +1565,6 @@ static int wcd934x_set_interpolator_rate(struct snd_soc_dai *dai, return ret; ret = wcd934x_set_mix_interpolator_rate(dai, (u8)rate_val, sample_rate); - if (ret) - return ret; return ret; } From 4b4f2119f98518c86c5651771ad9db9070c76de4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:29:16 -0600 Subject: [PATCH 0062/1091] ASoC: lpass-wsa-macro: add missing test cppcheck warning: sound/soc/codecs/lpass-wsa-macro.c:958:6: style: Variable 'ret' is reassigned a value before the old one has been used. [redundantAssignment] ret = wsa_macro_set_prim_interpolator_rate(dai, (u8) rate_val, sample_rate); ^ sound/soc/codecs/lpass-wsa-macro.c:946:6: note: ret is assigned ret = wsa_macro_set_mix_interpolator_rate(dai, (u8) rate_val, sample_rate); ^ sound/soc/codecs/lpass-wsa-macro.c:958:6: note: ret is overwritten ret = wsa_macro_set_prim_interpolator_rate(dai, (u8) rate_val, sample_rate); ^ set_mix_interpolator_rate can return -EINVAL, add a test and bail on error. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210218222916.89809-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index 9ca49a165f69..e37c8148c0de 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -944,6 +944,8 @@ static int wsa_macro_set_interpolator_rate(struct snd_soc_dai *dai, goto prim_rate; ret = wsa_macro_set_mix_interpolator_rate(dai, (u8) rate_val, sample_rate); + if (ret < 0) + return ret; prim_rate: /* set primary path sample rate */ for (i = 0; i < ARRAY_SIZE(int_prim_sample_rate_val); i++) { From 628fc9d9a0e6e52fd3116b5591cb4e90473db9ad Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Wed, 24 Feb 2021 22:19:15 +0100 Subject: [PATCH 0063/1091] ASoC: rt*: Constify static struct sdw_slave_ops The only usage of these is to assign their address to the ops field in the sdw_driver struct, which is a pointer to const. Make them const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn Link: https://lore.kernel.org/r/20210224211918.39109-2-rikard.falkeborn@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308-sdw.c | 2 +- sound/soc/codecs/rt5682-sdw.c | 2 +- sound/soc/codecs/rt700-sdw.c | 2 +- sound/soc/codecs/rt711-sdw.c | 2 +- sound/soc/codecs/rt715-sdw.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt1308-sdw.c b/sound/soc/codecs/rt1308-sdw.c index afd2c3b687cc..1c226994aebd 100644 --- a/sound/soc/codecs/rt1308-sdw.c +++ b/sound/soc/codecs/rt1308-sdw.c @@ -594,7 +594,7 @@ static int rt1308_sdw_pcm_hw_free(struct snd_pcm_substream *substream, * slave_ops: callbacks for get_clock_stop_mode, clock_stop and * port_prep are not defined for now */ -static struct sdw_slave_ops rt1308_slave_ops = { +static const struct sdw_slave_ops rt1308_slave_ops = { .read_prop = rt1308_read_prop, .interrupt_callback = rt1308_interrupt_callback, .update_status = rt1308_update_status, diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index b49f1e16125d..0b7ac74e671d 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -683,7 +683,7 @@ static int rt5682_interrupt_callback(struct sdw_slave *slave, return 0; } -static struct sdw_slave_ops rt5682_slave_ops = { +static const struct sdw_slave_ops rt5682_slave_ops = { .read_prop = rt5682_read_prop, .interrupt_callback = rt5682_interrupt_callback, .update_status = rt5682_update_status, diff --git a/sound/soc/codecs/rt700-sdw.c b/sound/soc/codecs/rt700-sdw.c index 4001612dfd73..ff9c081fd52a 100644 --- a/sound/soc/codecs/rt700-sdw.c +++ b/sound/soc/codecs/rt700-sdw.c @@ -430,7 +430,7 @@ static int rt700_interrupt_callback(struct sdw_slave *slave, * slave_ops: callbacks for get_clock_stop_mode, clock_stop and * port_prep are not defined for now */ -static struct sdw_slave_ops rt700_slave_ops = { +static const struct sdw_slave_ops rt700_slave_ops = { .read_prop = rt700_read_prop, .interrupt_callback = rt700_interrupt_callback, .update_status = rt700_update_status, diff --git a/sound/soc/codecs/rt711-sdw.c b/sound/soc/codecs/rt711-sdw.c index 2beb4286d997..8f5ebe92d407 100644 --- a/sound/soc/codecs/rt711-sdw.c +++ b/sound/soc/codecs/rt711-sdw.c @@ -431,7 +431,7 @@ static int rt711_interrupt_callback(struct sdw_slave *slave, return 0; } -static struct sdw_slave_ops rt711_slave_ops = { +static const struct sdw_slave_ops rt711_slave_ops = { .read_prop = rt711_read_prop, .interrupt_callback = rt711_interrupt_callback, .update_status = rt711_update_status, diff --git a/sound/soc/codecs/rt715-sdw.c b/sound/soc/codecs/rt715-sdw.c index 71dd3b97a459..81a1dd77b6f6 100644 --- a/sound/soc/codecs/rt715-sdw.c +++ b/sound/soc/codecs/rt715-sdw.c @@ -488,7 +488,7 @@ static int rt715_bus_config(struct sdw_slave *slave, return 0; } -static struct sdw_slave_ops rt715_slave_ops = { +static const struct sdw_slave_ops rt715_slave_ops = { .read_prop = rt715_read_prop, .update_status = rt715_update_status, .bus_config = rt715_bus_config, From f9e56a34cda2189a1d1611bdff1f6d1d0fb460e5 Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Wed, 24 Feb 2021 22:19:16 +0100 Subject: [PATCH 0064/1091] ASoC: rt*: Constify static struct snd_soc_dai_ops The only usage of them is to assign their address to the ops field in the snd_soc_dai_driver struct, which is a pointer to const. Make them const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn Link: https://lore.kernel.org/r/20210224211918.39109-3-rikard.falkeborn@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 2 +- sound/soc/codecs/rt1016.c | 2 +- sound/soc/codecs/rt5682-sdw.c | 2 +- sound/soc/codecs/rt700.c | 2 +- sound/soc/codecs/rt711.c | 2 +- sound/soc/codecs/rt715.c | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 844e4079d176..501cc45240b4 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -1028,7 +1028,7 @@ static void rt1015_remove(struct snd_soc_component *component) #define RT1015_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -static struct snd_soc_dai_ops rt1015_aif_dai_ops = { +static const struct snd_soc_dai_ops rt1015_aif_dai_ops = { .hw_params = rt1015_hw_params, .set_fmt = rt1015_set_dai_fmt, .set_tdm_slot = rt1015_set_tdm_slot, diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c index a23d368ab4da..483375fc16ca 100644 --- a/sound/soc/codecs/rt1016.c +++ b/sound/soc/codecs/rt1016.c @@ -534,7 +534,7 @@ static void rt1016_remove(struct snd_soc_component *component) #define RT1016_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -static struct snd_soc_dai_ops rt1016_aif_dai_ops = { +static const struct snd_soc_dai_ops rt1016_aif_dai_ops = { .hw_params = rt1016_hw_params, .set_fmt = rt1016_set_dai_fmt, }; diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 0b7ac74e671d..5e097f776561 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -269,7 +269,7 @@ static int rt5682_sdw_hw_free(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_dai_ops rt5682_sdw_ops = { +static const struct snd_soc_dai_ops rt5682_sdw_ops = { .hw_params = rt5682_sdw_hw_params, .hw_free = rt5682_sdw_hw_free, .set_sdw_stream = rt5682_set_sdw_stream, diff --git a/sound/soc/codecs/rt700.c b/sound/soc/codecs/rt700.c index 66ec395dbbcd..01af9d9dd3ca 100644 --- a/sound/soc/codecs/rt700.c +++ b/sound/soc/codecs/rt700.c @@ -1002,7 +1002,7 @@ static int rt700_pcm_hw_free(struct snd_pcm_substream *substream, #define RT700_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -static struct snd_soc_dai_ops rt700_ops = { +static const struct snd_soc_dai_ops rt700_ops = { .hw_params = rt700_pcm_hw_params, .hw_free = rt700_pcm_hw_free, .set_sdw_stream = rt700_set_sdw_stream, diff --git a/sound/soc/codecs/rt711.c b/sound/soc/codecs/rt711.c index 85f744184a60..202bf6fbc5be 100644 --- a/sound/soc/codecs/rt711.c +++ b/sound/soc/codecs/rt711.c @@ -1048,7 +1048,7 @@ static int rt711_pcm_hw_free(struct snd_pcm_substream *substream, #define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -static struct snd_soc_dai_ops rt711_ops = { +static const struct snd_soc_dai_ops rt711_ops = { .hw_params = rt711_pcm_hw_params, .hw_free = rt711_pcm_hw_free, .set_sdw_stream = rt711_set_sdw_stream, diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index 9a7d393d424a..f419d001a3fb 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -683,7 +683,7 @@ static int rt715_pcm_hw_free(struct snd_pcm_substream *substream, #define RT715_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -static struct snd_soc_dai_ops rt715_ops = { +static const struct snd_soc_dai_ops rt715_ops = { .hw_params = rt715_pcm_hw_params, .hw_free = rt715_pcm_hw_free, .set_sdw_stream = rt715_set_sdw_stream, From 3084e5f7f75339451d8bb39dede700c37e588b8c Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Wed, 24 Feb 2021 22:19:17 +0100 Subject: [PATCH 0065/1091] ASoC: rt*: Constify static struct acpi_device_id These are never modified, so make them const to allow the compiler to put them in read-only memory. Signed-off-by: Rikard Falkeborn Link: https://lore.kernel.org/r/20210224211918.39109-4-rikard.falkeborn@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 2 +- sound/soc/codecs/rt1015.c | 2 +- sound/soc/codecs/rt1016.c | 2 +- sound/soc/codecs/rt1305.c | 2 +- sound/soc/codecs/rt1308.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 098ecf13814d..6877be5f36b9 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -2151,7 +2151,7 @@ MODULE_DEVICE_TABLE(of, rt1011_of_match); #endif #ifdef CONFIG_ACPI -static struct acpi_device_id rt1011_acpi_match[] = { +static const struct acpi_device_id rt1011_acpi_match[] = { {"10EC1011", 0,}, {}, }; diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 501cc45240b4..3cd967ae999d 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -1121,7 +1121,7 @@ MODULE_DEVICE_TABLE(of, rt1015_of_match); #endif #ifdef CONFIG_ACPI -static struct acpi_device_id rt1015_acpi_match[] = { +static const struct acpi_device_id rt1015_acpi_match[] = { {"10EC1015", 0,}, {}, }; diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c index 483375fc16ca..c14a809da52b 100644 --- a/sound/soc/codecs/rt1016.c +++ b/sound/soc/codecs/rt1016.c @@ -623,7 +623,7 @@ MODULE_DEVICE_TABLE(of, rt1016_of_match); #endif #ifdef CONFIG_ACPI -static struct acpi_device_id rt1016_acpi_match[] = { +static const struct acpi_device_id rt1016_acpi_match[] = { {"10EC1016", 0,}, {}, }; diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index 4e9dfd235e59..16aa405fb8f0 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -975,7 +975,7 @@ MODULE_DEVICE_TABLE(of, rt1305_of_match); #endif #ifdef CONFIG_ACPI -static struct acpi_device_id rt1305_acpi_match[] = { +static const struct acpi_device_id rt1305_acpi_match[] = { {"10EC1305", 0,}, {"10EC1306", 0,}, {}, diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index b75931a69a1c..76e65844543d 100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -790,7 +790,7 @@ MODULE_DEVICE_TABLE(of, rt1308_of_match); #endif #ifdef CONFIG_ACPI -static struct acpi_device_id rt1308_acpi_match[] = { +static const struct acpi_device_id rt1308_acpi_match[] = { { "10EC1308", 0, }, { }, }; From c4fd082e466277b82fe2c0480b19f9398652302b Mon Sep 17 00:00:00 2001 From: Rikard Falkeborn Date: Wed, 24 Feb 2021 22:19:18 +0100 Subject: [PATCH 0066/1091] ASoc: rt5631: Constify static struct coeff_clk_div coeff_div is only read from, so make it const to show the intent. Signed-off-by: Rikard Falkeborn Link: https://lore.kernel.org/r/20210224211918.39109-5-rikard.falkeborn@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5631.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index 653da3eaf355..afc1305a7fa5 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -1283,7 +1283,7 @@ static const struct pll_div codec_slave_pll_div[] = { {3072000, 12288000, 0x0a90}, }; -static struct coeff_clk_div coeff_div[] = { +static const struct coeff_clk_div coeff_div[] = { /* sysclk is 256fs */ {2048000, 8000 * 32, 8000, 0x1000}, {2048000, 8000 * 64, 8000, 0x0000}, From b296743576220b745938fde62e4f8ad25a195985 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:29 -0600 Subject: [PATCH 0067/1091] ASoC: fsl: fsl_asrc: remove useless assignment cppcheck warning: sound/soc/fsl/fsl_asrc.c:613:8: style: Variable 'i' is assigned a value that is never used. [unreadVariable] int i = 0, j = 0; ^ The same issue occurs for the 'j' variable. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index c325c984d165..63d236ef5c4d 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -610,7 +610,7 @@ static void fsl_asrc_select_clk(struct fsl_asrc_priv *asrc_priv, struct asrc_config *config = pair_priv->config; int rate[2], select_clk[2]; /* Array size 2 means IN and OUT */ int clk_rate, clk_index; - int i = 0, j = 0; + int i, j; rate[IN] = in_rate; rate[OUT] = out_rate; From b035a9efda2889c4d6064b67100bba6eff17af32 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:30 -0600 Subject: [PATCH 0068/1091] ASoC: fsl: fsl_dma: remove unused variable cppcheck warning: sound/soc/fsl/fsl_dma.c:411:10: style: Variable 'channel' is assigned a value that is never used. [unreadVariable] channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; ^ Removing this line shows the variable isn't needed any longer so remove declaration as well. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_dma.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/fsl/fsl_dma.c b/sound/soc/fsl/fsl_dma.c index e0c39c5f4854..84bd8a5356eb 100644 --- a/sound/soc/fsl/fsl_dma.c +++ b/sound/soc/fsl/fsl_dma.c @@ -392,7 +392,6 @@ static int fsl_dma_open(struct snd_soc_component *component, dma_addr_t ld_buf_phys; u64 temp_link; /* Pointer to next link descriptor */ u32 mr; - unsigned int channel; int ret = 0; unsigned int i; @@ -408,8 +407,6 @@ static int fsl_dma_open(struct snd_soc_component *component, return ret; } - channel = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0 : 1; - if (dma->assigned) { dev_err(dev, "dma channel already assigned\n"); return -EBUSY; From 062b85216886bbb5e318705c479838563bfdd9d2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:31 -0600 Subject: [PATCH 0069/1091] ASoC: fsl: fsl_easrc: remove useless assignments cppcheck warnings: sound/soc/fsl/fsl_easrc.c:751:53: style: Variable 'st2_mem_alloc' is assigned a value that is never used. [unreadVariable] int st1_chanxexp, st1_mem_alloc = 0, st2_mem_alloc = 0; ^ sound/soc/fsl/fsl_easrc.c:1331:11: style: Variable 'size' is assigned a value that is never used. [unreadVariable] int size = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 636a702f37a6..725a5d3aaa02 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -710,7 +710,7 @@ static int fsl_easrc_max_ch_for_slot(struct fsl_asrc_pair *ctx, struct fsl_easrc_slot *slot) { struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; - int st1_mem_alloc = 0, st2_mem_alloc = 0; + int st1_mem_alloc = 0, st2_mem_alloc; int pf_mem_alloc = 0; int max_channels = 8 - slot->num_channel; int channels = 0; @@ -748,7 +748,7 @@ static int fsl_easrc_config_one_slot(struct fsl_asrc_pair *ctx, { struct fsl_asrc *easrc = ctx->asrc; struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; - int st1_chanxexp, st1_mem_alloc = 0, st2_mem_alloc = 0; + int st1_chanxexp, st1_mem_alloc = 0, st2_mem_alloc; unsigned int reg0, reg1, reg2, reg3; unsigned int addr; @@ -1328,7 +1328,7 @@ static int fsl_easrc_stop_context(struct fsl_asrc_pair *ctx) { struct fsl_asrc *easrc = ctx->asrc; int val, i; - int size = 0; + int size; int retry = 200; regmap_read(easrc->regmap, REG_EASRC_CC(ctx->index), &val); From 8f6fef01a5ba48b416d1dc7e910268e03d270a10 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:32 -0600 Subject: [PATCH 0070/1091] ASoC: fsl: fsl_esai: clarify expression cppcheck warning: sound/soc/fsl/fsl_esai.c:307:16: style: Clarify calculation precedence for '%' and '?'. [clarifyCalculation] clk_id % 2 ? "extal" : "fsys"); ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 08056fa0a0fa..41b154417b92 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -304,7 +304,7 @@ static int fsl_esai_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, if (IS_ERR(clksrc)) { dev_err(dai->dev, "no assigned %s clock\n", - clk_id % 2 ? "extal" : "fsys"); + (clk_id % 2) ? "extal" : "fsys"); return PTR_ERR(clksrc); } clk_rate = clk_get_rate(clksrc); From 2fb563567bc425b9a7371f1432c62e25627e1754 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:33 -0600 Subject: [PATCH 0071/1091] ASoC: fsl: fsl_ssi: remove unnecessary tests cppcheck warnings: sound/soc/fsl/fsl_ssi.c:767:34: style: Condition 'div2' is always false [knownConditionTrueFalse] stccr = SSI_SxCCR_PM(pm + 1) | (div2 ? SSI_SxCCR_DIV2 : 0) | ^ sound/soc/fsl/fsl_ssi.c:722:9: note: Assignment 'div2=0', assigned value is 0 div2 = 0; ^ sound/soc/fsl/fsl_ssi.c:767:34: note: Condition 'div2' is always false stccr = SSI_SxCCR_PM(pm + 1) | (div2 ? SSI_SxCCR_DIV2 : 0) | ^ sound/soc/fsl/fsl_ssi.c:768:4: style: Condition 'psr' is always false [knownConditionTrueFalse] (psr ? SSI_SxCCR_PSR : 0); ^ sound/soc/fsl/fsl_ssi.c:721:8: note: Assignment 'psr=0', assigned value is 0 psr = 0; ^ sound/soc/fsl/fsl_ssi.c:768:4: note: Condition 'psr' is always false (psr ? SSI_SxCCR_PSR : 0); ^ Upon further analysis, the variables 'div2' and 'psr' are set to zero and never modified. All the tests can be removed. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index ad8af3f450e2..4e2ce47a7c6e 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -747,7 +747,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, sub *= 100000; do_div(sub, freq); - if (sub < savesub && !(i == 0 && psr == 0 && div2 == 0)) { + if (sub < savesub && !(i == 0)) { baudrate = tmprate; savesub = sub; pm = i; @@ -764,8 +764,7 @@ static int fsl_ssi_set_bclk(struct snd_pcm_substream *substream, return -EINVAL; } - stccr = SSI_SxCCR_PM(pm + 1) | (div2 ? SSI_SxCCR_DIV2 : 0) | - (psr ? SSI_SxCCR_PSR : 0); + stccr = SSI_SxCCR_PM(pm + 1); mask = SSI_SxCCR_PM_MASK | SSI_SxCCR_DIV2 | SSI_SxCCR_PSR; /* STCCR is used for RX in synchronous mode */ From 4a6202f0cef51714bcc46728cdf8153da49d2785 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:34 -0600 Subject: [PATCH 0072/1091] ASoC: fsl: imx-hdmi: remove unused structure members cppcheck warning: sound/soc/fsl/imx-hdmi.c:21:16: style: struct member 'cpu_priv::sysclk_freq' is never used. [unusedStructMember] unsigned long sysclk_freq[2]; ^ Additional checks show the sysclk_dir member is also not used. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-hdmi.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c index dbbb7618351c..1ebcb9a2336b 100644 --- a/sound/soc/fsl/imx-hdmi.c +++ b/sound/soc/fsl/imx-hdmi.c @@ -10,16 +10,12 @@ /** * struct cpu_priv - CPU private data - * @sysclk_freq: SYSCLK rates for set_sysclk() - * @sysclk_dir: SYSCLK directions for set_sysclk() * @sysclk_id: SYSCLK ids for set_sysclk() * @slot_width: Slot width of each frame * * Note: [1] for tx and [0] for rx */ struct cpu_priv { - unsigned long sysclk_freq[2]; - u32 sysclk_dir[2]; u32 sysclk_id[2]; u32 slot_width; }; From 91ab7743112bf2414cd6264dbadb94deef51855a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:35 -0600 Subject: [PATCH 0073/1091] ASoC: fsl: mpc5200: signed parameter in snprintf format cppcheck warning: sound/soc/fsl/mpc5200_dma.c:414:2: warning: %u in format string (no. 1) requires 'unsigned int' but the argument type is 'signed int'. [invalidPrintfArgType_uint] snprintf(psc_dma->name, sizeof psc_dma->name, "PSC%u", psc_dma->id); ^ Also fix sizeof use, missing parentheses reported by checkpatch.pl Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/mpc5200_dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/mpc5200_dma.c b/sound/soc/fsl/mpc5200_dma.c index 231984882176..6c65cd858b0b 100644 --- a/sound/soc/fsl/mpc5200_dma.c +++ b/sound/soc/fsl/mpc5200_dma.c @@ -411,7 +411,7 @@ int mpc5200_audio_dma_create(struct platform_device *op) psc_dma->dev = &op->dev; psc_dma->playback.psc_dma = psc_dma; psc_dma->capture.psc_dma = psc_dma; - snprintf(psc_dma->name, sizeof psc_dma->name, "PSC%u", psc_dma->id); + snprintf(psc_dma->name, sizeof(psc_dma->name), "PSC%d", psc_dma->id); /* Find the address of the fifo data registers and setup the * DMA tasks */ From f5036db354d9cc0d2261758e3dada3894d378dbb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:36 -0600 Subject: [PATCH 0074/1091] ASoC: fsl: mpc8610: remove useless assignment cppcheck warning: sound/soc/fsl/mpc8610_hpcd.c:333:6: style: Redundant initialization for 'ret'. The initialized value is overwritten before it is read. [redundantInitialization] ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", ^ sound/soc/fsl/mpc8610_hpcd.c:193:10: note: ret is initialized int ret = -ENODEV; ^ sound/soc/fsl/mpc8610_hpcd.c:333:6: note: ret is overwritten ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/mpc8610_hpcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/mpc8610_hpcd.c b/sound/soc/fsl/mpc8610_hpcd.c index eccc833390d4..58b9ca3c4da0 100644 --- a/sound/soc/fsl/mpc8610_hpcd.c +++ b/sound/soc/fsl/mpc8610_hpcd.c @@ -190,7 +190,7 @@ static int mpc8610_hpcd_probe(struct platform_device *pdev) struct device_node *codec_np = NULL; struct mpc8610_hpcd_data *machine_data; struct snd_soc_dai_link_component *comp; - int ret = -ENODEV; + int ret; const char *sprop; const u32 *iprop; From b86fe83448b45254cf39bc4f7db739b29488d72a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:29:37 -0600 Subject: [PATCH 0075/1091] ASoC: fsl: p1022_ds: remove useless assignment cppcheck warning: sound/soc/fsl/p1022_ds.c:344:6: style: Redundant initialization for 'ret'. The initialized value is overwritten before it is read. [redundantInitialization] ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], ^ sound/soc/fsl/p1022_ds.c:203:10: note: ret is initialized int ret = -ENODEV; ^ sound/soc/fsl/p1022_ds.c:344:6: note: ret is overwritten ret = fsl_asoc_get_dma_channel(np, "fsl,playback-dma", &mdata->dai[0], ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219232937.6440-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/p1022_ds.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/p1022_ds.c b/sound/soc/fsl/p1022_ds.c index ac68d2238045..317c767b0099 100644 --- a/sound/soc/fsl/p1022_ds.c +++ b/sound/soc/fsl/p1022_ds.c @@ -200,7 +200,7 @@ static int p1022_ds_probe(struct platform_device *pdev) struct device_node *codec_np = NULL; struct machine_data *mdata; struct snd_soc_dai_link_component *comp; - int ret = -ENODEV; + int ret; const char *sprop; const u32 *iprop; From 6053a840f711fbb4e36fad06880be11db37d3cdc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Feb 2021 09:46:57 +0900 Subject: [PATCH 0076/1091] ASoC: soc-pcm: remove strange format storing dpcm_init_runtime_hw() (= A) is used from dpcm_set_fe_runtime() (= B) with for_each_rtd_cpu_dais() loop (= C), and it checks formats (= D). (A) static void dpcm_init_runtime_hw(...) { ... ^ if (runtime->hw.formats) | (D1) runtime->hw.formats &= stream->formats; (D) else | (D2) runtime->hw.formats = stream->formats; v } (B) static void dpcm_set_fe_runtime(...) { ... (C) for_each_rtd_cpu_dais(rtd, i, cpu_dai) { ... (A) dpcm_init_runtime_hw(...); } } If this for_each_rtd_cpu_dais() loop (= C) calls dpcm_init_runtime_hw() (= A) multiple times, this means it is Multi-CPU. If we focus to format operation at (D), using mask (= D1) is understandable because it restricts unsupported format. But, enabling format when zero format case (= D2) is very strange, because it might enables unsupported format. This runtime->hw.formats is initialized by ULLONG_MAX at soc_pcm_hw_init(), thus becoming zero format means it can't use such format. And doing this strange format operation is only here. This patch removes strange format operation (= D2), and use standard soc_pcm_hw_update_format() for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sg5pvshq.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 14d85ca1e435..bb912a94e895 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1533,10 +1533,7 @@ static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, soc_pcm_hw_update_rate(hw, stream); soc_pcm_hw_update_chan(hw, stream); - if (runtime->hw.formats) - runtime->hw.formats &= stream->formats; - else - runtime->hw.formats = stream->formats; + soc_pcm_hw_update_format(hw, stream); } static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, From 7f4a763642cc8d5f49e64a3611de8f62102c9d31 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Feb 2021 09:47:19 +0900 Subject: [PATCH 0077/1091] ASoC: soc-pcm: unpack dpcm_init_runtime_hw() dpcm_init_runtime_hw() is now just verbose function. This patch unpacks it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r1l9vsh4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index bb912a94e895..fd279fb28533 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1526,16 +1526,6 @@ unwind: return err; } -static void dpcm_init_runtime_hw(struct snd_pcm_runtime *runtime, - struct snd_soc_pcm_stream *stream) -{ - struct snd_pcm_hardware *hw = &runtime->hw; - - soc_pcm_hw_update_rate(hw, stream); - soc_pcm_hw_update_chan(hw, stream); - soc_pcm_hw_update_format(hw, stream); -} - static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime) { @@ -1669,6 +1659,8 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) soc_pcm_hw_init(hw); for_each_rtd_cpu_dais(rtd, i, cpu_dai) { + struct snd_soc_pcm_stream *stream; + /* * Skip CPUs which don't support the current stream * type. See soc_pcm_init_runtime_hw() for more details @@ -1676,9 +1668,11 @@ static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) continue; - dpcm_init_runtime_hw(runtime, - snd_soc_dai_get_pcm_stream(cpu_dai, - substream->stream)); + stream = snd_soc_dai_get_pcm_stream(cpu_dai, substream->stream); + + soc_pcm_hw_update_rate(hw, stream); + soc_pcm_hw_update_chan(hw, stream); + soc_pcm_hw_update_format(hw, stream); } dpcm_runtime_merge_format(substream, runtime); From 5f53898af1a2bf753f111ec1c7ed668fe6557b76 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Feb 2021 09:47:26 +0900 Subject: [PATCH 0078/1091] ASoC: soc-pcm: add dpcm_runtime_setup_fe() dpcm_fe_dai_startup() (= A) calls dpcm_set_fe_runtime() (= B) to setup DPCM runtime. From *naming point of view*, it sounds like setup function for FE. (A) static int dpcm_fe_dai_startup(...) { ... (B) dpcm_set_fe_runtime(...); ... } But in dpcm_set_fe_runtime() (= B), It setups FE by for_each loop (= X), and setups BE by dpcm_runtime_merge_xxx() (= Y). (B) static void dpcm_set_fe_runtime(...) { ... ^ for_each_rtd_cpu_dais(...) { | ... (X) soc_pcm_hw_update_rate(...); | soc_pcm_hw_update_chan(...); | soc_pcm_hw_update_format(...); v } ^ dpcm_runtime_merge_format(...); (Y) dpcm_runtime_merge_chan(...); v dpcm_runtime_merge_rate(...); } These means that the function which is called as xxx_fe_xxx() is setups both FE and BE. This is confusable and can be hot bed for bug. To tidyup it, as 1st step, this patch adds new dpcm_runtime_setup_fe() for (X). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pn0tvsgx.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 53 ++++++++++++++++++++++++++------------------- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index fd279fb28533..066218f1f075 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1526,6 +1526,36 @@ unwind: return err; } +static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_pcm_hardware *hw = &runtime->hw; + struct snd_soc_dai *dai; + int stream = substream->stream; + int i; + + soc_pcm_hw_init(hw); + + for_each_rtd_cpu_dais(fe, i, dai) { + struct snd_soc_pcm_stream *cpu_stream; + + /* + * Skip CPUs which don't support the current stream + * type. See soc_pcm_init_runtime_hw() for more details + */ + if (!snd_soc_dai_stream_valid(dai, stream)) + continue; + + cpu_stream = snd_soc_dai_get_pcm_stream(dai, stream); + + soc_pcm_hw_update_rate(hw, cpu_stream); + soc_pcm_hw_update_chan(hw, cpu_stream); + soc_pcm_hw_update_format(hw, cpu_stream); + } + +} + static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, struct snd_pcm_runtime *runtime) { @@ -1651,29 +1681,8 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) { struct snd_pcm_runtime *runtime = substream->runtime; - struct snd_pcm_hardware *hw = &runtime->hw; - struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *cpu_dai; - int i; - soc_pcm_hw_init(hw); - - for_each_rtd_cpu_dais(rtd, i, cpu_dai) { - struct snd_soc_pcm_stream *stream; - - /* - * Skip CPUs which don't support the current stream - * type. See soc_pcm_init_runtime_hw() for more details - */ - if (!snd_soc_dai_stream_valid(cpu_dai, substream->stream)) - continue; - - stream = snd_soc_dai_get_pcm_stream(cpu_dai, substream->stream); - - soc_pcm_hw_update_rate(hw, stream); - soc_pcm_hw_update_chan(hw, stream); - soc_pcm_hw_update_format(hw, stream); - } + dpcm_runtime_setup_fe(substream); dpcm_runtime_merge_format(substream, runtime); dpcm_runtime_merge_chan(substream, runtime); From 1b8cb123f3dd6f205541299e2a573237452a6ffe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Feb 2021 09:47:34 +0900 Subject: [PATCH 0079/1091] ASoC: soc-pcm: add dpcm_runtime_setup() dpcm_fe_dai_startup() (= A) calls dpcm_set_fe_runtime() (= B) to setup DPCM runtime. From *naming point of view*, it sounds like setup function for FE. (A) static int dpcm_fe_dai_startup(...) { ... (B) dpcm_set_fe_runtime(...); ... } But in dpcm_set_fe_runtime() (= B), It setups FE by dpcm_runtime_setup_fe() (= X), and setups BE by dpcm_runtime_merge_xxx() (= Y). (B) static void dpcm_set_fe_runtime(...) { ... (X) dpcm_runtime_setup_fe(...); ^ dpcm_runtime_merge_format(...); (Y) dpcm_runtime_merge_chan(...); v dpcm_runtime_merge_rate(...); } These means that the function which is called as xxx_fe_xxx() is setups both FE and BE. This is confusable and can be hot bed for bug. This patch renames unclear dpcm_runtime_merge_xxx() (= Y) to more clear dpcm_runtime_setup_be_xxx(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o8gdvsgr.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 20 +++++++++----------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 066218f1f075..7fc7e3e24444 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1556,10 +1556,10 @@ static void dpcm_runtime_setup_fe(struct snd_pcm_substream *substream) } -static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) +static void dpcm_runtime_setup_be_format(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dpcm *dpcm; struct snd_soc_dai *dai; @@ -1593,10 +1593,10 @@ static void dpcm_runtime_merge_format(struct snd_pcm_substream *substream, } } -static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) +static void dpcm_runtime_setup_be_chan(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1641,10 +1641,10 @@ static void dpcm_runtime_merge_chan(struct snd_pcm_substream *substream, } } -static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, - struct snd_pcm_runtime *runtime) +static void dpcm_runtime_setup_be_rate(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); + struct snd_pcm_runtime *runtime = substream->runtime; struct snd_pcm_hardware *hw = &runtime->hw; struct snd_soc_dpcm *dpcm; int stream = substream->stream; @@ -1680,13 +1680,11 @@ static void dpcm_runtime_merge_rate(struct snd_pcm_substream *substream, static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) { - struct snd_pcm_runtime *runtime = substream->runtime; - dpcm_runtime_setup_fe(substream); - dpcm_runtime_merge_format(substream, runtime); - dpcm_runtime_merge_chan(substream, runtime); - dpcm_runtime_merge_rate(substream, runtime); + dpcm_runtime_setup_be_format(substream); + dpcm_runtime_setup_be_chan(substream); + dpcm_runtime_setup_be_rate(substream); } static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, From 4fe28461e289e7209dc969d5878997069f5be157 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Feb 2021 09:47:36 +0900 Subject: [PATCH 0080/1091] ASoC: soc-pcm: unpack dpcm_set_fe_runtime() dpcm_fe_dai_startup() (= A) calls dpcm_set_fe_runtime() (= B) to setup DPCM runtime. From *naming point of view*, it sounds like setup function for FE. (A) static int dpcm_fe_dai_startup(...) { ... (B) dpcm_set_fe_runtime(...); ... } But in dpcm_set_fe_runtime() (= B), It setups FE by dpcm_runtime_setup_fe() (= X), and setups BE by dpcm_runtime_merge_xxx() (= Y). (B) static void dpcm_set_fe_runtime(...) { ... (X) dpcm_runtime_setup_fe(...); ^ dpcm_runtime_setup_be_format(...); (Y) dpcm_runtime_setup_be_chan(...); v dpcm_runtime_setup_be_rate(...); } These means that the function which is called as xxx_fe_xxx() is setups both FE and BE. This is confusable and can be hot bed for bug. Now dpcm_set_fe_runtime() (= B) is simple enough and confusable naming, let's unpack it at dpcm_fe_dai_startup(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mtvxvsgn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 7fc7e3e24444..511c9218308a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1678,15 +1678,6 @@ static void dpcm_runtime_setup_be_rate(struct snd_pcm_substream *substream) } } -static void dpcm_set_fe_runtime(struct snd_pcm_substream *substream) -{ - dpcm_runtime_setup_fe(substream); - - dpcm_runtime_setup_be_format(substream); - dpcm_runtime_setup_be_chan(substream); - dpcm_runtime_setup_be_rate(substream); -} - static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, int stream) { @@ -1766,7 +1757,11 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; - dpcm_set_fe_runtime(fe_substream); + dpcm_runtime_setup_fe(fe_substream); + + dpcm_runtime_setup_be_format(fe_substream); + dpcm_runtime_setup_be_chan(fe_substream); + dpcm_runtime_setup_be_rate(fe_substream); ret = dpcm_apply_symmetry(fe_substream, stream); if (ret < 0) From 5a81abc2ea3d7cc094b3bef16b0fb0157b8ced0f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:09:13 -0600 Subject: [PATCH 0081/1091] ASoC: samsung: i2s: remove unassigned variable cppcheck warning: sound/soc/samsung/i2s.c:1159:18: style: Variable 'dai' is not assigned a value. [unassignedVariable] struct i2s_dai *dai; ^ This variable is only used for a sizeof(*dai). Signed-off-by: Pierre-Louis Bossart Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210219230918.5058-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/samsung/i2s.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/samsung/i2s.c b/sound/soc/samsung/i2s.c index b043183174b2..c632842d42eb 100644 --- a/sound/soc/samsung/i2s.c +++ b/sound/soc/samsung/i2s.c @@ -1156,11 +1156,10 @@ static int i2s_alloc_dais(struct samsung_i2s_priv *priv, static const char *stream_names[] = { "Primary Playback", "Secondary Playback" }; struct snd_soc_dai_driver *dai_drv; - struct i2s_dai *dai; int i; priv->dai = devm_kcalloc(&priv->pdev->dev, num_dais, - sizeof(*dai), GFP_KERNEL); + sizeof(struct i2s_dai), GFP_KERNEL); if (!priv->dai) return -ENOMEM; From 0587e83c5d8bc09af005bd736234b480a8fd66f2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:09:14 -0600 Subject: [PATCH 0082/1091] ASoC: samsung: s3c24xx_simtec: add missing error check cppcheck warning: sound/soc/samsung/s3c24xx_simtec.c:191:7: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, ^ Looking at the code, it's not clear why the return value is checked in the two other cases but not here, so mirror the behavior and add a check. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210219230918.5058-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/samsung/s3c24xx_simtec.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/sound/soc/samsung/s3c24xx_simtec.c b/sound/soc/samsung/s3c24xx_simtec.c index 3cddd11344ac..81a29d12c57d 100644 --- a/sound/soc/samsung/s3c24xx_simtec.c +++ b/sound/soc/samsung/s3c24xx_simtec.c @@ -190,6 +190,11 @@ static int simtec_hw_params(struct snd_pcm_substream *substream, ret = snd_soc_dai_set_clkdiv(cpu_dai, S3C24XX_DIV_PRESCALER, cdclk_scale); + if (ret) { + pr_err("%s: failed to set clock div\n", + __func__); + return ret; + } } return 0; From fbb123e248c127f9bccdd6181487bcad1275c137 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:09:15 -0600 Subject: [PATCH 0083/1091] ASoC: samsung: smdk_wm8994: add missing return cppcheck warning: sound/soc/samsung/smdk_wm8994.c:179:6: style: Variable 'ret' is reassigned a value before the old one has been used. [redundantAssignment] ret = devm_snd_soc_register_card(&pdev->dev, card); ^ sound/soc/samsung/smdk_wm8994.c:166:8: note: ret is assigned ret = -EINVAL; ^ sound/soc/samsung/smdk_wm8994.c:179:6: note: ret is overwritten ret = devm_snd_soc_register_card(&pdev->dev, card); ^ The initial authors bothered to set ret to -EINVAL and throw a dev_err() message, so it looks like there is a missing return to avoid continuing if the property is missing. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210219230918.5058-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/samsung/smdk_wm8994.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/samsung/smdk_wm8994.c b/sound/soc/samsung/smdk_wm8994.c index 681b244d5312..39a7a449f554 100644 --- a/sound/soc/samsung/smdk_wm8994.c +++ b/sound/soc/samsung/smdk_wm8994.c @@ -164,6 +164,7 @@ static int smdk_audio_probe(struct platform_device *pdev) dev_err(&pdev->dev, "Property 'samsung,i2s-controller' missing or invalid\n"); ret = -EINVAL; + return ret; } smdk_dai[0].platforms->name = NULL; From c856cef731ddfde68ec21a827919aef68e37fb27 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:09:16 -0600 Subject: [PATCH 0084/1091] ASoC: samsung: snow: remove useless test cppcheck warning: sound/soc/samsung/snow.c:112:2: style:inconclusive: Found duplicate branches for 'if' and 'else'. [duplicateBranch] if (rtd->num_codecs > 1) ^ sound/soc/samsung/snow.c:114:2: note: Found duplicate branches for 'if' and 'else'. else ^ sound/soc/samsung/snow.c:112:2: note: Found duplicate branches for 'if' and 'else'. if (rtd->num_codecs > 1) ^ Signed-off-by: Pierre-Louis Bossart Fixes: 7de6b6bc1a58 ("ASoC: samsung: use asoc_rtd_to_cpu() / asoc_rtd_to_codec() macro for DAI pointer") Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210219230918.5058-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/samsung/snow.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/samsung/snow.c b/sound/soc/samsung/snow.c index 989af624dd11..6da674e901ca 100644 --- a/sound/soc/samsung/snow.c +++ b/sound/soc/samsung/snow.c @@ -109,10 +109,7 @@ static int snow_late_probe(struct snd_soc_card *card) rtd = snd_soc_get_pcm_runtime(card, &card->dai_link[0]); /* In the multi-codec case codec_dais 0 is MAX98095 and 1 is HDMI. */ - if (rtd->num_codecs > 1) - codec_dai = asoc_rtd_to_codec(rtd, 0); - else - codec_dai = asoc_rtd_to_codec(rtd, 0); + codec_dai = asoc_rtd_to_codec(rtd, 0); /* Set the MCLK rate for the codec */ return snd_soc_dai_set_sysclk(codec_dai, 0, From 7ca5f04946176ae9611bb80e3ec3d3fa300b7cff Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:19:16 -0600 Subject: [PATCH 0085/1091] ASoC: soc-ops: remove useless assignment cppcheck warning: sound/soc/soc-ops.c:410:35: style: Variable 'val2' is assigned a value that is never used. [unreadVariable] unsigned int val, val_mask, val2 = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210218221921.88991-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-ops.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-ops.c b/sound/soc/soc-ops.c index 10f48827bb0e..58527247df83 100644 --- a/sound/soc/soc-ops.c +++ b/sound/soc/soc-ops.c @@ -407,7 +407,7 @@ int snd_soc_put_volsw_sx(struct snd_kcontrol *kcontrol, int min = mc->min; unsigned int mask = (1U << (fls(min + max) - 1)) - 1; int err = 0; - unsigned int val, val_mask, val2 = 0; + unsigned int val, val_mask, val2; val_mask = mask << shift; val = (ucontrol->value.integer.value[0] + min) & mask; From 9dbe774091b0e473509221f7dcef0795b5380298 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:19:17 -0600 Subject: [PATCH 0086/1091] ASoC: soc-pcm: remove redundant assignment cppcheck warning: sound/soc/soc-pcm.c:2398:7: style: Variable 'ret' is reassigned a value before the old one has been used. [redundantAssignment] ret = -EINVAL; ^ sound/soc/soc-pcm.c:2395:7: note: ret is assigned ret = -EINVAL; ^ sound/soc/soc-pcm.c:2398:7: note: ret is overwritten ret = -EINVAL; ^ This looks like a copy/paste or git merge issue. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210218221921.88991-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 14d85ca1e435..12fd10a6c190 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2395,7 +2395,6 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) /* Only start the BE if the FE is ready */ if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_FREE || fe->dpcm[stream].state == SND_SOC_DPCM_STATE_CLOSE) { - ret = -EINVAL; dev_err(fe->dev, "ASoC: FE %s is not ready %d\n", fe->dai_link->name, fe->dpcm[stream].state); ret = -EINVAL; From 61b9eedd93b1f55e922dfd3ac3cb844e2b69b808 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:19:18 -0600 Subject: [PATCH 0087/1091] ASoC: soc-pcm: remove shadowing variable cppcheck warning: sound/soc/soc-pcm.c:1718:7: style: Local variable 'i' shadows outer variable [shadowVariable] int i; ^ sound/soc/soc-pcm.c:1696:6: note: Shadowed declaration int i; ^ sound/soc/soc-pcm.c:1718:7: note: Shadow variable int i; ^ the second variable seems totally unnecessary. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210218221921.88991-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 12fd10a6c190..705fb2d548a9 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1718,7 +1718,6 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, snd_soc_dpcm_get_substream(be, stream); struct snd_soc_pcm_runtime *rtd; struct snd_soc_dai *dai; - int i; /* A backend may not have the requested substream */ if (!be_substream) From 61456212e80ee274828d2d14fcc7b9364dfc0744 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:19:19 -0600 Subject: [PATCH 0088/1091] ASoC: soc-pcm: add error log cppcheck warning: sound/soc/soc-pcm.c:1907:6: style: Variable 'err' is assigned a value that is never used. [unreadVariable] err = dpcm_be_dai_hw_free(fe, stream); ^ it's not clear why dpcm_be_dai_hw_free() is sometimes called without testing the error status, and sometimes an error message is provided. When in doubt, add an error message for consistency. This may have to be revisited. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210218221921.88991-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 705fb2d548a9..2de69dc240bd 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1907,6 +1907,8 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) /* only hw_params backends that are either sinks or sources * to this frontend DAI */ err = dpcm_be_dai_hw_free(fe, stream); + if (err < 0) + dev_err(fe->dev, "ASoC: hw_free BE failed %d\n", err); fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); From 47108a61b2f7f5a9eb13f88691f03147c4f9fc40 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:19:20 -0600 Subject: [PATCH 0089/1091] ASoC: soc-topology: clarify expression cppcheck warning: sound/soc/soc-topology.c:1676:52: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0; ^ sound/soc/soc-topology.c:1680:55: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS ? ^ sound/soc/soc-topology.c:1685:57: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ? ^ sound/soc/soc-topology.c:1768:52: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES ? 1 : 0; ^ sound/soc/soc-topology.c:1772:55: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS ? ^ sound/soc/soc-topology.c:1777:57: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS ? ^ sound/soc/soc-topology.c:1782:48: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] flags & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP ? ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210218221921.88991-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-topology.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 1b0cd33a1348..73076d425efb 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1673,16 +1673,16 @@ static void set_dai_flags(struct snd_soc_dai_driver *dai_drv, { if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES) dai_drv->symmetric_rate = - flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES ? 1 : 0; + (flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_RATES) ? 1 : 0; if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS) dai_drv->symmetric_channels = - flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS ? + (flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_CHANNELS) ? 1 : 0; if (flag_mask & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS) dai_drv->symmetric_sample_bits = - flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS ? + (flags & SND_SOC_TPLG_DAI_FLGBIT_SYMMETRIC_SAMPLEBITS) ? 1 : 0; } @@ -1765,22 +1765,22 @@ static void set_link_flags(struct snd_soc_dai_link *link, { if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES) link->symmetric_rate = - flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES ? 1 : 0; + (flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_RATES) ? 1 : 0; if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS) link->symmetric_channels = - flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS ? + (flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_CHANNELS) ? 1 : 0; if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS) link->symmetric_sample_bits = - flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS ? + (flags & SND_SOC_TPLG_LNK_FLGBIT_SYMMETRIC_SAMPLEBITS) ? 1 : 0; if (flag_mask & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP) link->ignore_suspend = - flags & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP ? - 1 : 0; + (flags & SND_SOC_TPLG_LNK_FLGBIT_VOICE_WAKEUP) ? + 1 : 0; } /* create the FE DAI link */ From bd029fc86834760276171bd2301d6c43e45a65b0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 18 Feb 2021 16:19:21 -0600 Subject: [PATCH 0090/1091] ASoC: generic: simple-card-utils: remove useless assignment cppcheck warning: sound/soc/generic/simple-card-utils.c:258:10: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int ret = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210218221921.88991-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index ab31045cfc95..06c2512b6f2d 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -254,7 +254,7 @@ int asoc_simple_hw_params(struct snd_pcm_substream *substream, struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); unsigned int mclk, mclk_fs = 0; - int ret = 0; + int ret; if (dai_props->mclk_fs) mclk_fs = dai_props->mclk_fs; From 77150b5a5a473ec35c0bf6f1a8b966329ad9439d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:16:28 -0600 Subject: [PATCH 0091/1091] ASoC: sh: dma-sh7760: remove unused variable cppcheck warning: sound/soc/sh/dma-sh7760.c:180:6: style: Unused variable: ret [unusedVariable] int ret; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219231635.5749-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sh/dma-sh7760.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sh/dma-sh7760.c b/sound/soc/sh/dma-sh7760.c index b70068dd5a06..121e48f984c5 100644 --- a/sound/soc/sh/dma-sh7760.c +++ b/sound/soc/sh/dma-sh7760.c @@ -177,7 +177,6 @@ static int camelot_hw_params(struct snd_soc_component *component, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct camelot_pcm *cam = &cam_pcm_data[asoc_rtd_to_cpu(rtd, 0)->id]; int recv = substream->stream == SNDRV_PCM_STREAM_PLAYBACK ? 0:1; - int ret; if (recv) { cam->rx_period_size = params_period_bytes(hw_params); From d29a60604fe6cb8d4dc1782dbfe893dacb7f57e2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:16:29 -0600 Subject: [PATCH 0092/1091] ASoC: sh: rcar: align function prototypes cppcheck warnings: sound/soc/sh/rcar/adg.c:208:51: style:inconclusive: Function 'rsnd_adg_set_cmd_timsel_gen2' argument 1 names different: declaration 'mod' definition 'cmd_mod'. [funcArgNamesDifferent] int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod, ^ sound/soc/sh/rcar/rsnd.h:608:51: note: Function 'rsnd_adg_set_cmd_timsel_gen2' argument 1 names different: declaration 'mod' definition 'cmd_mod'. int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod, ^ sound/soc/sh/rcar/adg.c:208:51: note: Function 'rsnd_adg_set_cmd_timsel_gen2' argument 1 names different: declaration 'mod' definition 'cmd_mod'. int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod, ^ sound/soc/sh/rcar/adg.c:322:44: style:inconclusive: Function 'rsnd_adg_ssi_clk_stop' argument 1 names different: declaration 'mod' definition 'ssi_mod'. [funcArgNamesDifferent] int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod) ^ sound/soc/sh/rcar/rsnd.h:600:44: note: Function 'rsnd_adg_ssi_clk_stop' argument 1 names different: declaration 'mod' definition 'ssi_mod'. int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); ^ sound/soc/sh/rcar/adg.c:322:44: note: Function 'rsnd_adg_ssi_clk_stop' argument 1 names different: declaration 'mod' definition 'ssi_mod'. int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod) ^ sound/soc/sh/rcar/adg.c:329:49: style:inconclusive: Function 'rsnd_adg_ssi_clk_try_start' argument 1 names different: declaration 'mod' definition 'ssi_mod'. [funcArgNamesDifferent] int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ^ sound/soc/sh/rcar/rsnd.h:601:49: note: Function 'rsnd_adg_ssi_clk_try_start' argument 1 names different: declaration 'mod' definition 'ssi_mod'. int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); ^ sound/soc/sh/rcar/adg.c:329:49: note: Function 'rsnd_adg_ssi_clk_try_start' argument 1 names different: declaration 'mod' definition 'ssi_mod'. int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate) ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219231635.5749-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/rsnd.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/sh/rcar/rsnd.h b/sound/soc/sh/rcar/rsnd.h index 6b519370fd64..1255a85151db 100644 --- a/sound/soc/sh/rcar/rsnd.h +++ b/sound/soc/sh/rcar/rsnd.h @@ -597,15 +597,15 @@ phys_addr_t rsnd_gen_get_phy_addr(struct rsnd_priv *priv, int reg_id); * R-Car ADG */ int rsnd_adg_clk_query(struct rsnd_priv *priv, unsigned int rate); -int rsnd_adg_ssi_clk_stop(struct rsnd_mod *mod); -int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *mod, unsigned int rate); +int rsnd_adg_ssi_clk_stop(struct rsnd_mod *ssi_mod); +int rsnd_adg_ssi_clk_try_start(struct rsnd_mod *ssi_mod, unsigned int rate); int rsnd_adg_probe(struct rsnd_priv *priv); void rsnd_adg_remove(struct rsnd_priv *priv); int rsnd_adg_set_src_timesel_gen2(struct rsnd_mod *src_mod, struct rsnd_dai_stream *io, unsigned int in_rate, unsigned int out_rate); -int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *mod, +int rsnd_adg_set_cmd_timsel_gen2(struct rsnd_mod *cmd_mod, struct rsnd_dai_stream *io); #define rsnd_adg_clk_enable(priv) rsnd_adg_clk_control(priv, 1) #define rsnd_adg_clk_disable(priv) rsnd_adg_clk_control(priv, 0) From 652fc90f9de4ab0ba023cbdf5b0853f9447d7966 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:16:30 -0600 Subject: [PATCH 0093/1091] ASoC: sh: rcar: simplify return cppcheck warning: sound/soc/sh/rcar/core.c:219:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/sh/rcar/core.c:210:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/sh/rcar/core.c:219:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219231635.5749-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1029d8d9d800..a07c77dd5250 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -216,7 +216,7 @@ int rsnd_mod_init(struct rsnd_priv *priv, mod->clk = clk; mod->priv = priv; - return ret; + return 0; } void rsnd_mod_quit(struct rsnd_mod *mod) From 4862811f87350c3656e86dfc3ce310d0390d48ab Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:16:32 -0600 Subject: [PATCH 0094/1091] ASoC: sh: rcar: ctu: add missing error check cppcheck warning: sound/soc/sh/rcar/ctu.c:212:6: style: Variable 'ret' is reassigned a value before the old one has been used. [redundantAssignment] ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0", ^ sound/soc/sh/rcar/ctu.c:205:6: note: ret is assigned ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU Pass", ^ sound/soc/sh/rcar/ctu.c:212:6: note: ret is overwritten ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0", ^ All the kcontrol creations are checked for errors, except for one. Add the missing error check. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219231635.5749-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ctu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sh/rcar/ctu.c b/sound/soc/sh/rcar/ctu.c index 7647b3d4c0ba..20eecd088d13 100644 --- a/sound/soc/sh/rcar/ctu.c +++ b/sound/soc/sh/rcar/ctu.c @@ -207,6 +207,8 @@ static int rsnd_ctu_pcm_new(struct rsnd_mod *mod, NULL, &ctu->pass, RSND_MAX_CHANNELS, 0xC); + if (ret < 0) + return ret; /* ROW0 */ ret = rsnd_kctrl_new_m(mod, io, rtd, "CTU SV0", From 9946871c608739b76c95d62aed70f9ee4f2d6747 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:16:33 -0600 Subject: [PATCH 0095/1091] ASoC: sh: rcar: ssi: remove redundant assignment cppcheck warning: sound/soc/sh/rcar/ssi.c:403:6: style: Redundant initialization for 'wsr'. The initialized value is overwritten before it is read. [redundantInitialization] wsr = ssi->wsr; ^ sound/soc/sh/rcar/ssi.c:372:11: note: wsr is initialized u32 wsr = ssi->wsr; ^ sound/soc/sh/rcar/ssi.c:403:6: note: wsr is overwritten wsr = ssi->wsr; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219231635.5749-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d0ded427a836..659b25992ff2 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -400,7 +400,6 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, * see * rsnd_ssiu_init_gen2() */ - wsr = ssi->wsr; if (is_tdm || is_tdm_split) { wsr |= WS_MODE; cr_own |= CHNL_8; From eeff1df1fa13126f6024eb6dd0075b3182a3e011 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:16:34 -0600 Subject: [PATCH 0096/1091] ASoC: sh: siu_pcm: remove useless assignment cppcheck warning: sound/soc/sh/siu_pcm.c:375:5: style: Redundant initialization for 'rt'. The initialized value is overwritten before it is read. [redundantInitialization] rt = siu_stream->substream->runtime; ^ sound/soc/sh/siu_pcm.c:366:30: note: rt is initialized struct snd_pcm_runtime *rt = ss->runtime; ^ sound/soc/sh/siu_pcm.c:375:5: note: rt is overwritten rt = siu_stream->substream->runtime; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219231635.5749-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sh/siu_pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 4785886df4f0..6496300f73a9 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -363,7 +363,7 @@ static int siu_pcm_prepare(struct snd_soc_component *component, struct siu_info *info = siu_i2s_data; struct siu_port *port_info = siu_port_info(ss); struct device *dev = ss->pcm->card->dev; - struct snd_pcm_runtime *rt = ss->runtime; + struct snd_pcm_runtime *rt; struct siu_stream *siu_stream; snd_pcm_sframes_t xfer_cnt; From b7e41867a4c9e3613494fbda1c5995f9ed39f3f1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 19 Feb 2021 17:16:35 -0600 Subject: [PATCH 0097/1091] ASoC: sh: siu_pcm: remove unused variable cppcheck warning: sound/soc/sh/siu_pcm.c:225:8: style: Variable 'virt' is assigned a value that is never used. [unreadVariable] virt = PERIOD_OFFSET(rt->dma_area, ^ It's not clear what this variable was needed for, remove it. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210219231635.5749-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sh/siu_pcm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/sound/soc/sh/siu_pcm.c b/sound/soc/sh/siu_pcm.c index 6496300f73a9..0a8a3c314a73 100644 --- a/sound/soc/sh/siu_pcm.c +++ b/sound/soc/sh/siu_pcm.c @@ -217,14 +217,10 @@ static void siu_io_work(struct work_struct *work) if (substream->stream == SNDRV_PCM_STREAM_CAPTURE) { dma_addr_t buff; size_t count; - u8 *virt; buff = (dma_addr_t)PERIOD_OFFSET(rt->dma_addr, siu_stream->cur_period, siu_stream->period_bytes); - virt = PERIOD_OFFSET(rt->dma_area, - siu_stream->cur_period, - siu_stream->period_bytes); count = siu_stream->period_bytes; /* DMA transfer start */ From 64ca77d9f55afbbe5e63b1d290cade4acfb8e4fa Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 13 Feb 2021 11:19:04 +0100 Subject: [PATCH 0098/1091] ASoC: mmp-sspa: drop unneeded snd_soc_dai_set_drvdata snd_soc_dai_set_drvdata is not needed when the set data comes from snd_soc_dai_get_drvdata or dev_get_drvdata. The problem was fixed usingthe following semantic patch: (http://coccinelle.lip6.fr/) // @@ expression x,y,e; @@ x = dev_get_drvdata(y->dev) ... when != x = e - snd_soc_dai_set_drvdata(y,x); @@ expression x,y,e; @@ x = snd_soc_dai_get_drvdata(y) ... when != x = e - snd_soc_dai_set_drvdata(y,x); // Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20210213101907.1318496-2-Julia.Lawall@inria.fr Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-sspa.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/pxa/mmp-sspa.c b/sound/soc/pxa/mmp-sspa.c index 4803972ee655..7e39210a0b38 100644 --- a/sound/soc/pxa/mmp-sspa.c +++ b/sound/soc/pxa/mmp-sspa.c @@ -330,7 +330,6 @@ static int mmp_sspa_probe(struct snd_soc_dai *dai) &sspa->playback_dma_data, &sspa->capture_dma_data); - snd_soc_dai_set_drvdata(dai, sspa); return 0; } From b8fdf60931440296912e35bfe08b351fd3c37d11 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 13 Feb 2021 11:19:05 +0100 Subject: [PATCH 0099/1091] ASoC: mxs-saif: drop unneeded snd_soc_dai_set_drvdata snd_soc_dai_set_drvdata is not needed when the set data comes from snd_soc_dai_get_drvdata or dev_get_drvdata. The problem was fixed usingthe following semantic patch: (http://coccinelle.lip6.fr/) // @@ expression x,y,e; @@ x = dev_get_drvdata(y->dev) ... when != x = e - snd_soc_dai_set_drvdata(y,x); @@ expression x,y,e; @@ x = snd_soc_dai_get_drvdata(y) ... when != x = e - snd_soc_dai_set_drvdata(y,x); // In this case, the whole probe function then does nothing, so drop it. Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20210213101907.1318496-3-Julia.Lawall@inria.fr Signed-off-by: Mark Brown --- sound/soc/mxs/mxs-saif.c | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/sound/soc/mxs/mxs-saif.c b/sound/soc/mxs/mxs-saif.c index 07f8cf9980e3..6a2d24d48964 100644 --- a/sound/soc/mxs/mxs-saif.c +++ b/sound/soc/mxs/mxs-saif.c @@ -642,18 +642,8 @@ static const struct snd_soc_dai_ops mxs_saif_dai_ops = { .set_fmt = mxs_saif_set_dai_fmt, }; -static int mxs_saif_dai_probe(struct snd_soc_dai *dai) -{ - struct mxs_saif *saif = dev_get_drvdata(dai->dev); - - snd_soc_dai_set_drvdata(dai, saif); - - return 0; -} - static struct snd_soc_dai_driver mxs_saif_dai = { .name = "mxs-saif", - .probe = mxs_saif_dai_probe, .playback = { .channels_min = 2, .channels_max = 2, From 36785fec16bed809f622bd523c4cabdfefa9e836 Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 13 Feb 2021 11:19:06 +0100 Subject: [PATCH 0100/1091] ASoC: sun4i-i2s: drop unneeded snd_soc_dai_set_drvdata snd_soc_dai_set_drvdata is not needed when the set data comes from snd_soc_dai_get_drvdata or dev_get_drvdata. The problem was fixed usingthe following semantic patch: (http://coccinelle.lip6.fr/) // @@ expression x,y,e; @@ x = dev_get_drvdata(y->dev) ... when != x = e - snd_soc_dai_set_drvdata(y,x); @@ expression x,y,e; @@ x = snd_soc_dai_get_drvdata(y) ... when != x = e - snd_soc_dai_set_drvdata(y,x); // Signed-off-by: Julia Lawall Link: https://lore.kernel.org/r/20210213101907.1318496-4-Julia.Lawall@inria.fr Signed-off-by: Mark Brown --- sound/soc/sunxi/sun4i-i2s.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/sunxi/sun4i-i2s.c b/sound/soc/sunxi/sun4i-i2s.c index 78506c3811dc..c57feae3396e 100644 --- a/sound/soc/sunxi/sun4i-i2s.c +++ b/sound/soc/sunxi/sun4i-i2s.c @@ -1079,8 +1079,6 @@ static int sun4i_i2s_dai_probe(struct snd_soc_dai *dai) &i2s->playback_dma_data, &i2s->capture_dma_data); - snd_soc_dai_set_drvdata(dai, i2s); - return 0; } From eb0d22d793e82c126ce922fda387c29fe26a2bff Mon Sep 17 00:00:00 2001 From: Julia Lawall Date: Sat, 13 Feb 2021 11:19:07 +0100 Subject: [PATCH 0101/1091] ASoC: fsl: drop unneeded snd_soc_dai_set_drvdata snd_soc_dai_set_drvdata is not needed when the set data comes from snd_soc_dai_get_drvdata or dev_get_drvdata. The problem was fixed usingthe following semantic patch: (http://coccinelle.lip6.fr/) // @@ expression x,y,e; @@ x = dev_get_drvdata(y->dev) ... when != x = e - snd_soc_dai_set_drvdata(y,x); @@ expression x,y,e; @@ x = snd_soc_dai_get_drvdata(y) ... when != x = e - snd_soc_dai_set_drvdata(y,x); // Signed-off-by: Julia Lawall Acked-by: Nicolin Chen Link: https://lore.kernel.org/r/20210213101907.1318496-5-Julia.Lawall@inria.fr Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 2 -- sound/soc/fsl/fsl_sai.c | 2 -- sound/soc/fsl/fsl_xcvr.c | 1 - 3 files changed, 5 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 5935af2e5ff4..2b9edd4bb94d 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -423,8 +423,6 @@ static int fsl_micfil_dai_probe(struct snd_soc_dai *cpu_dai) return ret; } - snd_soc_dai_set_drvdata(cpu_dai, micfil); - return 0; } diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 5e65b456d3e2..8876d0ed37d9 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -727,8 +727,6 @@ static int fsl_sai_dai_probe(struct snd_soc_dai *cpu_dai) snd_soc_dai_init_dma_data(cpu_dai, &sai->dma_params_tx, &sai->dma_params_rx); - snd_soc_dai_set_drvdata(cpu_dai, sai); - return 0; } diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 6dd0a5fcd455..4f33dbe29c78 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -869,7 +869,6 @@ static int fsl_xcvr_dai_probe(struct snd_soc_dai *dai) struct fsl_xcvr *xcvr = snd_soc_dai_get_drvdata(dai); snd_soc_dai_init_dma_data(dai, &xcvr->dma_prms_tx, &xcvr->dma_prms_rx); - snd_soc_dai_set_drvdata(dai, xcvr); snd_soc_add_dai_controls(dai, &fsl_xcvr_mode_kctl, 1); snd_soc_add_dai_controls(dai, &fsl_xcvr_arc_mode_kctl, 1); From 929cc78260550e82fc481c8c9428ec2aa589d88c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Feb 2021 09:25:02 +0900 Subject: [PATCH 0102/1091] ASoC: rsnd: cleanup ppcheck warning for ssiu.c This patch cleanups below ppcheck warning. sound/soc/sh/rcar/ssiu.c:212:10: style: The scope of the variable 'shift' can be reduced. [variableScope] int i, shift; ^ sound/soc/sh/rcar/ssiu.c:337:19: style: The scope of the variable 'mod' can be reduced. [variableScope] struct rsnd_mod *mod; ^ sound/soc/sh/rcar/ssiu.c:362:22: style: The scope of the variable 'np' can be reduced. [variableScope] struct device_node *np; ^ sound/soc/sh/rcar/ssiu.c:363:19: style: The scope of the variable 'mod' can be reduced. [variableScope] struct rsnd_mod *mod; ^ sound/soc/sh/rcar/ssiu.c:366:6: style: The scope of the variable 'i' can be reduced. [variableScope] int i; ^ sound/soc/sh/rcar/ssiu.c:397:13: style: The scope of the variable 'ret' can be reduced. [variableScope] int i, nr, ret; ^ Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfbdro2p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssiu.c | 22 ++++++++++++---------- 1 file changed, 12 insertions(+), 10 deletions(-) diff --git a/sound/soc/sh/rcar/ssiu.c b/sound/soc/sh/rcar/ssiu.c index f29bd72f3a26..852cdeedf7e9 100644 --- a/sound/soc/sh/rcar/ssiu.c +++ b/sound/soc/sh/rcar/ssiu.c @@ -209,7 +209,7 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); struct rsnd_mod *pos; u32 val; - int i, shift; + int i; i = rsnd_mod_id(ssi_mod); @@ -221,7 +221,8 @@ static int rsnd_ssiu_init_gen2(struct rsnd_mod *mod, i; for_each_rsnd_mod_array(i, pos, io, rsnd_ssi_array) { - shift = (i * 4) + 20; + int shift = (i * 4) + 20; + val = (val & ~(0xF << shift)) | rsnd_mod_id(pos) << shift; } @@ -334,7 +335,6 @@ static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, struct rsnd_dai_stream *io) { struct rsnd_mod *ssi_mod = rsnd_io_to_mod_ssi(io); - struct rsnd_mod *mod; struct rsnd_ssiu *ssiu; int i; @@ -343,7 +343,7 @@ static void rsnd_parse_connect_ssiu_compatible(struct rsnd_priv *priv, /* select BUSIF0 */ for_each_rsnd_ssiu(ssiu, priv, i) { - mod = rsnd_mod_get(ssiu); + struct rsnd_mod *mod = rsnd_mod_get(ssiu); if ((rsnd_mod_id(ssi_mod) == rsnd_mod_id(mod)) && (rsnd_mod_id_sub(mod) == 0)) { @@ -359,17 +359,17 @@ void rsnd_parse_connect_ssiu(struct rsnd_dai *rdai, { struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); struct device_node *node = rsnd_ssiu_of_node(priv); - struct device_node *np; - struct rsnd_mod *mod; struct rsnd_dai_stream *io_p = &rdai->playback; struct rsnd_dai_stream *io_c = &rdai->capture; - int i; /* use rcar_sound,ssiu if exist */ if (node) { - i = 0; + struct device_node *np; + int i = 0; + for_each_child_of_node(node, np) { - mod = rsnd_ssiu_mod_get(priv, i); + struct rsnd_mod *mod = rsnd_ssiu_mod_get(priv, i); + if (np == playback) rsnd_dai_connect(mod, io_p, mod->type); if (np == capture) @@ -394,7 +394,7 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) struct rsnd_ssiu *ssiu; struct rsnd_mod_ops *ops; const int *list = NULL; - int i, nr, ret; + int i, nr; /* * Keep DT compatibility. @@ -441,6 +441,8 @@ int rsnd_ssiu_probe(struct rsnd_priv *priv) } for_each_rsnd_ssiu(ssiu, priv, i) { + int ret; + if (node) { int j; From 0779baa812cf27325ad1d43a917144f50ffd2142 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Feb 2021 09:25:08 +0900 Subject: [PATCH 0103/1091] ASoC: rsnd: cleanup ppcheck warning for ssi.c This patch cleanups below ppcheck warning. sound/soc/sh/rcar/ssi.c:170:19: style: The scope of the variable 'mod' can be reduced. [variableScope] struct rsnd_mod *mod; ^ sound/soc/sh/rcar/ssi.c:535:6: style: The scope of the variable 'i' can be reduced. [variableScope] int i; ^ sound/soc/sh/rcar/ssi.c:1212:19: style: The scope of the variable 'mod' can be reduced. [variableScope] struct rsnd_mod *mod; ^ sound/soc/sh/rcar/ssi.c:328:16: portability: Shifting signed 32-bit value by 31 bits is implementation-defined behaviour [shiftTooManyBitsSigned] ssi->cr_clk = FORCE | rsnd_rdai_width_to_swl(rdai) | ^ sound/soc/sh/rcar/ssi.c:387:12: portability: Shifting signed 32-bit value by 31 bits is implementation-defined behaviour [shiftTooManyBitsSigned] cr_own |= FORCE | rsnd_rdai_width_to_swl(rdai); ^ Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0qxro2j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 45 +++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 22 deletions(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d0ded427a836..49aa81ff9361 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -24,23 +24,23 @@ /* * SSICR */ -#define FORCE (1 << 31) /* Fixed */ -#define DMEN (1 << 28) /* DMA Enable */ -#define UIEN (1 << 27) /* Underflow Interrupt Enable */ -#define OIEN (1 << 26) /* Overflow Interrupt Enable */ -#define IIEN (1 << 25) /* Idle Mode Interrupt Enable */ -#define DIEN (1 << 24) /* Data Interrupt Enable */ -#define CHNL_4 (1 << 22) /* Channels */ -#define CHNL_6 (2 << 22) /* Channels */ -#define CHNL_8 (3 << 22) /* Channels */ -#define DWL_MASK (7 << 19) /* Data Word Length mask */ -#define DWL_8 (0 << 19) /* Data Word Length */ -#define DWL_16 (1 << 19) /* Data Word Length */ -#define DWL_18 (2 << 19) /* Data Word Length */ -#define DWL_20 (3 << 19) /* Data Word Length */ -#define DWL_22 (4 << 19) /* Data Word Length */ -#define DWL_24 (5 << 19) /* Data Word Length */ -#define DWL_32 (6 << 19) /* Data Word Length */ +#define FORCE (1u << 31) /* Fixed */ +#define DMEN (1u << 28) /* DMA Enable */ +#define UIEN (1u << 27) /* Underflow Interrupt Enable */ +#define OIEN (1u << 26) /* Overflow Interrupt Enable */ +#define IIEN (1u << 25) /* Idle Mode Interrupt Enable */ +#define DIEN (1u << 24) /* Data Interrupt Enable */ +#define CHNL_4 (1u << 22) /* Channels */ +#define CHNL_6 (2u << 22) /* Channels */ +#define CHNL_8 (3u << 22) /* Channels */ +#define DWL_MASK (7u << 19) /* Data Word Length mask */ +#define DWL_8 (0u << 19) /* Data Word Length */ +#define DWL_16 (1u << 19) /* Data Word Length */ +#define DWL_18 (2u << 19) /* Data Word Length */ +#define DWL_20 (3u << 19) /* Data Word Length */ +#define DWL_22 (4u << 19) /* Data Word Length */ +#define DWL_24 (5u << 19) /* Data Word Length */ +#define DWL_32 (6u << 19) /* Data Word Length */ /* * System word length @@ -167,7 +167,6 @@ static void rsnd_ssi_status_check(struct rsnd_mod *mod, static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) { - struct rsnd_mod *mod; enum rsnd_mod_type types[] = { RSND_MOD_SSIM1, RSND_MOD_SSIM2, @@ -177,7 +176,8 @@ static u32 rsnd_ssi_multi_secondaries(struct rsnd_dai_stream *io) mask = 0; for (i = 0; i < ARRAY_SIZE(types); i++) { - mod = rsnd_io_to_mod(io, types[i]); + struct rsnd_mod *mod = rsnd_io_to_mod(io, types[i]); + if (!mod) continue; @@ -533,7 +533,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, struct device *dev = rsnd_priv_to_dev(priv); int is_tdm, is_tdm_split; int id = rsnd_mod_id(mod); - int i; u32 sys_int_enable = 0; is_tdm = rsnd_runtime_is_tdm(io); @@ -561,6 +560,8 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, /* disable busif buffer over/under run interrupt. */ if (is_tdm || is_tdm_split) { + int i; + switch (id) { case 0: case 1: @@ -1210,7 +1211,6 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); struct device_node *node; struct device_node *np; - struct rsnd_mod *mod; int i; node = rsnd_ssi_of_node(priv); @@ -1219,7 +1219,8 @@ void rsnd_parse_connect_ssi(struct rsnd_dai *rdai, i = 0; for_each_child_of_node(node, np) { - mod = rsnd_ssi_mod_get(priv, i); + struct rsnd_mod *mod = rsnd_ssi_mod_get(priv, i); + if (np == playback) rsnd_ssi_connect(mod, &rdai->playback); if (np == capture) From e539943c664e58a7005959f2c902d1fbda464b59 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Feb 2021 09:25:14 +0900 Subject: [PATCH 0104/1091] ASoC: rsnd: cleanup ppcheck warning for core.c This patch cleanups below ppcheck warning. sound/soc/sh/rcar/core.c:233:26: style: The scope of the variable 'io' can be reduced. [variableScope] struct rsnd_dai_stream *io; ^ sound/soc/sh/rcar/core.c:489:19: style: The scope of the variable 'mod' can be reduced. [variableScope] struct rsnd_mod *mod; ^ sound/soc/sh/rcar/core.c:1064:9: style: The scope of the variable 'j' can be reduced. [variableScope] int i, j; ^ sound/soc/sh/rcar/core.c:1143:19: style: The scope of the variable 'mod' can be reduced. [variableScope] struct rsnd_mod *mod; ^ sound/soc/sh/rcar/core.c:1261:22: style: The scope of the variable 'playback' can be reduced. [variableScope] struct device_node *playback, *capture; ^ sound/soc/sh/rcar/core.c:1261:33: style: The scope of the variable 'capture' can be reduced. [variableScope] struct device_node *playback, *capture; ^ sound/soc/sh/rcar/core.c:1419:29: style: The scope of the variable 'be_params' can be reduced. [variableScope] struct snd_pcm_hw_params *be_params; ^ sound/soc/sh/rcar/core.c:1369:22: style: Local variable 'rdai' shadows outer variable [shadowVariable] struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); ^ sound/soc/sh/rcar/core.c:1338:19: note: Shadowed declaration struct rsnd_dai *rdai; ^ sound/soc/sh/rcar/core.c:1369:22: note: Shadow variable struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); ^ sound/soc/sh/rcar/core.c:1380:22: style: Local variable 'rdai' shadows outer variable [shadowVariable] struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); ^ Reported-by: Pierre-Louis Bossart Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87im6hro2d.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index 1029d8d9d800..ee1f320935db 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -230,12 +230,12 @@ void rsnd_mod_interrupt(struct rsnd_mod *mod, struct rsnd_dai_stream *io)) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); - struct rsnd_dai_stream *io; struct rsnd_dai *rdai; int i; for_each_rsnd_dai(rdai, priv, i) { - io = &rdai->playback; + struct rsnd_dai_stream *io = &rdai->playback; + if (mod == io->mod[mod->type]) callback(mod, io); @@ -486,13 +486,12 @@ struct rsnd_mod *rsnd_mod_next(int *iterator, enum rsnd_mod_type *array, int array_size) { - struct rsnd_mod *mod; - enum rsnd_mod_type type; int max = array ? array_size : RSND_MOD_MAX; for (; *iterator < max; (*iterator)++) { - type = (array) ? array[*iterator] : *iterator; - mod = rsnd_io_to_mod(io, type); + enum rsnd_mod_type type = (array) ? array[*iterator] : *iterator; + struct rsnd_mod *mod = rsnd_io_to_mod(io, type); + if (mod) return mod; } @@ -1061,7 +1060,7 @@ static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv, struct device_node *ssiu_np = rsnd_ssiu_of_node(priv); struct device_node *np; int is_play = rsnd_io_is_play(io); - int i, j; + int i; if (!ssiu_np) return; @@ -1078,13 +1077,11 @@ static void rsnd_parse_tdm_split_mode(struct rsnd_priv *priv, if (!node) break; - j = 0; for_each_child_of_node(ssiu_np, np) { if (np == node) { rsnd_flags_set(io, RSND_STREAM_TDM_SPLIT); dev_dbg(dev, "%s is part of TDM Split\n", io->name); } - j++; } of_node_put(node); @@ -1140,7 +1137,6 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, { struct rsnd_priv *priv = rsnd_rdai_to_priv(rdai); struct device_node *np; - struct rsnd_mod *mod; int i; if (!node) @@ -1148,7 +1144,8 @@ void rsnd_parse_connect_common(struct rsnd_dai *rdai, i = 0; for_each_child_of_node(node, np) { - mod = mod_get(priv, i); + struct rsnd_mod *mod = mod_get(priv, i); + if (np == playback) rsnd_dai_connect(mod, &rdai->playback, mod->type); if (np == capture) @@ -1258,7 +1255,6 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, struct device_node *dai_np, int dai_i) { - struct device_node *playback, *capture; struct rsnd_dai_stream *io_playback; struct rsnd_dai_stream *io_capture; struct snd_soc_dai_driver *drv; @@ -1301,8 +1297,8 @@ static void __rsnd_dai_probe(struct rsnd_priv *priv, rsnd_rdai_width_set(rdai, 32); /* default 32bit width */ for (io_i = 0;; io_i++) { - playback = of_parse_phandle(dai_np, "playback", io_i); - capture = of_parse_phandle(dai_np, "capture", io_i); + struct device_node *playback = of_parse_phandle(dai_np, "playback", io_i); + struct device_node *capture = of_parse_phandle(dai_np, "capture", io_i); if (!playback && !capture) break; @@ -1366,7 +1362,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) for_each_endpoint_of_node(dai_node, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_i); if (rsnd_is_gen3(priv)) { - struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); + rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_graph(priv, &rdai->playback, dai_np); rsnd_parse_connect_graph(priv, &rdai->capture, dai_np); @@ -1377,7 +1373,7 @@ static int rsnd_dai_probe(struct rsnd_priv *priv) for_each_child_of_node(dai_node, dai_np) { __rsnd_dai_probe(priv, dai_np, dai_i); if (rsnd_is_gen3(priv)) { - struct rsnd_dai *rdai = rsnd_rdai_get(priv, dai_i); + rdai = rsnd_rdai_get(priv, dai_i); rsnd_parse_connect_simple(priv, &rdai->playback, dai_np); rsnd_parse_connect_simple(priv, &rdai->capture, dai_np); @@ -1416,11 +1412,11 @@ static int rsnd_hw_params(struct snd_soc_component *component, struct rsnd_priv *priv = rsnd_io_to_priv(io); struct device *dev = rsnd_priv_to_dev(priv); struct snd_soc_dpcm *dpcm; - struct snd_pcm_hw_params *be_params; int stream = substream->stream; for_each_dpcm_be(fe, stream, dpcm) { - be_params = &dpcm->hw_params; + struct snd_pcm_hw_params *be_params = &dpcm->hw_params; + if (params_channels(hw_params) != params_channels(be_params)) io->converted_chan = params_channels(be_params); if (params_rate(hw_params) != params_rate(be_params)) From 31dbf7acc6a3abf84c2cb3c2312283ed8691de5b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Feb 2021 09:25:19 +0900 Subject: [PATCH 0105/1091] ASoC: rsnd: cleanup ppcheck warning for cmd.c This patch cleanups below ppcheck warning. sound/soc/sh/rcar/cmd.c:46:20: style: The scope of the variable 'src' can be reduced. [variableScope] struct rsnd_mod *src; ^ sound/soc/sh/rcar/cmd.c:47:27: style: The scope of the variable 'tio' can be reduced. [variableScope] struct rsnd_dai_stream *tio; ^ sound/soc/sh/rcar/cmd.c:145:13: style: The scope of the variable 'ret' can be reduced. [variableScope] int i, nr, ret; ^ Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h7m1ro28.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/cmd.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/sound/soc/sh/rcar/cmd.c b/sound/soc/sh/rcar/cmd.c index e6bb6a9a0684..9fdb37c2cbc2 100644 --- a/sound/soc/sh/rcar/cmd.c +++ b/sound/soc/sh/rcar/cmd.c @@ -43,8 +43,6 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, if (mix) { struct rsnd_dai *rdai; - struct rsnd_mod *src; - struct rsnd_dai_stream *tio; int i; /* @@ -54,8 +52,9 @@ static int rsnd_cmd_init(struct rsnd_mod *mod, */ data = 0; for_each_rsnd_dai(rdai, priv, i) { - tio = &rdai->playback; - src = rsnd_io_to_mod_src(tio); + struct rsnd_dai_stream *tio = &rdai->playback; + struct rsnd_mod *src = rsnd_io_to_mod_src(tio); + if (mix == rsnd_io_to_mod_mix(tio)) data |= path[rsnd_mod_id(src)]; @@ -142,7 +141,7 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) { struct device *dev = rsnd_priv_to_dev(priv); struct rsnd_cmd *cmd; - int i, nr, ret; + int i, nr; /* This driver doesn't support Gen1 at this point */ if (rsnd_is_gen1(priv)) @@ -161,9 +160,9 @@ int rsnd_cmd_probe(struct rsnd_priv *priv) priv->cmd = cmd; for_each_rsnd_cmd(cmd, priv, i) { - ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), - &rsnd_cmd_ops, NULL, - RSND_MOD_CMD, i); + int ret = rsnd_mod_init(priv, rsnd_mod_get(cmd), + &rsnd_cmd_ops, NULL, + RSND_MOD_CMD, i); if (ret) return ret; } From b6e499bcb32f07364cf62e7022032f1c0632f76c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 25 Feb 2021 09:25:23 +0900 Subject: [PATCH 0106/1091] ASoC: rsnd: cleanup ppcheck warning for adg.c This patch cleanups below ppcheck warning. sound/soc/sh/rcar/adg.c:67:9: style: The scope of the variable 'ratio' can be reduced. [variableScope] int i, ratio; ^ sound/soc/sh/rcar/adg.c:114:6: style: The scope of the variable 'idx' can be reduced. [variableScope] int idx, sel, div, step; ^ sound/soc/sh/rcar/adg.c:114:21: style: The scope of the variable 'step' can be reduced. [variableScope] int idx, sel, div, step; ^ sound/soc/sh/rcar/adg.c:397:14: style: The scope of the variable 'clk' can be reduced. [variableScope] struct clk *clk; ^ Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ft1lro24.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/adg.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/sound/soc/sh/rcar/adg.c b/sound/soc/sh/rcar/adg.c index abdfd9cf91e2..0b8ae3eee148 100644 --- a/sound/soc/sh/rcar/adg.c +++ b/sound/soc/sh/rcar/adg.c @@ -64,13 +64,13 @@ static const char * const clk_name[] = { static u32 rsnd_adg_calculate_rbgx(unsigned long div) { - int i, ratio; + int i; if (!div) return 0; for (i = 3; i >= 0; i--) { - ratio = 2 << (i * 2); + int ratio = 2 << (i * 2); if (0 == (div % ratio)) return (u32)((i << 8) | ((div / ratio) - 1)); } @@ -111,7 +111,7 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, { struct rsnd_adg *adg = rsnd_priv_to_adg(priv); struct device *dev = rsnd_priv_to_dev(priv); - int idx, sel, div, step; + int sel; unsigned int val, en; unsigned int min, diff; unsigned int sel_rate[] = { @@ -126,8 +126,9 @@ static void __rsnd_adg_get_timesel_ratio(struct rsnd_priv *priv, val = 0; en = 0; for (sel = 0; sel < ARRAY_SIZE(sel_rate); sel++) { - idx = 0; - step = 2; + int idx = 0; + int step = 2; + int div; if (!sel_rate[sel]) continue; @@ -394,11 +395,11 @@ static void rsnd_adg_get_clkin(struct rsnd_priv *priv, struct rsnd_adg *adg) { struct device *dev = rsnd_priv_to_dev(priv); - struct clk *clk; int i; for (i = 0; i < CLKMAX; i++) { - clk = devm_clk_get(dev, clk_name[i]); + struct clk *clk = devm_clk_get(dev, clk_name[i]); + adg->clk[i] = IS_ERR(clk) ? NULL : clk; } } From 933f98be60a7b9c287acb081fb5d6659dd5e0441 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 21 Feb 2021 16:30:24 +0100 Subject: [PATCH 0107/1091] ASoC: constify of_phandle_args in snd_soc_get_dai_name() The pointer to of_phandle_args passed to snd_soc_get_dai_name() and of_xlate_dai_name() implementations is not modified. Since it is being used only to translate passed OF node to a DAI name, it should not be modified, so mark it as const for correctness and safer code. Signed-off-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210221153024.453583-1-krzk@kernel.org Signed-off-by: Mark Brown --- include/sound/soc-component.h | 4 ++-- include/sound/soc.h | 2 +- sound/soc/meson/aiu-acodec-ctrl.c | 2 +- sound/soc/meson/aiu-codec-ctrl.c | 2 +- sound/soc/meson/aiu.c | 4 ++-- sound/soc/meson/aiu.h | 2 +- sound/soc/qcom/lpass-cpu.c | 2 +- sound/soc/qcom/qdsp6/q6afe-dai.c | 2 +- sound/soc/soc-component.c | 2 +- sound/soc/soc-core.c | 2 +- 10 files changed, 12 insertions(+), 12 deletions(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 5b47768222b7..7dc75b39287f 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -101,7 +101,7 @@ struct snd_soc_component_driver { /* DT */ int (*of_xlate_dai_name)(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name); int (*of_xlate_dai_id)(struct snd_soc_component *comment, struct device_node *endpoint); @@ -450,7 +450,7 @@ void snd_soc_component_remove(struct snd_soc_component *component); int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, struct device_node *ep); int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name); int snd_soc_component_compr_open(struct snd_compr_stream *cstream); void snd_soc_component_compr_free(struct snd_compr_stream *cstream, diff --git a/include/sound/soc.h b/include/sound/soc.h index bd38015d6c6d..78609ab331c8 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1219,7 +1219,7 @@ unsigned int snd_soc_of_parse_daifmt(struct device_node *np, struct device_node **bitclkmaster, struct device_node **framemaster); int snd_soc_get_dai_id(struct device_node *ep); -int snd_soc_get_dai_name(struct of_phandle_args *args, +int snd_soc_get_dai_name(const struct of_phandle_args *args, const char **dai_name); int snd_soc_of_get_dai_name(struct device_node *of_node, const char **dai_name); diff --git a/sound/soc/meson/aiu-acodec-ctrl.c b/sound/soc/meson/aiu-acodec-ctrl.c index 7078197e0cc5..27a6d3259c50 100644 --- a/sound/soc/meson/aiu-acodec-ctrl.c +++ b/sound/soc/meson/aiu-acodec-ctrl.c @@ -159,7 +159,7 @@ static const struct snd_kcontrol_new aiu_acodec_ctrl_controls[] = { }; static int aiu_acodec_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name) { return aiu_of_xlate_dai_name(component, args, dai_name, AIU_ACODEC); diff --git a/sound/soc/meson/aiu-codec-ctrl.c b/sound/soc/meson/aiu-codec-ctrl.c index 4b773d3e8b07..c3ea733fce91 100644 --- a/sound/soc/meson/aiu-codec-ctrl.c +++ b/sound/soc/meson/aiu-codec-ctrl.c @@ -125,7 +125,7 @@ static const struct snd_soc_dapm_route aiu_hdmi_ctrl_routes[] = { }; static int aiu_hdmi_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name) { return aiu_of_xlate_dai_name(component, args, dai_name, AIU_HDMI); diff --git a/sound/soc/meson/aiu.c b/sound/soc/meson/aiu.c index dc35ca79021c..ba15d5762b0b 100644 --- a/sound/soc/meson/aiu.c +++ b/sound/soc/meson/aiu.c @@ -42,7 +42,7 @@ static const struct snd_soc_dapm_route aiu_cpu_dapm_routes[] = { }; int aiu_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name, unsigned int component_id) { @@ -72,7 +72,7 @@ int aiu_of_xlate_dai_name(struct snd_soc_component *component, } static int aiu_cpu_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name) { return aiu_of_xlate_dai_name(component, args, dai_name, AIU_CPU); diff --git a/sound/soc/meson/aiu.h b/sound/soc/meson/aiu.h index 87aa19ac4af3..393b6c2307e4 100644 --- a/sound/soc/meson/aiu.h +++ b/sound/soc/meson/aiu.h @@ -45,7 +45,7 @@ struct aiu { SNDRV_PCM_FMTBIT_S24_LE) int aiu_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name, unsigned int component_id); diff --git a/sound/soc/qcom/lpass-cpu.c b/sound/soc/qcom/lpass-cpu.c index c642e5f8f28c..4762286b33fe 100644 --- a/sound/soc/qcom/lpass-cpu.c +++ b/sound/soc/qcom/lpass-cpu.c @@ -340,7 +340,7 @@ int asoc_qcom_lpass_cpu_dai_probe(struct snd_soc_dai *dai) EXPORT_SYMBOL_GPL(asoc_qcom_lpass_cpu_dai_probe); static int asoc_qcom_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name) { struct lpass_data *drvdata = snd_soc_component_get_drvdata(component); diff --git a/sound/soc/qcom/qdsp6/q6afe-dai.c b/sound/soc/qcom/qdsp6/q6afe-dai.c index 4e1f101281e7..e8915519f427 100644 --- a/sound/soc/qcom/qdsp6/q6afe-dai.c +++ b/sound/soc/qcom/qdsp6/q6afe-dai.c @@ -1315,7 +1315,7 @@ static struct snd_soc_dai_driver q6afe_dais[] = { }; static int q6afe_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name) { int id = args->args[0]; diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 159bf88b9f8c..8415e9bd2932 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -370,7 +370,7 @@ int snd_soc_component_of_xlate_dai_id(struct snd_soc_component *component, } int snd_soc_component_of_xlate_dai_name(struct snd_soc_component *component, - struct of_phandle_args *args, + const struct of_phandle_args *args, const char **dai_name) { if (component->driver->of_xlate_dai_name) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0cffc9527e28..16ba54eb8164 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2998,7 +2998,7 @@ int snd_soc_get_dai_id(struct device_node *ep) } EXPORT_SYMBOL_GPL(snd_soc_get_dai_id); -int snd_soc_get_dai_name(struct of_phandle_args *args, +int snd_soc_get_dai_name(const struct of_phandle_args *args, const char **dai_name) { struct snd_soc_component *pos; From 13fba3e873b1f21ed3de6596568ef02d31050b6f Mon Sep 17 00:00:00 2001 From: dingsenjie Date: Wed, 24 Feb 2021 16:54:07 +0800 Subject: [PATCH 0108/1091] ASoC: uniphier: Simplify the return expression of uniphier_aio_startup Simplify the return expression in the aio-cpu.c. Signed-off-by: dingsenjie Link: https://lore.kernel.org/r/20210224085407.22120-1-dingsenjie@163.com Signed-off-by: Mark Brown --- sound/soc/uniphier/aio-cpu.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/sound/soc/uniphier/aio-cpu.c b/sound/soc/uniphier/aio-cpu.c index 25c40c28eba4..cf9814130067 100644 --- a/sound/soc/uniphier/aio-cpu.c +++ b/sound/soc/uniphier/aio-cpu.c @@ -256,17 +256,12 @@ static int uniphier_aio_startup(struct snd_pcm_substream *substream, { struct uniphier_aio *aio = uniphier_priv(dai); struct uniphier_aio_sub *sub = &aio->sub[substream->stream]; - int ret; sub->substream = substream; sub->pass_through = 0; sub->use_mmap = true; - ret = aio_init(sub); - if (ret) - return ret; - - return 0; + return aio_init(sub); } static void uniphier_aio_shutdown(struct snd_pcm_substream *substream, From 907e0cdebc1f36623ca8ce6a6376abb1ad56e93d Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 22 Feb 2021 16:40:20 +0800 Subject: [PATCH 0109/1091] ASoC: fsl_sai: Add pm qos cpu latency support On SoCs such as i.MX7ULP, cpuidle has some levels which may disable system/bus clocks, so need to add pm_qos to prevent cpuidle from entering low level idles and make sure system/bus clocks are enabled when sai is active. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1613983220-5373-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 12 ++++++++++++ sound/soc/fsl/fsl_sai.h | 4 ++++ 2 files changed, 16 insertions(+) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 5e65b456d3e2..a22679dea578 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -10,6 +10,7 @@ #include #include #include +#include #include #include #include @@ -1177,6 +1178,7 @@ static const struct fsl_sai_soc_data fsl_sai_vf610_data = { .fifo_depth = 32, .reg_offset = 0, .mclk0_is_mclk1 = false, + .flags = 0, }; static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { @@ -1185,6 +1187,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx6sx_data = { .fifo_depth = 32, .reg_offset = 0, .mclk0_is_mclk1 = true, + .flags = 0, }; static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = { @@ -1193,6 +1196,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx7ulp_data = { .fifo_depth = 16, .reg_offset = 8, .mclk0_is_mclk1 = false, + .flags = PMQOS_CPU_LATENCY, }; static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = { @@ -1201,6 +1205,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx8mq_data = { .fifo_depth = 128, .reg_offset = 8, .mclk0_is_mclk1 = false, + .flags = 0, }; static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = { @@ -1209,6 +1214,7 @@ static const struct fsl_sai_soc_data fsl_sai_imx8qm_data = { .fifo_depth = 64, .reg_offset = 0, .mclk0_is_mclk1 = false, + .flags = 0, }; static const struct of_device_id fsl_sai_ids[] = { @@ -1235,6 +1241,9 @@ static int fsl_sai_runtime_suspend(struct device *dev) clk_disable_unprepare(sai->bus_clk); + if (sai->soc_data->flags & PMQOS_CPU_LATENCY) + cpu_latency_qos_remove_request(&sai->pm_qos_req); + regcache_cache_only(sai->regmap, true); return 0; @@ -1264,6 +1273,9 @@ static int fsl_sai_runtime_resume(struct device *dev) goto disable_tx_clk; } + if (sai->soc_data->flags & PMQOS_CPU_LATENCY) + cpu_latency_qos_add_request(&sai->pm_qos_req, 0); + regcache_cache_only(sai->regmap, false); regcache_mark_dirty(sai->regmap); regmap_write(sai->regmap, FSL_SAI_TCSR(ofs), FSL_SAI_CSR_SR); diff --git a/sound/soc/fsl/fsl_sai.h b/sound/soc/fsl/fsl_sai.h index ff2619f1b214..bc60030967dd 100644 --- a/sound/soc/fsl/fsl_sai.h +++ b/sound/soc/fsl/fsl_sai.h @@ -216,12 +216,15 @@ #define FSL_SAI_MAXBURST_TX 6 #define FSL_SAI_MAXBURST_RX 6 +#define PMQOS_CPU_LATENCY BIT(0) + struct fsl_sai_soc_data { bool use_imx_pcm; bool use_edma; bool mclk0_is_mclk1; unsigned int fifo_depth; unsigned int reg_offset; + unsigned int flags; }; /** @@ -273,6 +276,7 @@ struct fsl_sai { struct snd_dmaengine_dai_dma_data dma_params_tx; struct fsl_sai_verid verid; struct fsl_sai_param param; + struct pm_qos_request pm_qos_req; }; #define TX 1 From ff5687854323533668ec06dd38808bae9a984f68 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Mon, 15 Feb 2021 20:05:01 +0000 Subject: [PATCH 0110/1091] ASoC: codecs: lpass-rx-macro: remove redundant initialization of variable hph_pwr_mode The variable hph_pwr_mode is being initialized with a value that is never read and it is being updated later with a new value. The initialization is redundant and can be removed. Signed-off-by: Colin Ian King Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210215200501.90697-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 8c04b3b2c907..76909c50d7b9 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -2038,7 +2038,7 @@ static int rx_macro_load_compander_coeff(struct snd_soc_component *component, { u16 comp_coeff_lsb_reg, comp_coeff_msb_reg; int i; - int hph_pwr_mode = HPH_LOHIFI; + int hph_pwr_mode; if (!rx->comp_enabled[comp]) return 0; From 1730ef62874dbdc53dc2abfa430f09f0b304bafc Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Fri, 26 Feb 2021 18:56:53 +0000 Subject: [PATCH 0111/1091] ASoC: Intel: boards: sof-wm8804: add check for PLL setting Currently the return from snd_soc_dai_set_pll is not checking for failure, this is the only driver in the kernel that ignores this, so it probably should be added for sake of completeness. Fix this by adding an error return check. Addresses-Coverity: ("Unchecked return value") Fixes: f139546fb7d4 ("ASoC: Intel: boards: sof-wm8804: support for Hifiberry Digiplus boards") Signed-off-by: Colin Ian King Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210226185653.1071321-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_wm8804.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/sof_wm8804.c b/sound/soc/intel/boards/sof_wm8804.c index a46ba13e8eb0..6a181e45143d 100644 --- a/sound/soc/intel/boards/sof_wm8804.c +++ b/sound/soc/intel/boards/sof_wm8804.c @@ -124,7 +124,11 @@ static int sof_wm8804_hw_params(struct snd_pcm_substream *substream, } snd_soc_dai_set_clkdiv(codec_dai, WM8804_MCLK_DIV, mclk_div); - snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); + ret = snd_soc_dai_set_pll(codec_dai, 0, 0, sysclk, mclk_freq); + if (ret < 0) { + dev_err(rtd->card->dev, "Failed to set WM8804 PLL\n"); + return ret; + } ret = snd_soc_dai_set_sysclk(codec_dai, WM8804_TX_CLKSRC_PLL, sysclk, SND_SOC_CLOCK_OUT); From 1372c76802bed271ddcfdd71b6fe3ea9254e6277 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Wed, 24 Feb 2021 16:15:41 +0200 Subject: [PATCH 0112/1091] ASoC: SOF: Intel: hda: turn off display power in resume Turn off display power at the end of controller resume flow. This is now possible with the changes done in commit 87fc20e4a0cb ("ASoC: SOF: Intel: hda: use hdac_ext fine-grained link management"). As codec driver is able to request the HDA link to be brought back up, the controller no longer needs to blindly keep display power enabled. Co-developed-by: Sathyanarayana Nujella Signed-off-by: Sathyanarayana Nujella Signed-off-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Reviewed-by: Keyon Jie Link: https://lore.kernel.org/r/20210224141541.3331254-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index c3b757cf01a0..6e24e1cb13f9 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -678,7 +678,7 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) if (ret < 0) { dev_err(sdev->dev, "error: failed to start controller after resume\n"); - return ret; + goto cleanup; } #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) @@ -704,6 +704,10 @@ static int hda_resume(struct snd_sof_dev *sdev, bool runtime_resume) hda_dsp_ctrl_ppcap_enable(sdev, true); hda_dsp_ctrl_ppcap_int_enable(sdev, true); +cleanup: + /* display codec can powered off after controller init */ + hda_codec_i915_display_power(sdev, false); + return 0; } From 5f160cbe76bfdb097ebf5514a4562e8dc658d5d2 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Mon, 22 Feb 2021 17:09:50 +0800 Subject: [PATCH 0113/1091] ASoC: fsl_xcvr: move reset assert into runtime_resume Move reset assert into runtime_resume since we cannot rely on reset assert state when the device is put out from suspend. Signed-off-by: Viorel Suman Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1613984990-5534-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_xcvr.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 6dd0a5fcd455..c01eb213ea56 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1243,10 +1243,6 @@ static __maybe_unused int fsl_xcvr_runtime_suspend(struct device *dev) if (ret < 0) dev_err(dev, "Failed to assert M0+ core: %d\n", ret); - ret = reset_control_assert(xcvr->reset); - if (ret < 0) - dev_err(dev, "Failed to assert M0+ reset: %d\n", ret); - regcache_cache_only(xcvr->regmap, true); clk_disable_unprepare(xcvr->spba_clk); @@ -1262,6 +1258,12 @@ static __maybe_unused int fsl_xcvr_runtime_resume(struct device *dev) struct fsl_xcvr *xcvr = dev_get_drvdata(dev); int ret; + ret = reset_control_assert(xcvr->reset); + if (ret < 0) { + dev_err(dev, "Failed to assert M0+ reset: %d\n", ret); + return ret; + } + ret = clk_prepare_enable(xcvr->ipg_clk); if (ret) { dev_err(dev, "failed to start IPG clock.\n"); From 1b99d50b9709a2cddaba4a7faf1862b4f7bec865 Mon Sep 17 00:00:00 2001 From: Cezary Rojewski Date: Mon, 25 Jan 2021 12:54:41 +0100 Subject: [PATCH 0114/1091] ASoC: Intel: Skylake: Compile when any configuration is selected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Skylake is dependent on SND_SOC_INTEL_SKYLAKE (aka "all SST platforms") whereas selecting specific configuration such as KBL-only will not cause driver code to compile. Switch to SND_SOC_INTEL_SKYLAKE_COMMON dependency so selecting any configuration causes the driver to be built. Reported-by: Kai-Heng Feng Suggested-by: Amadeusz Sławiński Fixes: 35bc99aaa1a3 ("ASoC: Intel: Skylake: Add more platform granularity") Signed-off-by: Cezary Rojewski Link: https://lore.kernel.org/r/20210125115441.10383-1-cezary.rojewski@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/Makefile | 2 +- sound/soc/intel/skylake/Makefile | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/Makefile b/sound/soc/intel/Makefile index 4e0248d2accc..7c5038803be7 100644 --- a/sound/soc/intel/Makefile +++ b/sound/soc/intel/Makefile @@ -5,7 +5,7 @@ obj-$(CONFIG_SND_SOC) += common/ # Platform Support obj-$(CONFIG_SND_SST_ATOM_HIFI2_PLATFORM) += atom/ obj-$(CONFIG_SND_SOC_INTEL_CATPT) += catpt/ -obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += skylake/ +obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += skylake/ obj-$(CONFIG_SND_SOC_INTEL_KEEMBAY) += keembay/ # Machine support diff --git a/sound/soc/intel/skylake/Makefile b/sound/soc/intel/skylake/Makefile index dd39149b89b1..1c4649bccec5 100644 --- a/sound/soc/intel/skylake/Makefile +++ b/sound/soc/intel/skylake/Makefile @@ -7,7 +7,7 @@ ifdef CONFIG_DEBUG_FS snd-soc-skl-objs += skl-debug.o endif -obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE) += snd-soc-skl.o +obj-$(CONFIG_SND_SOC_INTEL_SKYLAKE_COMMON) += snd-soc-skl.o #Skylake Clock device support snd-soc-skl-ssp-clk-objs := skl-ssp-clk.o From 2b719fd20f327f81270b0ab99159f61da3bbac34 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 23 Feb 2021 17:07:59 +0800 Subject: [PATCH 0115/1091] ASoC: rt1316: Add RT1316 SDCA vendor-specific driver This is the initial amplifier driver for rt1316 SDCA version. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210223090759.15323-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 6 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt1316-sdw.c | 744 ++++++++++++++++++++++++++++++++++ sound/soc/codecs/rt1316-sdw.h | 55 +++ 4 files changed, 807 insertions(+) create mode 100644 sound/soc/codecs/rt1316-sdw.c create mode 100644 sound/soc/codecs/rt1316-sdw.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 1c87b42606c9..0eb9f06660e7 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -182,6 +182,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT711_SDW imply SND_SOC_RT715_SDW imply SND_SOC_RT1308_SDW + imply SND_SOC_RT1316_SDW imply SND_SOC_SGTL5000 imply SND_SOC_SI476X imply SND_SOC_SIMPLE_AMPLIFIER @@ -1143,6 +1144,11 @@ config SND_SOC_RT1308_SDW depends on I2C && SOUNDWIRE select REGMAP_SOUNDWIRE +config SND_SOC_RT1316_SDW + tristate "Realtek RT1316 Codec - SDW" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + config SND_SOC_RT5514 tristate depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 81357dc62ea0..1585bc1d9a25 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -173,6 +173,7 @@ snd-soc-rt1015p-objs := rt1015p.o snd-soc-rt1305-objs := rt1305.o snd-soc-rt1308-objs := rt1308.o snd-soc-rt1308-sdw-objs := rt1308-sdw.o +snd-soc-rt1316-sdw-objs := rt1316-sdw.o snd-soc-rt274-objs := rt274.o snd-soc-rt286-objs := rt286.o snd-soc-rt298-objs := rt298.o @@ -487,6 +488,7 @@ obj-$(CONFIG_SND_SOC_RT1015P) += snd-soc-rt1015p.o obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o obj-$(CONFIG_SND_SOC_RT1308) += snd-soc-rt1308.o obj-$(CONFIG_SND_SOC_RT1308_SDW) += snd-soc-rt1308-sdw.o +obj-$(CONFIG_SND_SOC_RT1316_SDW) += snd-soc-rt1316-sdw.o obj-$(CONFIG_SND_SOC_RT274) += snd-soc-rt274.o obj-$(CONFIG_SND_SOC_RT286) += snd-soc-rt286.o obj-$(CONFIG_SND_SOC_RT298) += snd-soc-rt298.o diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c new file mode 100644 index 000000000000..a6fb34a48f33 --- /dev/null +++ b/sound/soc/codecs/rt1316-sdw.c @@ -0,0 +1,744 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt1316-sdw.c -- rt1316 SDCA ALSA SoC amplifier audio driver +// +// Copyright(c) 2021 Realtek Semiconductor Corp. +// +// +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rt1316-sdw.h" + +static const struct reg_default rt1316_reg_defaults[] = { + { 0x3004, 0x00 }, + { 0x3005, 0x00 }, + { 0x3206, 0x00 }, + { 0xc001, 0x00 }, + { 0xc002, 0x00 }, + { 0xc003, 0x00 }, + { 0xc004, 0x00 }, + { 0xc005, 0x00 }, + { 0xc006, 0x00 }, + { 0xc007, 0x00 }, + { 0xc008, 0x00 }, + { 0xc009, 0x00 }, + { 0xc00a, 0x00 }, + { 0xc00b, 0x00 }, + { 0xc00c, 0x00 }, + { 0xc00d, 0x00 }, + { 0xc00e, 0x00 }, + { 0xc00f, 0x00 }, + { 0xc010, 0xa5 }, + { 0xc011, 0x00 }, + { 0xc012, 0xff }, + { 0xc013, 0xff }, + { 0xc014, 0x40 }, + { 0xc015, 0x00 }, + { 0xc016, 0x00 }, + { 0xc017, 0x00 }, + { 0xc605, 0x30 }, + { 0xc700, 0x0a }, + { 0xc701, 0xaa }, + { 0xc702, 0x1a }, + { 0xc703, 0x0a }, + { 0xc710, 0x80 }, + { 0xc711, 0x00 }, + { 0xc712, 0x3e }, + { 0xc713, 0x80 }, + { 0xc714, 0x80 }, + { 0xc715, 0x06 }, + { 0xd101, 0x00 }, + { 0xd102, 0x30 }, + { 0xd103, 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_UDMPU21, RT1316_SDCA_CTL_UDMPU_CLUSTER, 0), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_FU21, RT1316_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_FU21, RT1316_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_XU24, RT1316_SDCA_CTL_BYPASS, 0), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE23, RT1316_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE22, RT1316_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE24, RT1316_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, +}; + +static const struct reg_sequence rt1316_blind_write[] = { + { 0xc710, 0x17 }, + { 0xc711, 0x80 }, + { 0xc712, 0x26 }, + { 0xc713, 0x06 }, + { 0xc714, 0x80 }, + { 0xc715, 0x06 }, + { 0xc702, 0x0a }, + { 0xc703, 0x0a }, + { 0xc001, 0x45 }, + { 0xc003, 0x00 }, + { 0xc004, 0x11 }, + { 0xc005, 0x00 }, + { 0xc006, 0x00 }, + { 0xc106, 0x00 }, + { 0xc007, 0x11 }, + { 0xc008, 0x11 }, + { 0xc009, 0x00 }, + + { 0x2f0a, 0x00 }, + { 0xd101, 0xf0 }, + { 0xd103, 0x9b }, + { 0x2f36, 0x8e }, + { 0x3206, 0x80 }, + { 0x3211, 0x0b }, + { 0x3216, 0x06 }, + { 0xc614, 0x20 }, + { 0xc615, 0x0a }, + { 0xc616, 0x02 }, + { 0xc617, 0x00 }, + { 0xc60b, 0x10 }, + { 0xc60e, 0x05 }, + { 0xc102, 0x00 }, + { 0xc090, 0xb0 }, + { 0xc00f, 0x01 }, + { 0xc09c, 0x7b }, + + { 0xc602, 0x07 }, + { 0xc603, 0x07 }, + { 0xc0a3, 0x71 }, + { 0xc00b, 0x30 }, + { 0xc093, 0x80 }, + { 0xc09d, 0x80 }, + { 0xc0b0, 0x77 }, + { 0xc010, 0xa5 }, + { 0xc050, 0x83 }, + { 0x2f55, 0x03 }, + { 0x3217, 0xb5 }, + { 0x3202, 0x02 }, + + { SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_XU24, RT1316_SDCA_CTL_BYPASS, 0), 0x00 }, + + /* for IV sense */ + { 0x2232, 0x80 }, + { 0xc0b0, 0x77 }, + { 0xc011, 0x00 }, + { 0xc020, 0x00 }, + { 0xc023, 0x00 }, + { 0x3101, 0x00 }, + { 0x3004, 0xa0 }, + { 0x3005, 0xb1 }, + { 0xc007, 0x11 }, + { 0xc008, 0x11 }, + { 0xc009, 0x00 }, + { 0xc022, 0xd6 }, + { 0xc025, 0xd6 }, + + { 0xd001, 0x03 }, + { 0xd002, 0xbf }, + { 0xd003, 0x03 }, + { 0xd004, 0xbf }, +}; + +static bool rt1316_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2f0a: + case 0x2f36: + case 0x3203 ... 0x320e: + case 0xc000 ... 0xc7b4: + case 0xcf00 ... 0xcf03: + case 0xd101 ... 0xd103: + case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_UDMPU21, RT1316_SDCA_CTL_UDMPU_CLUSTER, 0): + case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_FU21, RT1316_SDCA_CTL_FU_MUTE, CH_L): + case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_FU21, RT1316_SDCA_CTL_FU_MUTE, CH_R): + case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE23, RT1316_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE27, RT1316_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE22, RT1316_SDCA_CTL_REQ_POWER_STATE, 0): + case SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE24, RT1316_SDCA_CTL_REQ_POWER_STATE, 0): + return true; + default: + return false; + } +} + +static bool rt1316_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0xc000: + case 0xc093: + case 0xc09d: + case 0xc0a3: + case 0xc201: + case 0xc427 ... 0xc428: + case 0xd102: + return true; + default: + return false; + } +} + +static const struct regmap_config rt1316_sdw_regmap = { + .reg_bits = 32, + .val_bits = 8, + .readable_reg = rt1316_readable_register, + .volatile_reg = rt1316_volatile_register, + .max_register = 0x4108ffff, + .reg_defaults = rt1316_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rt1316_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static int rt1316_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval; + int i, j; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + prop->is_sdca = true; + + prop->paging_support = true; + + /* first we need to allocate memory for set bits in port lists */ + prop->source_ports = 0x04; /* BITMAP: 00000100 */ + prop->sink_ports = 0x2; /* BITMAP: 00000010 */ + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + j = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[j].num = bit; + dpn[j].type = SDW_DPN_FULL; + dpn[j].simple_ch_prep_sm = true; + dpn[j].ch_prep_timeout = 10; + j++; + } + + /* set the timeout values */ + prop->clk_stop_timeout = 20; + + dev_dbg(&slave->dev, "%s\n", __func__); + + return 0; +} + +static int rt1316_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev); + + if (rt1316->hw_init) + return 0; + + if (rt1316->first_hw_init) { + regcache_cache_only(rt1316->regmap, false); + regcache_cache_bypass(rt1316->regmap, true); + } else { + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + } + + pm_runtime_get_noresume(&slave->dev); + + /* sw reset */ + regmap_write(rt1316->regmap, 0xc000, 0x02); + + /* initial settings - blind write */ + regmap_multi_reg_write(rt1316->regmap, rt1316_blind_write, + ARRAY_SIZE(rt1316_blind_write)); + + if (rt1316->first_hw_init) { + regcache_cache_bypass(rt1316->regmap, false); + regcache_mark_dirty(rt1316->regmap); + } else + rt1316->first_hw_init = true; + + /* Mark Slave initialization complete */ + rt1316->hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + return 0; +} + +static int rt1316_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(&slave->dev); + + /* Update the status */ + rt1316->status = status; + + if (status == SDW_SLAVE_UNATTACHED) + rt1316->hw_init = false; + + /* + * Perform initialization only if slave status is present and + * hw_init flag is false + */ + if (rt1316->hw_init || rt1316->status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return rt1316_io_init(&slave->dev, slave); +} + +static int rt1316_classd_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt1316_sdw_priv *rt1316 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE23, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE27, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE22, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE23, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE27, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE22, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + + default: + break; + } + + return 0; +} + +static int rt1316_pde24_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt1316_sdw_priv *rt1316 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE24, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt1316->regmap, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_PDE24, + RT1316_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + } + return 0; +} + +static const char * const rt1316_rx_data_ch_select[] = { + "L,R", + "L,L", + "L,R", + "L,L+R", + "R,L", + "R,R", + "R,L+R", + "L+R,L", + "L+R,R", + "L+R,L+R", +}; + +static SOC_ENUM_SINGLE_DECL(rt1316_rx_data_ch_enum, + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_UDMPU21, RT1316_SDCA_CTL_UDMPU_CLUSTER, 0), 0, + rt1316_rx_data_ch_select); + +static const struct snd_kcontrol_new rt1316_snd_controls[] = { + + /* I2S Data Channel Selection */ + SOC_ENUM("RX Channel Select", rt1316_rx_data_ch_enum), + + /* XU24 Bypass Control */ + SOC_SINGLE("XU24 Bypass Switch", + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_XU24, RT1316_SDCA_CTL_BYPASS, 0), 0, 1, 0), + + /* Left/Right IV tag */ + SOC_SINGLE("Left V Tag Select", 0x3004, 0, 7, 0), + SOC_SINGLE("Left I Tag Select", 0x3004, 4, 7, 0), + SOC_SINGLE("Right V Tag Select", 0x3005, 0, 7, 0), + SOC_SINGLE("Right I Tag Select", 0x3005, 4, 7, 0), + + /* IV mixer Control */ + SOC_DOUBLE("Isense Mixer Switch", 0xc605, 2, 0, 1, 1), + SOC_DOUBLE("Vsense Mixer Switch", 0xc605, 3, 1, 1, 1), +}; + +static const struct snd_kcontrol_new rt1316_sto_dac = + SOC_DAPM_DOUBLE_R("Switch", + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_FU21, RT1316_SDCA_CTL_FU_MUTE, CH_L), + SDW_SDCA_CTL(FUNC_NUM_SMART_AMP, RT1316_SDCA_ENT_FU21, RT1316_SDCA_CTL_FU_MUTE, CH_R), + 0, 1, 1); + +static const struct snd_soc_dapm_widget rt1316_dapm_widgets[] = { + /* Audio Interface */ + SND_SOC_DAPM_AIF_IN("DP1RX", "DP1 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0), + + /* Digital Interface */ + SND_SOC_DAPM_SWITCH("DAC", SND_SOC_NOPM, 0, 0, &rt1316_sto_dac), + + /* Output Lines */ + SND_SOC_DAPM_PGA_E("CLASS D", SND_SOC_NOPM, 0, 0, NULL, 0, + rt1316_classd_event, + SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU), + SND_SOC_DAPM_OUTPUT("SPOL"), + SND_SOC_DAPM_OUTPUT("SPOR"), + + SND_SOC_DAPM_SUPPLY("PDE 24", SND_SOC_NOPM, 0, 0, + rt1316_pde24_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PGA("I Sense", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA("V Sense", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_SIGGEN("I Gen"), + SND_SOC_DAPM_SIGGEN("V Gen"), +}; + +static const struct snd_soc_dapm_route rt1316_dapm_routes[] = { + { "DAC", "Switch", "DP1RX" }, + { "CLASS D", NULL, "DAC" }, + { "SPOL", NULL, "CLASS D" }, + { "SPOR", NULL, "CLASS D" }, + + { "I Sense", NULL, "I Gen" }, + { "V Sense", NULL, "V Gen" }, + { "I Sense", NULL, "PDE 24" }, + { "V Sense", NULL, "PDE 24" }, + { "DP2TX", NULL, "I Sense" }, + { "DP2TX", NULL, "V Sense" }, +}; + +static int rt1316_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + struct sdw_stream_data *stream; + + if (!sdw_stream) + return 0; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void rt1316_sdw_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int rt1316_sdw_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt1316_sdw_priv *rt1316 = + snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_data *stream; + int retval, port, num_channels, ch_mask; + + dev_dbg(dai->dev, "%s %s", __func__, dai->name); + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -EINVAL; + + if (!rt1316->sdw_slave) + return -EINVAL; + + /* SoundWire specific configuration */ + /* port 1 for playback */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + port = 1; + } else { + direction = SDW_DATA_DIR_TX; + port = 2; + } + + num_channels = params_channels(params); + ch_mask = (1 << num_channels) - 1; + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = num_channels; + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + port_config.ch_mask = ch_mask; + port_config.num = port; + + retval = sdw_stream_add_slave(rt1316->sdw_slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (retval) { + dev_err(dai->dev, "Unable to configure port\n"); + return retval; + } + + return 0; +} + +static int rt1316_sdw_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt1316_sdw_priv *rt1316 = + snd_soc_component_get_drvdata(component); + struct sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt1316->sdw_slave) + return -EINVAL; + + sdw_stream_remove_slave(rt1316->sdw_slave, stream->sdw_stream); + return 0; +} + +/* + * slave_ops: callbacks for get_clock_stop_mode, clock_stop and + * port_prep are not defined for now + */ +static struct sdw_slave_ops rt1316_slave_ops = { + .read_prop = rt1316_read_prop, + .update_status = rt1316_update_status, +}; + +static const struct snd_soc_component_driver soc_component_sdw_rt1316 = { + .controls = rt1316_snd_controls, + .num_controls = ARRAY_SIZE(rt1316_snd_controls), + .dapm_widgets = rt1316_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt1316_dapm_widgets), + .dapm_routes = rt1316_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt1316_dapm_routes), +}; + +static const struct snd_soc_dai_ops rt1316_aif_dai_ops = { + .hw_params = rt1316_sdw_hw_params, + .hw_free = rt1316_sdw_pcm_hw_free, + .set_sdw_stream = rt1316_set_sdw_stream, + .shutdown = rt1316_sdw_shutdown, +}; + +#define RT1316_STEREO_RATES SNDRV_PCM_RATE_48000 +#define RT1316_FORMATS (SNDRV_PCM_FMTBIT_S20_3LE | SNDRV_PCM_FMTBIT_S16_LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +static struct snd_soc_dai_driver rt1316_sdw_dai[] = { + { + .name = "rt1316-aif", + .playback = { + .stream_name = "DP1 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT1316_STEREO_RATES, + .formats = RT1316_FORMATS, + }, + .capture = { + .stream_name = "DP2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT1316_STEREO_RATES, + .formats = RT1316_FORMATS, + }, + .ops = &rt1316_aif_dai_ops, + }, +}; + +static int rt1316_sdw_init(struct device *dev, struct regmap *regmap, + struct sdw_slave *slave) +{ + struct rt1316_sdw_priv *rt1316; + int ret; + + rt1316 = devm_kzalloc(dev, sizeof(*rt1316), GFP_KERNEL); + if (!rt1316) + return -ENOMEM; + + dev_set_drvdata(dev, rt1316); + rt1316->sdw_slave = slave; + rt1316->regmap = regmap; + + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt1316->hw_init = false; + rt1316->first_hw_init = false; + + ret = devm_snd_soc_register_component(dev, + &soc_component_sdw_rt1316, + rt1316_sdw_dai, + ARRAY_SIZE(rt1316_sdw_dai)); + + dev_dbg(&slave->dev, "%s\n", __func__); + + return ret; +} + +static int rt1316_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap; + + /* Regmap Initialization */ + regmap = devm_regmap_init_sdw(slave, &rt1316_sdw_regmap); + if (!regmap) + return -EINVAL; + + return rt1316_sdw_init(&slave->dev, regmap, slave); +} + +static const struct sdw_device_id rt1316_id[] = { + SDW_SLAVE_ENTRY_EXT(0x025d, 0x1316, 0x3, 0x1, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, rt1316_id); + +static int __maybe_unused rt1316_dev_suspend(struct device *dev) +{ + struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev); + + if (!rt1316->hw_init) + return 0; + + regcache_cache_only(rt1316->regmap, true); + + return 0; +} + +#define RT1316_PROBE_TIMEOUT 5000 + +static int __maybe_unused rt1316_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt1316_sdw_priv *rt1316 = dev_get_drvdata(dev); + unsigned long time; + + if (!rt1316->hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(RT1316_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(rt1316->regmap, false); + regcache_sync(rt1316->regmap); + + return 0; +} + +static const struct dev_pm_ops rt1316_pm = { + SET_SYSTEM_SLEEP_PM_OPS(rt1316_dev_suspend, rt1316_dev_resume) + SET_RUNTIME_PM_OPS(rt1316_dev_suspend, rt1316_dev_resume, NULL) +}; + +static struct sdw_driver rt1316_sdw_driver = { + .driver = { + .name = "rt1316-sdca", + .owner = THIS_MODULE, + .pm = &rt1316_pm, + }, + .probe = rt1316_sdw_probe, + .ops = &rt1316_slave_ops, + .id_table = rt1316_id, +}; +module_sdw_driver(rt1316_sdw_driver); + +MODULE_DESCRIPTION("ASoC RT1316 driver SDCA SDW"); +MODULE_AUTHOR("Shuming Fan "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt1316-sdw.h b/sound/soc/codecs/rt1316-sdw.h new file mode 100644 index 000000000000..cbcdaa8f8cfa --- /dev/null +++ b/sound/soc/codecs/rt1316-sdw.h @@ -0,0 +1,55 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt1316-sdw.h -- RT1316 SDCA ALSA SoC audio driver header + * + * Copyright(c) 2021 Realtek Semiconductor Corp. + */ + +#ifndef __RT1316_SDW_H__ +#define __RT1316_SDW_H__ + +#include +#include +#include +#include +#include + +/* RT1316 SDCA Control - function number */ +#define FUNC_NUM_SMART_AMP 0x04 + +/* RT1316 SDCA entity */ +#define RT1316_SDCA_ENT_PDE23 0x31 +#define RT1316_SDCA_ENT_PDE27 0x32 +#define RT1316_SDCA_ENT_PDE22 0x33 +#define RT1316_SDCA_ENT_PDE24 0x34 +#define RT1316_SDCA_ENT_XU24 0x24 +#define RT1316_SDCA_ENT_FU21 0x03 +#define RT1316_SDCA_ENT_UDMPU21 0x02 + +/* RT1316 SDCA control */ +#define RT1316_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10 +#define RT1316_SDCA_CTL_REQ_POWER_STATE 0x01 +#define RT1316_SDCA_CTL_BYPASS 0x01 +#define RT1316_SDCA_CTL_FU_MUTE 0x01 +#define RT1316_SDCA_CTL_FU_VOLUME 0x02 +#define RT1316_SDCA_CTL_UDMPU_CLUSTER 0x10 + +/* RT1316 SDCA channel */ +#define CH_L 0x01 +#define CH_R 0x02 + +struct rt1316_sdw_priv { + struct snd_soc_component *component; + struct regmap *regmap; + struct sdw_slave *sdw_slave; + enum sdw_slave_status status; + struct sdw_bus_params params; + bool hw_init; + bool first_hw_init; +}; + +struct sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +#endif /* __RT1316_SDW_H__ */ From 99ac2f8d1508f31ecf28d5af0ce384bf0a033f90 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Mon, 1 Mar 2021 19:09:00 +0200 Subject: [PATCH 0116/1091] ASoC: mchp-i2s-mcc: Add compatible for SAMA7G5 Microchip's new SAMA7G5 includes an updated I2S-MCC compatible with the previous version found on SAM9X60. The new controller includes 8 (4 * 2) input and output data pins for up to 8 channels for I2S and Left-Justified formats. Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210301170905.835091-3-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/Kconfig | 3 +++ sound/soc/atmel/mchp-i2s-mcc.c | 3 +++ 2 files changed, 6 insertions(+) diff --git a/sound/soc/atmel/Kconfig b/sound/soc/atmel/Kconfig index 9fe9471f4514..ec04e3386bc0 100644 --- a/sound/soc/atmel/Kconfig +++ b/sound/soc/atmel/Kconfig @@ -127,10 +127,13 @@ config SND_MCHP_SOC_I2S_MCC Say Y or M if you want to add support for I2S Multi-Channel ASoC driver on the following Microchip platforms: - sam9x60 + - sama7g5 The I2SMCC complies with the Inter-IC Sound (I2S) bus specification and supports a Time Division Multiplexed (TDM) interface with external multi-channel audio codecs. + Starting with sama7g5, I2S and Left-Justified multi-channel is + supported by using multiple data pins, output and input, without TDM. config SND_MCHP_SOC_SPDIFTX tristate "Microchip ASoC driver for boards using S/PDIF TX" diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 6d5ae18f8b38..0ee01383e307 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -873,6 +873,9 @@ static const struct of_device_id mchp_i2s_mcc_dt_ids[] = { { .compatible = "microchip,sam9x60-i2smcc", }, + { + .compatible = "microchip,sama7g5-i2smcc", + }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids); From 13c1629d758aae97f329d25714e26edde4e5cf3e Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Mon, 1 Mar 2021 19:09:01 +0200 Subject: [PATCH 0117/1091] ASoC: mchp-i2s-mcc: Add multi-channel support for I2S and LEFT_J formats The latest I2S-MCC available in SAMA7G5 supports multi-channel for I2S and Left-Justified formats. For this, the new version uses 8 (4 * 2) input and output pins, with each pin being responsible for 2 channels. This sums up to a total of 8 channels for synchronous capture and playback. Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210301170905.835091-4-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-i2s-mcc.c | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 0ee01383e307..52d3f43148dc 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include @@ -225,6 +226,10 @@ static const struct regmap_config mchp_i2s_mcc_regmap_config = { .max_register = MCHP_I2SMCC_VERSION, }; +struct mchp_i2s_mcc_soc_data { + unsigned int data_pin_pair_num; +}; + struct mchp_i2s_mcc_dev { struct wait_queue_head wq_txrdy; struct wait_queue_head wq_rxrdy; @@ -232,6 +237,7 @@ struct mchp_i2s_mcc_dev { struct regmap *regmap; struct clk *pclk; struct clk *gclk; + const struct mchp_i2s_mcc_soc_data *soc; struct snd_dmaengine_dai_dma_data playback; struct snd_dmaengine_dai_dma_data capture; unsigned int fmt; @@ -549,6 +555,17 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, } if (dev->fmt & (SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_LEFT_J)) { + /* for I2S and LEFT_J one pin is needed for every 2 channels */ + if (channels > dev->soc->data_pin_pair_num * 2) { + dev_err(dev->dev, + "unsupported number of audio channels: %d\n", + channels); + return -EINVAL; + } + + /* enable for interleaved format */ + mrb |= MCHP_I2SMCC_MRB_CRAMODE_REGULAR; + switch (channels) { case 1: if (is_playback) @@ -558,6 +575,12 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, break; case 2: break; + case 4: + mra |= MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1; + break; + case 8: + mra |= MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2; + break; default: dev_err(dev->dev, "unsupported number of audio channels\n"); return -EINVAL; @@ -869,12 +892,22 @@ static const struct snd_soc_component_driver mchp_i2s_mcc_component = { }; #ifdef CONFIG_OF +static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sam9x60 = { + .data_pin_pair_num = 1, +}; + +static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sama7g5 = { + .data_pin_pair_num = 4, +}; + static const struct of_device_id mchp_i2s_mcc_dt_ids[] = { { .compatible = "microchip,sam9x60-i2smcc", + .data = &mchp_i2s_mcc_sam9x60, }, { .compatible = "microchip,sama7g5-i2smcc", + .data = &mchp_i2s_mcc_sama7g5, }, { /* sentinel */ } }; @@ -932,6 +965,11 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev) dev->gclk = NULL; } + dev->soc = of_device_get_match_data(&pdev->dev); + if (!dev->soc) { + dev_err(&pdev->dev, "failed to get soc data\n"); + return -ENODEV; + } dev->dev = &pdev->dev; dev->regmap = regmap; platform_set_drvdata(pdev, dev); From bfdca489751ff765ee606c85bda1680040dedd8e Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Mon, 1 Mar 2021 19:09:03 +0200 Subject: [PATCH 0118/1091] ASoC: mchp-i2s-mcc: Add support to select TDM pins SAMA7G5's I2S-MCC has 4 pairs of DIN/DOUT pins. Since TDM only uses a single pair of pins for synchronous capture and playback, the controller needs to be told which of the pair is connected. This can be mentioned using the "microchip,tdm-data-pair" property from DT. The property is optional, useful only if TDM is used. If it's missing, DIN/DOUT 0 pins will be used by default. Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210301170905.835091-6-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-i2s-mcc.c | 52 +++++++++++++++++++++++++++++++--- 1 file changed, 48 insertions(+), 4 deletions(-) diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 52d3f43148dc..515ba3634fdd 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -100,6 +100,8 @@ #define MCHP_I2SMCC_MRA_DATALENGTH_8_BITS_COMPACT (7 << 1) #define MCHP_I2SMCC_MRA_WIRECFG_MASK GENMASK(5, 4) +#define MCHP_I2SMCC_MRA_WIRECFG_TDM(pin) (((pin) << 4) & \ + MCHP_I2SMCC_MRA_WIRECFG_MASK) #define MCHP_I2SMCC_MRA_WIRECFG_I2S_1_TDM_0 (0 << 4) #define MCHP_I2SMCC_MRA_WIRECFG_I2S_2_TDM_1 (1 << 4) #define MCHP_I2SMCC_MRA_WIRECFG_I2S_4_TDM_2 (2 << 4) @@ -245,6 +247,7 @@ struct mchp_i2s_mcc_dev { unsigned int frame_length; int tdm_slots; int channels; + u8 tdm_data_pair; unsigned int gclk_use:1; unsigned int gclk_running:1; unsigned int tx_rdy:1; @@ -589,6 +592,8 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, if (!frame_length) frame_length = 2 * params_physical_width(params); } else if (dev->fmt & SND_SOC_DAIFMT_DSP_A) { + mra |= MCHP_I2SMCC_MRA_WIRECFG_TDM(dev->tdm_data_pair); + if (dev->tdm_slots) { if (channels % 2 && channels * 2 <= dev->tdm_slots) { /* @@ -914,6 +919,45 @@ static const struct of_device_id mchp_i2s_mcc_dt_ids[] = { MODULE_DEVICE_TABLE(of, mchp_i2s_mcc_dt_ids); #endif +static int mchp_i2s_mcc_soc_data_parse(struct platform_device *pdev, + struct mchp_i2s_mcc_dev *dev) +{ + int err; + + if (!dev->soc) { + dev_err(&pdev->dev, "failed to get soc data\n"); + return -ENODEV; + } + + if (dev->soc->data_pin_pair_num == 1) + return 0; + + err = of_property_read_u8(pdev->dev.of_node, "microchip,tdm-data-pair", + &dev->tdm_data_pair); + if (err < 0 && err != -EINVAL) { + dev_err(&pdev->dev, + "bad property data for 'microchip,tdm-data-pair': %d", + err); + return err; + } + if (err == -EINVAL) { + dev_info(&pdev->dev, + "'microchip,tdm-data-pair' not found; assuming DIN/DOUT 0 for TDM\n"); + dev->tdm_data_pair = 0; + } else { + if (dev->tdm_data_pair > dev->soc->data_pin_pair_num - 1) { + dev_err(&pdev->dev, + "invalid value for 'microchip,tdm-data-pair': %d\n", + dev->tdm_data_pair); + return -EINVAL; + } + dev_dbg(&pdev->dev, "TMD format on DIN/DOUT %d pins\n", + dev->tdm_data_pair); + } + + return 0; +} + static int mchp_i2s_mcc_probe(struct platform_device *pdev) { struct mchp_i2s_mcc_dev *dev; @@ -966,10 +1010,10 @@ static int mchp_i2s_mcc_probe(struct platform_device *pdev) } dev->soc = of_device_get_match_data(&pdev->dev); - if (!dev->soc) { - dev_err(&pdev->dev, "failed to get soc data\n"); - return -ENODEV; - } + err = mchp_i2s_mcc_soc_data_parse(pdev, dev); + if (err < 0) + return err; + dev->dev = &pdev->dev; dev->regmap = regmap; platform_set_drvdata(pdev, dev); From 16135d66309a5ca67e05cd7d0b1b038597a0b0a3 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Mon, 1 Mar 2021 19:09:04 +0200 Subject: [PATCH 0119/1091] ASoC: mchp-i2s-mcc: Add FIFOs support I2S-MCC found on SAMA7G5 includes 2 FIFOs (capture and playback). When FIFOs are enabled, bits I2SMCC_ISRA.TXLRDYx and I2SMCC_ISRA.TXRRDYx must not be used. Bits I2SMCC_ISRB.TXFFRDY and I2SMCC_ISRB.RXFFRDY must be used instead. Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210301170905.835091-7-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- sound/soc/atmel/mchp-i2s-mcc.c | 76 +++++++++++++++++++++++++--------- 1 file changed, 56 insertions(+), 20 deletions(-) diff --git a/sound/soc/atmel/mchp-i2s-mcc.c b/sound/soc/atmel/mchp-i2s-mcc.c index 515ba3634fdd..673bc16cb46a 100644 --- a/sound/soc/atmel/mchp-i2s-mcc.c +++ b/sound/soc/atmel/mchp-i2s-mcc.c @@ -176,7 +176,7 @@ */ #define MCHP_I2SMCC_MRB_CRAMODE_REGULAR (1 << 0) -#define MCHP_I2SMCC_MRB_FIFOEN BIT(1) +#define MCHP_I2SMCC_MRB_FIFOEN BIT(4) #define MCHP_I2SMCC_MRB_DMACHUNK_MASK GENMASK(9, 8) #define MCHP_I2SMCC_MRB_DMACHUNK(no_words) \ @@ -230,6 +230,7 @@ static const struct regmap_config mchp_i2s_mcc_regmap_config = { struct mchp_i2s_mcc_soc_data { unsigned int data_pin_pair_num; + bool has_fifo; }; struct mchp_i2s_mcc_dev { @@ -257,7 +258,7 @@ struct mchp_i2s_mcc_dev { static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void *dev_id) { struct mchp_i2s_mcc_dev *dev = dev_id; - u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0; + u32 sra, imra, srb, imrb, pendinga, pendingb, idra = 0, idrb = 0; irqreturn_t ret = IRQ_NONE; regmap_read(dev->regmap, MCHP_I2SMCC_IMRA, &imra); @@ -275,24 +276,36 @@ static irqreturn_t mchp_i2s_mcc_interrupt(int irq, void *dev_id) * Tx/Rx ready interrupts are enabled when stopping only, to assure * availability and to disable clocks if necessary */ - idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) | - MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)); - if (idra) + if (dev->soc->has_fifo) { + idrb |= pendingb & (MCHP_I2SMCC_INT_TXFFRDY | + MCHP_I2SMCC_INT_RXFFRDY); + } else { + idra |= pendinga & (MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels) | + MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)); + } + if (idra || idrb) ret = IRQ_HANDLED; - if ((imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) && - (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) == - (idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) { + if ((!dev->soc->has_fifo && + (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) && + (imra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)) == + (idra & MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels))) || + (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_TXFFRDY)) { dev->tx_rdy = 1; wake_up_interruptible(&dev->wq_txrdy); } - if ((imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) && - (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) == - (idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) { + if ((!dev->soc->has_fifo && + (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) && + (imra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)) == + (idra & MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels))) || + (dev->soc->has_fifo && imrb & MCHP_I2SMCC_INT_RXFFRDY)) { dev->rx_rdy = 1; wake_up_interruptible(&dev->wq_rxrdy); } - regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra); + if (dev->soc->has_fifo) + regmap_write(dev->regmap, MCHP_I2SMCC_IDRB, idrb); + else + regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, idra); return ret; } @@ -664,6 +677,10 @@ static int mchp_i2s_mcc_hw_params(struct snd_pcm_substream *substream, } } + /* enable FIFO if available */ + if (dev->soc->has_fifo) + mrb |= MCHP_I2SMCC_MRB_FIFOEN; + /* * If we are already running, the wanted setup must be * the same with the one that's currently ongoing @@ -726,8 +743,13 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream *substream, if (err == 0) { dev_warn_once(dev->dev, "Timeout waiting for Tx ready\n"); - regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, - MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)); + if (dev->soc->has_fifo) + regmap_write(dev->regmap, MCHP_I2SMCC_IDRB, + MCHP_I2SMCC_INT_TXFFRDY); + else + regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, + MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels)); + dev->tx_rdy = 1; } } else { @@ -737,8 +759,12 @@ static int mchp_i2s_mcc_hw_free(struct snd_pcm_substream *substream, if (err == 0) { dev_warn_once(dev->dev, "Timeout waiting for Rx ready\n"); - regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, - MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)); + if (dev->soc->has_fifo) + regmap_write(dev->regmap, MCHP_I2SMCC_IDRB, + MCHP_I2SMCC_INT_RXFFRDY); + else + regmap_write(dev->regmap, MCHP_I2SMCC_IDRA, + MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels)); dev->rx_rdy = 1; } } @@ -765,7 +791,7 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream *substream, int cmd, struct mchp_i2s_mcc_dev *dev = snd_soc_dai_get_drvdata(dai); bool is_playback = (substream->stream == SNDRV_PCM_STREAM_PLAYBACK); u32 cr = 0; - u32 iera = 0; + u32 iera = 0, ierb = 0; u32 sr; int err; @@ -789,7 +815,10 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream *substream, int cmd, * Enable Tx Ready interrupts on all channels * to assure all data is sent */ - iera = MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels); + if (dev->soc->has_fifo) + ierb = MCHP_I2SMCC_INT_TXFFRDY; + else + iera = MCHP_I2SMCC_INT_TXRDY_MASK(dev->channels); } else if (!is_playback && (sr & MCHP_I2SMCC_SR_RXEN)) { cr = MCHP_I2SMCC_CR_RXDIS; dev->rx_rdy = 0; @@ -797,7 +826,10 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream *substream, int cmd, * Enable Rx Ready interrupts on all channels * to assure all data is received */ - iera = MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels); + if (dev->soc->has_fifo) + ierb = MCHP_I2SMCC_INT_RXFFRDY; + else + iera = MCHP_I2SMCC_INT_RXRDY_MASK(dev->channels); } break; default: @@ -815,7 +847,10 @@ static int mchp_i2s_mcc_trigger(struct snd_pcm_substream *substream, int cmd, } } - regmap_write(dev->regmap, MCHP_I2SMCC_IERA, iera); + if (dev->soc->has_fifo) + regmap_write(dev->regmap, MCHP_I2SMCC_IERB, ierb); + else + regmap_write(dev->regmap, MCHP_I2SMCC_IERA, iera); regmap_write(dev->regmap, MCHP_I2SMCC_CR, cr); return 0; @@ -903,6 +938,7 @@ static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sam9x60 = { static struct mchp_i2s_mcc_soc_data mchp_i2s_mcc_sama7g5 = { .data_pin_pair_num = 4, + .has_fifo = true, }; static const struct of_device_id mchp_i2s_mcc_dt_ids[] = { From 153bb1feefd2a7c907d65ccf89953feb1548e60f Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Mon, 1 Mar 2021 19:08:59 +0200 Subject: [PATCH 0120/1091] ASoC: mchp,i2s-mcc: Add SAMA7G5 to binding SAMA7G5 includes an updated version of the I2S-MCC driver, that includes 3 more DIN/DOUT pin pairs for multi-channel. Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210301170905.835091-2-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt index 91ec83a6faed..2180dbd9ea81 100644 --- a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt +++ b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt @@ -1,7 +1,8 @@ * Microchip I2S Multi-Channel Controller Required properties: -- compatible: Should be "microchip,sam9x60-i2smcc". +- compatible: Should be "microchip,sam9x60-i2smcc" or + "microchip,sama7g5-i2smcc". - reg: Should be the physical base address of the controller and the length of memory mapped region. - interrupts: Should contain the interrupt for the controller. From ead2a3e43f0a6556e464a83ffba7d7baacf0d426 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Mon, 1 Mar 2021 19:09:02 +0200 Subject: [PATCH 0121/1091] ASoC: mchp, i2s-mcc: Add property to specify pin pair for TDM SAMA7G5's I2S-MCC has 4 pairs of DIN/DOUT pins. Since TDM only uses a single pair of pins for synchronous capture and playback, the controller needs to be told which of the pair is connected. This can be mentioned using the new "microchip,tdm-data-pair" property. The property is optional, needed only if TDM is used, and if it's missing DIN/DOUT 0 pins will be used by default. Signed-off-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210301170905.835091-5-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt index 2180dbd9ea81..af8fe3e657df 100644 --- a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt +++ b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt @@ -19,7 +19,12 @@ Required properties: Optional properties: - pinctrl-0: Should specify pin control groups used for this controller. - princtrl-names: Should contain only one value - "default". - +- microchip,tdm-data-pair: 8 bit value that represents the DIN/DOUT pair pins + which are used to receive/send TDM data. It is optional + and it is only needed if the controller uses the TDM + mode. Not available for "microchip,sam9x60-i2smcc" + compatible. If it's not present, the default value is 0, + so the DIN/DOUT 0 pins are used. (1) : Only the peripheral clock is required. The generated clock is optional and should be set mostly when Master Mode is required. From 4e8d9fe7f09bd975b85382af9fd301645ee8c0e8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 1 Mar 2021 17:56:36 -0600 Subject: [PATCH 0122/1091] ASoC: Intel: soc-acpi: remove unused TGL table with rt5682 only This patch partially reverts Commit 095ee71907ea ("ASoC: Intel: common: add match table for TGL RT5682 SoundWire driver"). This commit was added as an enabling patch before the Maxim98373 codec driver was available. This codec is now fully functional and the topology with only RT5682 no longer maintained or used. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20210301235637.1177525-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-tgl-match.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index 40f31c8a3aba..e8640ee10012 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -415,12 +415,6 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-tgl-sdw-max98373-rt5682.tplg", }, - { - .link_mask = 0x1, /* this will only enable rt5682 for now */ - .links = tgl_chromebook_base, - .drv_name = "sof_sdw", - .sof_tplg_filename = "sof-tgl-rt5682.tplg", - }, {}, }; EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_tgl_sdw_machines); From 5ed26a834b83a368f2c026f22db9becc56fd37f9 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 1 Mar 2021 17:56:37 -0600 Subject: [PATCH 0123/1091] ASoC: Intel: soc-acpi: remove TGL RVP mixed SoundWire/TDM config The TGL RVP can be configured in many ways. We initially supported a mixed configuration with RT711 in SoundWire mode and RT1308 in TDM mode. However Intel teams no longer have any hardware with this configuration and there are no commercially-available devices using it either, so let's remove this entry. The corresponding topology will also be removed from the SOF tree. This patch partially reverts Commit d985d208bf8f ("ASoC: Intel: common: add match tables for TGL w/ SoundWire") Signed-off-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Bard Liao Reviewed-by: Rander Wang Link: https://lore.kernel.org/r/20210301235637.1177525-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../soc/intel/common/soc-acpi-intel-tgl-match.c | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c index e8640ee10012..b5f05b81a584 100644 --- a/sound/soc/intel/common/soc-acpi-intel-tgl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-tgl-match.c @@ -182,15 +182,6 @@ static const struct snd_soc_acpi_adr_device rt714_3_adr[] = { } }; -static const struct snd_soc_acpi_link_adr tgl_i2s_rt1308[] = { - { - .mask = BIT(0), - .num_adr = ARRAY_SIZE(rt711_0_adr), - .adr_d = rt711_0_adr, - }, - {} -}; - static const struct snd_soc_acpi_link_adr tgl_rvp[] = { { .mask = BIT(0), @@ -330,14 +321,6 @@ static const struct snd_soc_acpi_codecs tgl_rt1011_amp = { }; struct snd_soc_acpi_mach snd_soc_acpi_intel_tgl_machines[] = { - { - .id = "10EC1308", - .drv_name = "sof_sdw", - .link_mask = 0x1, /* RT711 on SoundWire link0 */ - .links = tgl_i2s_rt1308, - .sof_fw_filename = "sof-tgl.ri", - .sof_tplg_filename = "sof-tgl-rt711-i2s-rt1308.tplg", - }, { .id = "10EC5682", .drv_name = "tgl_max98357a_rt5682", From 075d7da7d6b42db90039a95f102d7d999ecc410e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 1 Mar 2021 11:46:39 -0600 Subject: [PATCH 0124/1091] ASoC: codecs: nau8825: fix kernel-doc v5.12-rc1 flags new warnings with make W=1, fix missing or broken function descriptors. sound/soc/codecs/nau8825.c:298: warning: wrong kernel-doc identifier on line: * Ramp up the headphone volume change gradually to target level. sound/soc/codecs/nau8825.c:358: warning: expecting prototype for This func(). Prototype was for nau8825_intlog10_dec3() instead sound/soc/codecs/nau8825.c:411: warning: wrong kernel-doc identifier on line: * computes cross talk suppression sidetone gain. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210301174639.117017-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index f0cba7b5758b..e19db30c457b 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -295,7 +295,7 @@ static inline void nau8825_sema_reset(struct nau8825 *nau8825) } /** - * Ramp up the headphone volume change gradually to target level. + * nau8825_hpvol_ramp - Ramp up the headphone volume change gradually to target level. * * @nau8825: component to register the codec private data with * @vol_from: the volume to start up @@ -347,8 +347,9 @@ static void nau8825_hpvol_ramp(struct nau8825 *nau8825, } /** - * Computes log10 of a value; the result is round off to 3 decimal. This func- - * tion takes reference to dvb-math. The source code locates as the following. + * nau8825_intlog10_dec3 - Computes log10 of a value + * the result is round off to 3 decimal. This function takes reference to + * dvb-math. The source code locates as the following. * Linux/drivers/media/dvb-core/dvb_math.c * @value: input for log10 * @@ -408,7 +409,7 @@ static u32 nau8825_intlog10_dec3(u32 value) } /** - * computes cross talk suppression sidetone gain. + * nau8825_xtalk_sidetone - computes cross talk suppression sidetone gain. * * @sig_org: orignal signal level * @sig_cros: cross talk signal level From 2fb8711095a1f8b545b2cae307d9b0fc9591e36b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 1 Mar 2021 11:46:59 -0600 Subject: [PATCH 0125/1091] ASoC: soc-dai: fix kernel-doc v5.12-rc1 flags new warnings with make W=1, fix missing or broken function descriptors. sound/soc/soc-dai.c:167: warning: expecting prototype for snd_soc_xlate_tdm_slot(). Prototype was for snd_soc_xlate_tdm_slot_mask() instead Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210301174659.117122-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-dai.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index cd3bb9a7983f..080fbe053fc5 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -154,7 +154,7 @@ int snd_soc_dai_set_fmt(struct snd_soc_dai *dai, unsigned int fmt) EXPORT_SYMBOL_GPL(snd_soc_dai_set_fmt); /** - * snd_soc_xlate_tdm_slot - generate tx/rx slot mask. + * snd_soc_xlate_tdm_slot_mask - generate tx/rx slot mask. * @slots: Number of slots in use. * @tx_mask: bitmask representing active TX slots. * @rx_mask: bitmask representing active RX slots. From 7810ea4c8f74ff904ac1ea06dde9201af566d679 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Mon, 1 Mar 2021 10:53:47 -0600 Subject: [PATCH 0126/1091] ASoC: Intel: atom: fix kernel-doc v5.12-rc1 flags new warnings with make W=1, fix missing or broken function descriptors. sound/soc/intel/atom/sst/sst_loader.c:85: warning: expecting prototype for sst_start_merrifield(). Prototype was for sst_start_mrfld() instead sound/soc/intel/atom/sst/sst_acpi.c:339: warning: expecting prototype for intel_sst_remove(). Prototype was for sst_acpi_remove() instead Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210301165349.114952-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst/sst_acpi.c | 2 +- sound/soc/intel/atom/sst/sst_loader.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/atom/sst/sst_acpi.c b/sound/soc/intel/atom/sst/sst_acpi.c index 2c1b8a2e3506..3be64430c256 100644 --- a/sound/soc/intel/atom/sst/sst_acpi.c +++ b/sound/soc/intel/atom/sst/sst_acpi.c @@ -328,7 +328,7 @@ static int sst_acpi_probe(struct platform_device *pdev) } /** -* intel_sst_remove - remove function +* sst_acpi_remove - remove function * * @pdev: platform device structure * diff --git a/sound/soc/intel/atom/sst/sst_loader.c b/sound/soc/intel/atom/sst/sst_loader.c index 1c9b0c9ec483..eea889001c24 100644 --- a/sound/soc/intel/atom/sst/sst_loader.c +++ b/sound/soc/intel/atom/sst/sst_loader.c @@ -76,7 +76,7 @@ int intel_sst_reset_dsp_mrfld(struct intel_sst_drv *sst_drv_ctx) } /** - * sst_start_merrifield - Start the SST DSP processor + * sst_start_mrfld - Start the SST DSP processor * @sst_drv_ctx: intel_sst_drv context pointer * * This starts the DSP in MERRIFIELD platfroms From ee00e0bf7e4fe6c253219680b339add32686efee Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 1 Mar 2021 16:33:28 -0300 Subject: [PATCH 0127/1091] ASoC: wm8524: Do not print probe defer error On an imx8mq-evk the following error is seen: [ 1.375809] wm8524-codec audio-codec: Failed to get mute line: -517 It happens because the codec driver may probe prior to the imx gpio driver, which causes a probe defer. Change to dev_err_probe() to avoid printing this error. Reported-by: Chris Healy Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210301193328.2123511-1-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8524.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8524.c b/sound/soc/codecs/wm8524.c index 4e9ab542f648..81f858f6bd67 100644 --- a/sound/soc/codecs/wm8524.c +++ b/sound/soc/codecs/wm8524.c @@ -227,7 +227,7 @@ static int wm8524_codec_probe(struct platform_device *pdev) wm8524->mute = devm_gpiod_get(&pdev->dev, "wlf,mute", GPIOD_OUT_LOW); if (IS_ERR(wm8524->mute)) { ret = PTR_ERR(wm8524->mute); - dev_err(&pdev->dev, "Failed to get mute line: %d\n", ret); + dev_err_probe(&pdev->dev, ret, "Failed to get mute line\n"); return ret; } From e443858258a2e29eee96e919589448855aa2735e Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Mon, 1 Mar 2021 09:01:57 -0800 Subject: [PATCH 0128/1091] ASoC: SOF: Intel: hda: enable async suspend The skylake driver disabled async suspend to prevent disabling the DSP before the card was suspended during system suspend. This code was carried over to the SOF driver. But, there is no risk of the DSP getting disabled before the card is suspended with the SOF driver. Therefore, it is safe to enable async suspend and thereby optimize the system resume time. Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210301170157.36584-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 0c096db07322..5317dfa4a4bf 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -616,8 +616,6 @@ static int hda_init_caps(struct snd_sof_dev *sdev) u32 link_mask; int ret = 0; - device_disable_async_suspend(bus->dev); - /* check if dsp is there */ if (bus->ppcap) dev_dbg(sdev->dev, "PP capability, will probe DSP later.\n"); From f7c5c16875c2d2b6e1a7f4f1915d125b79be4951 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:04 -0600 Subject: [PATCH 0129/1091] ASoC: rt1011: use logical OR cppcheck complains a lot about mixing booleans and bitwise operations. There is no good reason to use && and |, fix with || Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 34 +++++++++++++++------------------- 1 file changed, 15 insertions(+), 19 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 6877be5f36b9..b9dadc8243b3 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1089,25 +1089,21 @@ static int rt1011_recv_spk_mode_put(struct snd_kcontrol *kcontrol, static bool rt1011_validate_bq_drc_coeff(unsigned short reg) { - if ((reg == RT1011_DAC_SET_1) | - (reg >= RT1011_ADC_SET && reg <= RT1011_ADC_SET_1) | - (reg == RT1011_ADC_SET_4) | (reg == RT1011_ADC_SET_5) | - (reg == RT1011_MIXER_1) | - (reg == RT1011_A_TIMING_1) | (reg >= RT1011_POWER_7 && - reg <= RT1011_POWER_8) | - (reg == RT1011_CLASS_D_POS) | (reg == RT1011_ANALOG_CTRL) | - (reg >= RT1011_SPK_TEMP_PROTECT_0 && - reg <= RT1011_SPK_TEMP_PROTECT_6) | - (reg >= RT1011_SPK_PRO_DC_DET_5 && reg <= RT1011_BAT_GAIN_1) | - (reg >= RT1011_RT_DRC_CROSS && reg <= RT1011_RT_DRC_POS_8) | - (reg >= RT1011_CROSS_BQ_SET_1 && reg <= RT1011_BQ_10_A2_15_0) | - (reg >= RT1011_SMART_BOOST_TIMING_1 && - reg <= RT1011_SMART_BOOST_TIMING_36) | - (reg == RT1011_SINE_GEN_REG_1) | - (reg >= RT1011_STP_ALPHA_RECIPROCAL_MSB && - reg <= RT1011_BQ_6_PARAMS_CHECK_5) | - (reg >= RT1011_BQ_7_PARAMS_CHECK_1 && - reg <= RT1011_BQ_10_PARAMS_CHECK_5)) + if ((reg == RT1011_DAC_SET_1) || + (reg >= RT1011_ADC_SET && reg <= RT1011_ADC_SET_1) || + (reg == RT1011_ADC_SET_4) || (reg == RT1011_ADC_SET_5) || + (reg == RT1011_MIXER_1) || + (reg == RT1011_A_TIMING_1) || + (reg >= RT1011_POWER_7 && reg <= RT1011_POWER_8) || + (reg == RT1011_CLASS_D_POS) || (reg == RT1011_ANALOG_CTRL) || + (reg >= RT1011_SPK_TEMP_PROTECT_0 && reg <= RT1011_SPK_TEMP_PROTECT_6) || + (reg >= RT1011_SPK_PRO_DC_DET_5 && reg <= RT1011_BAT_GAIN_1) || + (reg >= RT1011_RT_DRC_CROSS && reg <= RT1011_RT_DRC_POS_8) || + (reg >= RT1011_CROSS_BQ_SET_1 && reg <= RT1011_BQ_10_A2_15_0) || + (reg >= RT1011_SMART_BOOST_TIMING_1 && reg <= RT1011_SMART_BOOST_TIMING_36) || + (reg == RT1011_SINE_GEN_REG_1) || + (reg >= RT1011_STP_ALPHA_RECIPROCAL_MSB && reg <= RT1011_BQ_6_PARAMS_CHECK_5) || + (reg >= RT1011_BQ_7_PARAMS_CHECK_1 && reg <= RT1011_BQ_10_PARAMS_CHECK_5)) return true; return false; From 7e66f16251eb59410257a1e5e279e6c949f53171 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:05 -0600 Subject: [PATCH 0130/1091] ASoC: rt1011: remove redundant test cppcheck warning: sound/soc/codecs/rt1011.c:1994:6: style: Condition 'tx_slotnum' is always true [knownConditionTrueFalse] if (tx_slotnum) ^ sound/soc/codecs/rt1011.c:1895:24: note: Assuming that condition '!tx_slotnum' is not redundant if (tx_slotnum > 2 || !tx_slotnum) { ^ sound/soc/codecs/rt1011.c:1994:6: note: Condition 'tx_slotnum' is always true if (tx_slotnum) ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index b9dadc8243b3..39a9f17ca0a9 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1987,10 +1987,10 @@ static int rt1011_set_tdm_slot(struct snd_soc_dai *dai, RT1011_TDM_I2S_DOCK_EN_1_MASK, tdm_en); snd_soc_component_update_bits(component, RT1011_TDM2_SET_2, RT1011_TDM_I2S_DOCK_EN_2_MASK, tdm_en); - if (tx_slotnum) - snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET, - RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG, - RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT); + + snd_soc_component_update_bits(component, RT1011_TDM_TOTAL_SET, + RT1011_ADCDAT1_PIN_CONFIG | RT1011_ADCDAT2_PIN_CONFIG, + RT1011_ADCDAT1_OUTPUT | RT1011_ADCDAT2_OUTPUT); _set_tdm_err_: snd_soc_dapm_mutex_unlock(dapm); From 5a2429926549a8828f7dedd690b498eb9ce0296a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:06 -0600 Subject: [PATCH 0131/1091] ASoC: rt1011: clarify expression cppcheck warning: sound/soc/codecs/rt1011.c:1781:63: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT1011_PLL1_QM_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 39a9f17ca0a9..238cb66f4c6a 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -1778,8 +1778,9 @@ static int rt1011_set_component_pll(struct snd_soc_component *component, pll_code.n_code, pll_code.k_code); snd_soc_component_write(component, RT1011_PLL_1, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT1011_PLL1_QM_SFT | - pll_code.m_bp << RT1011_PLL1_BPM_SFT | pll_code.n_code); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT1011_PLL1_QM_SFT) | + (pll_code.m_bp << RT1011_PLL1_BPM_SFT) | + pll_code.n_code); snd_soc_component_write(component, RT1011_PLL_2, pll_code.k_code); From 4354ad55cde7c50c738d11edf302549537bce504 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:07 -0600 Subject: [PATCH 0132/1091] ASoC: rt1015: clarify expression cppcheck warning: sound/soc/codecs/rt1015.c:894:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT1015_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 3cd967ae999d..10a7b7745f4b 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -893,8 +893,9 @@ static int rt1015_set_component_pll(struct snd_soc_component *component, pll_code.n_code, pll_code.k_code); snd_soc_component_write(component, RT1015_PLL1, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT1015_PLL_M_SFT | - pll_code.m_bp << RT1015_PLL_M_BP_SFT | pll_code.n_code); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT1015_PLL_M_SFT) | + (pll_code.m_bp << RT1015_PLL_M_BP_SFT) | + pll_code.n_code); snd_soc_component_write(component, RT1015_PLL2, pll_code.k_code); From a426017ed5932141da4f09a35ed562bc845fa281 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:08 -0600 Subject: [PATCH 0133/1091] ASoC: rt1016: clarify expression cppcheck warning: sound/soc/codecs/rt1016.c:503:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT1016_PLL_M_SFT | ^ sound/soc/codecs/rt1016.c:506:40: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] pll_code.k_bp << RT1016_PLL_K_BP_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1016.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt1016.c b/sound/soc/codecs/rt1016.c index c14a809da52b..7561d202274c 100644 --- a/sound/soc/codecs/rt1016.c +++ b/sound/soc/codecs/rt1016.c @@ -500,10 +500,11 @@ static int rt1016_set_component_pll(struct snd_soc_component *component, (pll_code.k_bp ? 0 : pll_code.k_code)); snd_soc_component_write(component, RT1016_PLL1, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT1016_PLL_M_SFT | - pll_code.m_bp << RT1016_PLL_M_BP_SFT | pll_code.n_code); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT1016_PLL_M_SFT) | + (pll_code.m_bp << RT1016_PLL_M_BP_SFT) | + pll_code.n_code); snd_soc_component_write(component, RT1016_PLL2, - pll_code.k_bp << RT1016_PLL_K_BP_SFT | + (pll_code.k_bp << RT1016_PLL_K_BP_SFT) | (pll_code.k_bp ? 0 : pll_code.k_code)); rt1016->pll_in = freq_in; From 9e884eed54c4138bfb77da18016131a6ec1b0af7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:09 -0600 Subject: [PATCH 0134/1091] ASoC: rt1305: clarify expression cppcheck warning: sound/soc/codecs/rt1305.c:853:63: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT1305_PLL_1_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1305.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1305.c b/sound/soc/codecs/rt1305.c index 16aa405fb8f0..7a0094578e46 100644 --- a/sound/soc/codecs/rt1305.c +++ b/sound/soc/codecs/rt1305.c @@ -850,8 +850,8 @@ static int rt1305_set_component_pll(struct snd_soc_component *component, pll_code.n_code, pll_code.k_code); snd_soc_component_write(component, RT1305_PLL1_1, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT1305_PLL_1_M_SFT | - pll_code.m_bp << RT1305_PLL_1_M_BYPASS_SFT | + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT1305_PLL_1_M_SFT) | + (pll_code.m_bp << RT1305_PLL_1_M_BYPASS_SFT) | pll_code.n_code); snd_soc_component_write(component, RT1305_PLL1_2, pll_code.k_code); From 1dd9cca701468b6285dea5188efc9aa28aabbf56 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:10 -0600 Subject: [PATCH 0135/1091] ASoC: rt1308: clarify expression cppcheck warning: sound/soc/codecs/rt1308.c:676:40: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] pll_code.k_code << RT1308_PLL1_K_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1308.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt1308.c b/sound/soc/codecs/rt1308.c index 76e65844543d..b4e5546e2e21 100644 --- a/sound/soc/codecs/rt1308.c +++ b/sound/soc/codecs/rt1308.c @@ -673,10 +673,10 @@ static int rt1308_set_component_pll(struct snd_soc_component *component, pll_code.n_code, pll_code.k_code); snd_soc_component_write(component, RT1308_PLL_1, - pll_code.k_code << RT1308_PLL1_K_SFT | - pll_code.m_bp << RT1308_PLL1_M_BYPASS_SFT | - (pll_code.m_bp ? 0 : pll_code.m_code) << RT1308_PLL1_M_SFT | - pll_code.n_code << RT1308_PLL1_N_SFT); + (pll_code.k_code << RT1308_PLL1_K_SFT) | + (pll_code.m_bp << RT1308_PLL1_M_BYPASS_SFT) | + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT1308_PLL1_M_SFT) | + (pll_code.n_code << RT1308_PLL1_N_SFT)); rt1308->pll_in = freq_in; rt1308->pll_out = freq_out; From 4fbd2978944cff4e747f132cf86254956bb2f045 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:11 -0600 Subject: [PATCH 0136/1091] ASoC: rt5640: clarify expression cppcheck warning: sound/soc/codecs/rt5640.c:1923:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index a5674c227b3a..8c1766954b92 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -1918,10 +1918,10 @@ static int rt5640_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, pll_code.n_code, pll_code.k_code); snd_soc_component_write(component, RT5640_PLL_CTRL1, - pll_code.n_code << RT5640_PLL_N_SFT | pll_code.k_code); + (pll_code.n_code << RT5640_PLL_N_SFT) | pll_code.k_code); snd_soc_component_write(component, RT5640_PLL_CTRL2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT | - pll_code.m_bp << RT5640_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5640_PLL_M_SFT) | + (pll_code.m_bp << RT5640_PLL_M_BP_SFT)); rt5640->pll_in = freq_in; rt5640->pll_out = freq_out; From 5864cf7f26aed303c96bcc56f8c8af914fac9bfb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:12 -0600 Subject: [PATCH 0137/1091] ASoC: rt5645: use logical OR cppcheck warning: sound/soc/codecs/rt5645.c:693:37: style:inconclusive: Boolean expression 'reg>=420&®<=461' is used in bitwise operation. Did you mean '||'? [bitwiseOnBoolean] if ((reg >= 0x1a4 && reg <= 0x1cd) | (reg >= 0x1e5 && reg <= 0x1f8) | ^ sound/soc/codecs/rt5645.c:693:70: style:inconclusive: Boolean expression 'reg==177' is used in bitwise operation. Did you mean '||'? [bitwiseOnBoolean] if ((reg >= 0x1a4 && reg <= 0x1cd) | (reg >= 0x1e5 && reg <= 0x1f8) | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 63a7e052eaa0..4db6cd70e32b 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -690,7 +690,7 @@ static int rt5645_hweq_get(struct snd_kcontrol *kcontrol, static bool rt5645_validate_hweq(unsigned short reg) { - if ((reg >= 0x1a4 && reg <= 0x1cd) | (reg >= 0x1e5 && reg <= 0x1f8) | + if ((reg >= 0x1a4 && reg <= 0x1cd) || (reg >= 0x1e5 && reg <= 0x1f8) || (reg == RT5645_EQ_CTRL2)) return true; From fa0eb20cb38d8e41ff097b985755ba62e1b32b24 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:13 -0600 Subject: [PATCH 0138/1091] ASoC: rt5645: clarify expression cppcheck warning: sound/soc/codecs/rt5645.c:2959:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5645_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 4db6cd70e32b..c39095fa14ce 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -2956,8 +2956,8 @@ static int rt5645_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, snd_soc_component_write(component, RT5645_PLL_CTRL1, pll_code.n_code << RT5645_PLL_N_SFT | pll_code.k_code); snd_soc_component_write(component, RT5645_PLL_CTRL2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5645_PLL_M_SFT | - pll_code.m_bp << RT5645_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5645_PLL_M_SFT) | + (pll_code.m_bp << RT5645_PLL_M_BP_SFT)); rt5645->pll_in = freq_in; rt5645->pll_out = freq_out; From 33eaffe3706ab93ced1b4477f6598a5502028ce3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:14 -0600 Subject: [PATCH 0139/1091] ASoC: rt5651: clarify expression cppcheck warning: sound/soc/codecs/rt5659.c:3515:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5659_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index e59fdc81dbd4..49fab9db5917 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1498,8 +1498,8 @@ static int rt5651_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, snd_soc_component_write(component, RT5651_PLL_CTRL1, pll_code.n_code << RT5651_PLL_N_SFT | pll_code.k_code); snd_soc_component_write(component, RT5651_PLL_CTRL2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5651_PLL_M_SFT | - pll_code.m_bp << RT5651_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5651_PLL_M_SFT) | + (pll_code.m_bp << RT5651_PLL_M_BP_SFT)); rt5651->pll_in = freq_in; rt5651->pll_out = freq_out; From 9b9adc5b749d2f31885f36e2adc6c13af70543bd Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:15 -0600 Subject: [PATCH 0140/1091] ASoC: rt5651: remove useless assignment cppcheck warning: sound/soc/codecs/rt5651.c:1786:13: style: Variable 'report' is assigned a value that is never used. [unreadVariable] int report = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5651.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5651.c b/sound/soc/codecs/rt5651.c index 49fab9db5917..fc0c83b73f09 100644 --- a/sound/soc/codecs/rt5651.c +++ b/sound/soc/codecs/rt5651.c @@ -1783,7 +1783,7 @@ static void rt5651_jack_detect_work(struct work_struct *work) struct rt5651_priv *rt5651 = container_of(work, struct rt5651_priv, jack_detect_work); struct snd_soc_component *component = rt5651->component; - int report = 0; + int report; if (!rt5651_jack_inserted(component)) { /* Jack removed, or spurious IRQ? */ From bb133ec21f865a03b8798b57815461fe0e7e6ec8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:16 -0600 Subject: [PATCH 0141/1091] ASoC: rt5659: clarify expression cppcheck warning: sound/soc/codecs/rt5659.c:3515:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5659_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5659.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5659.c b/sound/soc/codecs/rt5659.c index 41e5917b16a5..67f0ab817135 100644 --- a/sound/soc/codecs/rt5659.c +++ b/sound/soc/codecs/rt5659.c @@ -3512,8 +3512,8 @@ static int rt5659_set_component_pll(struct snd_soc_component *component, int pll snd_soc_component_write(component, RT5659_PLL_CTRL_1, pll_code.n_code << RT5659_PLL_N_SFT | pll_code.k_code); snd_soc_component_write(component, RT5659_PLL_CTRL_2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5659_PLL_M_SFT | - pll_code.m_bp << RT5659_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5659_PLL_M_SFT) | + (pll_code.m_bp << RT5659_PLL_M_BP_SFT)); rt5659->pll_in = freq_in; rt5659->pll_out = freq_out; From 9fd72391ae8fa0811603c7489b8afacd66f5f5e6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:17 -0600 Subject: [PATCH 0142/1091] ASoC: rt5660: clarify expression cppcheck warning: sound/soc/codecs/rt5660.c:1060:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5660_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5660.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5660.c b/sound/soc/codecs/rt5660.c index 0edf09d3a499..33ff9156358b 100644 --- a/sound/soc/codecs/rt5660.c +++ b/sound/soc/codecs/rt5660.c @@ -1057,8 +1057,8 @@ static int rt5660_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, snd_soc_component_write(component, RT5660_PLL_CTRL1, pll_code.n_code << RT5660_PLL_N_SFT | pll_code.k_code); snd_soc_component_write(component, RT5660_PLL_CTRL2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5660_PLL_M_SFT | - pll_code.m_bp << RT5660_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5660_PLL_M_SFT) | + (pll_code.m_bp << RT5660_PLL_M_BP_SFT)); rt5660->pll_in = freq_in; rt5660->pll_out = freq_out; From ca1107d305b58a9b47ac071e1547490327bff007 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:18 -0600 Subject: [PATCH 0143/1091] ASoC: rt5663: clarify expression cppcheck warning: bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5663_PLL_M_SHIFT | ^ sound/soc/codecs/rt5663.c:2955:63: style: Boolean result is used in Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5663.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5663.c b/sound/soc/codecs/rt5663.c index 619fb9a031e3..be9fc58ff681 100644 --- a/sound/soc/codecs/rt5663.c +++ b/sound/soc/codecs/rt5663.c @@ -2952,8 +2952,8 @@ static int rt5663_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, snd_soc_component_write(component, RT5663_PLL_1, pll_code.n_code << RT5663_PLL_N_SHIFT | pll_code.k_code); snd_soc_component_write(component, RT5663_PLL_2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5663_PLL_M_SHIFT | - pll_code.m_bp << RT5663_PLL_M_BP_SHIFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5663_PLL_M_SHIFT) | + (pll_code.m_bp << RT5663_PLL_M_BP_SHIFT)); rt5663->pll_in = freq_in; rt5663->pll_out = freq_out; From 17d78e93114887033f0be1c3c574004d437f7608 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:19 -0600 Subject: [PATCH 0144/1091] ASoC: rt5665: clarify expression cppcheck warning: sound/soc/codecs/rt5665.c:4388:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5665_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5665.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5665.c b/sound/soc/codecs/rt5665.c index 8a915cdce0fe..e59323fd5bf2 100644 --- a/sound/soc/codecs/rt5665.c +++ b/sound/soc/codecs/rt5665.c @@ -4385,8 +4385,8 @@ static int rt5665_set_component_pll(struct snd_soc_component *component, int pll snd_soc_component_write(component, RT5665_PLL_CTRL_1, pll_code.n_code << RT5665_PLL_N_SFT | pll_code.k_code); snd_soc_component_write(component, RT5665_PLL_CTRL_2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5665_PLL_M_SFT | - pll_code.m_bp << RT5665_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5665_PLL_M_SFT) | + (pll_code.m_bp << RT5665_PLL_M_BP_SFT)); rt5665->pll_in = freq_in; rt5665->pll_out = freq_out; From 17de60946a65fb013753ff2d7d01f890cb82d446 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:20 -0600 Subject: [PATCH 0145/1091] ASoC: rt5668: clarify expression cppcheck warning: sound/soc/codecs/rt5668.c:2185:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5668_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5668.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index bc69adc9c8b7..d966d6d1bf64 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -2182,8 +2182,8 @@ static int rt5668_set_component_pll(struct snd_soc_component *component, snd_soc_component_write(component, RT5668_PLL_CTRL_1, pll_code.n_code << RT5668_PLL_N_SFT | pll_code.k_code); snd_soc_component_write(component, RT5668_PLL_CTRL_2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5668_PLL_M_SFT | - pll_code.m_bp << RT5668_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5668_PLL_M_SFT) | + (pll_code.m_bp << RT5668_PLL_M_BP_SFT)); rt5668->pll_in = freq_in; rt5668->pll_out = freq_out; From 6fa5445685150dee9930cdfe7a96353a4dcc1d50 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:21 -0600 Subject: [PATCH 0146/1091] ASoC: rt5668: remove useless assignments cppcheck warnings: sound/soc/codecs/rt5668.c:1177:6: style: Redundant initialization for 'idx'. The initialized value is overwritten before it is read. [redundantInitialization] idx = rt5668_div_sel(rt5668, 1500000, div, ARRAY_SIZE(div)); ^ sound/soc/codecs/rt5668.c:1174:10: note: idx is initialized int idx = -EINVAL; ^ sound/soc/codecs/rt5668.c:1177:6: note: idx is overwritten idx = rt5668_div_sel(rt5668, 1500000, div, ARRAY_SIZE(div)); ^ sound/soc/codecs/rt5668.c:1202:6: style: Redundant initialization for 'idx'. The initialized value is overwritten before it is read. [redundantInitialization] idx = rt5668_div_sel(rt5668, ref, div, ARRAY_SIZE(div)); ^ sound/soc/codecs/rt5668.c:1191:25: note: idx is initialized int ref, val, reg, idx = -EINVAL; ^ sound/soc/codecs/rt5668.c:1202:6: note: idx is overwritten idx = rt5668_div_sel(rt5668, ref, div, ARRAY_SIZE(div)); ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5668.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5668.c b/sound/soc/codecs/rt5668.c index d966d6d1bf64..6ab1a8bc3735 100644 --- a/sound/soc/codecs/rt5668.c +++ b/sound/soc/codecs/rt5668.c @@ -1171,7 +1171,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5668_priv *rt5668 = snd_soc_component_get_drvdata(component); - int idx = -EINVAL; + int idx; static const int div[] = {2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128}; idx = rt5668_div_sel(rt5668, 1500000, div, ARRAY_SIZE(div)); @@ -1188,7 +1188,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5668_priv *rt5668 = snd_soc_component_get_drvdata(component); - int ref, val, reg, idx = -EINVAL; + int ref, val, reg, idx; static const int div[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; val = snd_soc_component_read(component, RT5668_GPIO_CTRL_1) & From 7ad9b8d28d3f2997b4af0a074e6f609ffb5d32a7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:22 -0600 Subject: [PATCH 0147/1091] ASoC: rt5670: clarify expression cppcheck warning: sound/soc/codecs/rt5670.c:2519:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5670_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 4063aac2a443..8dcda24f3ceb 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2588,8 +2588,8 @@ static int rt5670_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, snd_soc_component_write(component, RT5670_PLL_CTRL1, pll_code.n_code << RT5670_PLL_N_SFT | pll_code.k_code); snd_soc_component_write(component, RT5670_PLL_CTRL2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5670_PLL_M_SFT | - pll_code.m_bp << RT5670_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5670_PLL_M_SFT) | + (pll_code.m_bp << RT5670_PLL_M_BP_SFT)); rt5670->pll_in = freq_in; rt5670->pll_out = freq_out; From ae052909d1b1c8dcc2406f11eb3b5f9193dc3d2f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:23 -0600 Subject: [PATCH 0148/1091] ASoC: rt5677: clarify expression cppcheck warning: sound/soc/codecs/rt5677.c:4571:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT | ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index 9e449d35fc28..bc5d1d73470e 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -4568,8 +4568,8 @@ static int rt5677_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, regmap_write(rt5677->regmap, RT5677_PLL1_CTRL1, pll_code.n_code << RT5677_PLL_N_SFT | pll_code.k_code); regmap_write(rt5677->regmap, RT5677_PLL1_CTRL2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT | - pll_code.m_bp << RT5677_PLL_M_BP_SFT); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5677_PLL_M_SFT) | + (pll_code.m_bp << RT5677_PLL_M_BP_SFT)); rt5677->pll_in = freq_in; rt5677->pll_out = freq_out; From 51cb94f6c34017845030f3c20668412469345ef0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:24 -0600 Subject: [PATCH 0149/1091] ASoC: rt5677: remove useless assignment cppcheck warning: sound/soc/codecs/rt5677.c:5335:10: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int ret = 0, loop, i, reg_irq, virq; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5677.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5677.c b/sound/soc/codecs/rt5677.c index bc5d1d73470e..f655228c8c4b 100644 --- a/sound/soc/codecs/rt5677.c +++ b/sound/soc/codecs/rt5677.c @@ -5332,7 +5332,7 @@ static bool rt5677_check_hotword(struct rt5677_priv *rt5677) static irqreturn_t rt5677_irq(int unused, void *data) { struct rt5677_priv *rt5677 = data; - int ret = 0, loop, i, reg_irq, virq; + int ret, loop, i, reg_irq, virq; bool irq_fired = false; mutex_lock(&rt5677->irq_lock); From e699b2c89f8302c600d3373ae0ab12689bbf0da5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:25 -0600 Subject: [PATCH 0150/1091] ASoC: rt5682: clarify expression cppcheck warning: sound/soc/codecs/rt5682.c:2401:65: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT | Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index b306ac4b9b2e..e4542200009d 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2396,10 +2396,10 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, pll_code.n_code, pll_code.k_code); snd_soc_component_write(component, RT5682_PLL_CTRL_1, - pll_code.n_code << RT5682_PLL_N_SFT | pll_code.k_code); + (pll_code.n_code << RT5682_PLL_N_SFT) | pll_code.k_code); snd_soc_component_write(component, RT5682_PLL_CTRL_2, - (pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT | - pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST); + ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT) | + (pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST)); } rt5682->pll_in[pll_id] = freq_in; From ec6aa9b59dbfb6db9447d09977d574f77a31392a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:26 -0600 Subject: [PATCH 0151/1091] ASoC: rt5682: remove useless assignments cppcheck warnings: sound/soc/codecs/rt5682.c:1234:6: style: Redundant initialization for 'idx'. The initialized value is overwritten before it is read. [redundantInitialization] idx = rt5682_div_sel(rt5682, dmic_clk_rate, div, ARRAY_SIZE(div)); ^ sound/soc/codecs/rt5682.c:1228:10: note: idx is initialized int idx = -EINVAL, dmic_clk_rate = 3072000; ^ sound/soc/codecs/rt5682.c:1234:6: note: idx is overwritten idx = rt5682_div_sel(rt5682, dmic_clk_rate, div, ARRAY_SIZE(div)); ^ sound/soc/codecs/rt5682.c:1263:6: style: Redundant initialization for 'idx'. The initialized value is overwritten before it is read. [redundantInitialization] idx = rt5682_div_sel(rt5682, ref, div_f, ARRAY_SIZE(div_f)); ^ sound/soc/codecs/rt5682.c:1248:25: note: idx is initialized int ref, val, reg, idx = -EINVAL; ^ sound/soc/codecs/rt5682.c:1263:6: note: idx is overwritten idx = rt5682_div_sel(rt5682, ref, div_f, ARRAY_SIZE(div_f)); ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-24-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index e4542200009d..8d5b8f01f55c 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -1225,7 +1225,7 @@ static int set_dmic_clk(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - int idx = -EINVAL, dmic_clk_rate = 3072000; + int idx, dmic_clk_rate = 3072000; static const int div[] = {2, 4, 6, 8, 12, 16, 24, 32, 48, 64, 96, 128}; if (rt5682->pdata.dmic_clk_rate) @@ -1245,7 +1245,7 @@ static int set_filter_clk(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt5682_priv *rt5682 = snd_soc_component_get_drvdata(component); - int ref, val, reg, idx = -EINVAL; + int ref, val, reg, idx; static const int div_f[] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32, 48}; static const int div_o[] = {1, 2, 4, 6, 8, 12, 16, 24, 32, 48}; From f1a1da09faa3a875ede33386863ea363270be097 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 15:25:27 -0600 Subject: [PATCH 0152/1091] ASoC: rt5682: remove useless initialization cppcheck complains about a possible null pointer dereference, but the problem is rather an useless initialization before walking through a list. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302212527.55158-25-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 8d5b8f01f55c..559dc6db1f7c 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2751,7 +2751,7 @@ static int rt5682_bclk_set_rate(struct clk_hw *hw, unsigned long rate, container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_BCLK_IDX]); struct snd_soc_component *component = rt5682->component; - struct snd_soc_dai *dai = NULL; + struct snd_soc_dai *dai; unsigned long factor; if (!rt5682_clk_check(rt5682)) From 80cd73094c4096b3ce4d57cb8cf2c3e341c6de97 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:18 -0600 Subject: [PATCH 0153/1091] ASoC: cs4270: fix kernel-doc Add missing parameter (which happens to be ignored) Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs4270.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/codecs/cs4270.c b/sound/soc/codecs/cs4270.c index ddd95c8269ed..2d239e983a83 100644 --- a/sound/soc/codecs/cs4270.c +++ b/sound/soc/codecs/cs4270.c @@ -400,6 +400,7 @@ static int cs4270_hw_params(struct snd_pcm_substream *substream, * cs4270_dai_mute - enable/disable the CS4270 external mute * @dai: the SOC DAI * @mute: 0 = disable mute, 1 = enable mute + * @direction: (ignored) * * This function toggles the mute bits in the MUTE register. The CS4270's * mute capability is intended for external muting circuitry, so if the From c5036b86678fcc17bc49f85b03bd1a0ac8524646 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:19 -0600 Subject: [PATCH 0154/1091] ASoC: jz4760: fix set but not used warning MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit make W=1 warning: sound/soc/codecs/jz4760.c: In function ‘jz4760_codec_startup’: sound/soc/codecs/jz4760.c:201:6: error: variable ‘ret’ set but not used [-Werror=unused-but-set-variable] 201 | int ret; | ^~~ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4760.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/jz4760.c b/sound/soc/codecs/jz4760.c index e8f28ccc145a..f62abf5ad917 100644 --- a/sound/soc/codecs/jz4760.c +++ b/sound/soc/codecs/jz4760.c @@ -198,7 +198,7 @@ static int jz4760_codec_startup(struct snd_pcm_substream *substream, { struct snd_soc_component *codec = dai->component; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(codec); - int ret; + int ret = 0; /* * SYSCLK output from the codec to the AIC is required to keep the @@ -207,7 +207,7 @@ static int jz4760_codec_startup(struct snd_pcm_substream *substream, */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) ret = snd_soc_dapm_force_enable_pin(dapm, "SYSCLK"); - return 0; + return ret; } static void jz4760_codec_shutdown(struct snd_pcm_substream *substream, From 79d77f7fd1de16ea5d5c778f426007edaeb4c365 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:20 -0600 Subject: [PATCH 0155/1091] ASoC: rt5631: fix kernel-doc warning make W=1 warning: sound/soc/codecs/rt5631.c:446: warning: expecting prototype for onebit_depop_power_stage(). Prototype was for depop_seq_power_stage() instead Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5631.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5631.c b/sound/soc/codecs/rt5631.c index afc1305a7fa5..3000bc128b5b 100644 --- a/sound/soc/codecs/rt5631.c +++ b/sound/soc/codecs/rt5631.c @@ -436,7 +436,7 @@ static void onebit_depop_mute_stage(struct snd_soc_component *component, int ena } /** - * onebit_depop_power_stage - step by step depop sequence in power stage. + * depop_seq_power_stage - step by step depop sequence in power stage. * @component: ASoC component * @enable: power on/off * From 5dd902d99ebb63f490d73277340745e0bd9ea7f2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:21 -0600 Subject: [PATCH 0156/1091] ASoC: sigmadsp-regmap: fix kernel-doc warning make W=1 warning: sound/soc/codecs/sigmadsp-regmap.c:42: warning: expecting prototype for devm_sigmadsp_init_i2c(). Prototype was for devm_sigmadsp_init_regmap() instead Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/sigmadsp-regmap.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sigmadsp-regmap.c b/sound/soc/codecs/sigmadsp-regmap.c index bf1c4086da9f..ba9a6795e470 100644 --- a/sound/soc/codecs/sigmadsp-regmap.c +++ b/sound/soc/codecs/sigmadsp-regmap.c @@ -26,7 +26,7 @@ static int sigmadsp_read_regmap(void *control_data, } /** - * devm_sigmadsp_init_i2c() - Initialize SigmaDSP instance + * devm_sigmadsp_init_regmap() - Initialize SigmaDSP instance * @dev: The parent device * @regmap: Regmap instance to use * @ops: The sigmadsp_ops to use for this instance From 7655e32685e809fd56daf02436a0826e08368805 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:22 -0600 Subject: [PATCH 0157/1091] ASoC: amd: renoir: remove invalid kernel-doc comment make W=1 warning: sound/soc/amd/renoir/rn-pci-acp3x.c:24: warning: wrong kernel-doc identifier on line: * dmic_acpi_check = -1 - Use ACPI/DMI method to detect the DMIC hardware presence at runtime Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/rn-pci-acp3x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/renoir/rn-pci-acp3x.c b/sound/soc/amd/renoir/rn-pci-acp3x.c index 050a61fe9693..19438da5dfa5 100644 --- a/sound/soc/amd/renoir/rn-pci-acp3x.c +++ b/sound/soc/amd/renoir/rn-pci-acp3x.c @@ -20,7 +20,7 @@ static int acp_power_gating; module_param(acp_power_gating, int, 0644); MODULE_PARM_DESC(acp_power_gating, "Enable acp power gating"); -/** +/* * dmic_acpi_check = -1 - Use ACPI/DMI method to detect the DMIC hardware presence at runtime * = 0 - Skip the DMIC device creation and return probe failure * = 1 - Force DMIC support From 6a9287f5beef9787a14b0ad63ef8078d9a409f22 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:23 -0600 Subject: [PATCH 0158/1091] ASoC: fsl: fsl_ssi: fix kernel-doc warning make W=1 warning: sound/soc/fsl/fsl_ssi.c:371: warning: expecting prototype for fsl_ssi_irq(). Prototype was for fsl_ssi_isr() instead Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_ssi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_ssi.c b/sound/soc/fsl/fsl_ssi.c index 4e2ce47a7c6e..2b57b60431bb 100644 --- a/sound/soc/fsl/fsl_ssi.c +++ b/sound/soc/fsl/fsl_ssi.c @@ -363,7 +363,7 @@ static bool fsl_ssi_is_i2s_cbm_cfs(struct fsl_ssi *ssi) } /** - * fsl_ssi_irq - Interrupt handler to gather states + * fsl_ssi_isr - Interrupt handler to gather states * @irq: irq number * @dev_id: context */ From 9d02a3021833d19d3c1ddfb4f26e9f58772ce89f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:24 -0600 Subject: [PATCH 0159/1091] ASoC: fsl: fsl_easrc: fix kernel-doc warning make W=1 warning: sound/soc/fsl/fsl_easrc.c:383: warning: wrong kernel-doc identifier on line: * Scale filter coefficients (64 bits float) Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 725a5d3aaa02..60f9c0bad3e8 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -380,7 +380,7 @@ static int fsl_easrc_resampler_config(struct fsl_asrc *easrc) } /** - * Scale filter coefficients (64 bits float) + * fsl_easrc_normalize_filter - Scale filter coefficients (64 bits float) * For input float32 normalized range (1.0,-1.0) -> output int[16,24,32]: * scale it by multiplying filter coefficients by 2^31 * For input int[16, 24, 32] -> output float32 From 45468f2cfe9679eaeb7b7371b880548c5b74bede Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:25 -0600 Subject: [PATCH 0160/1091] ASoC: Intel: bytcr_wm5102: remove unused static variable MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit make W=1 warning: sound/soc/intel/boards/bytcr_wm5102.c:216:40: error: ‘byt_wm5102_dai_params’ defined but not used [-Werror=unused-const-variable=] 216 | static const struct snd_soc_pcm_stream byt_wm5102_dai_params = { | ^~~~~~~~~~~~~~~~~~~~~ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_wm5102.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index f38850eb2eaf..fd584e380340 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -213,14 +213,6 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) return 0; } -static const struct snd_soc_pcm_stream byt_wm5102_dai_params = { - .formats = SNDRV_PCM_FMTBIT_S16_LE, - .rate_min = 48000, - .rate_max = 48000, - .channels_min = 2, - .channels_max = 2, -}; - static int byt_wm5102_codec_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { From f323ecedf3221b4827c19a41a73f08a2da16ca11 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Tue, 2 Mar 2021 14:59:26 -0600 Subject: [PATCH 0161/1091] ASoC: qcom: q6dsp: fix kernel-doc warning make W=1 warning: sound/soc/qcom/qdsp6/q6afe.c:1460: warning: expecting prototype for q6afe_dam_port_prepare(). Prototype was for q6afe_cdc_dma_port_prepare() instead Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210302205926.49063-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6afe.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 6f700c311337..38f6042fe893 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -1448,7 +1448,7 @@ int q6afe_i2s_port_prepare(struct q6afe_port *port, struct q6afe_i2s_cfg *cfg) EXPORT_SYMBOL_GPL(q6afe_i2s_port_prepare); /** - * q6afe_dam_port_prepare() - Prepare dma afe port. + * q6afe_cdc_dma_port_prepare() - Prepare dma afe port. * * @port: Instance of afe port * @cfg: DMA configuration for the afe port From 4c869beda489efa3accfc6ca3177c01b97bea99e Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Tue, 2 Mar 2021 21:56:30 +0800 Subject: [PATCH 0162/1091] ASoC: codec: Omit superfluous error message in jz4760_codec_probe() The function devm_platform_ioremap_resource has already contained error message, so remove the redundant dev_err here. Signed-off-by: Tang Bin Acked-by: Paul Cercueil Link: https://lore.kernel.org/r/20210302135630.11456-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4760.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/jz4760.c b/sound/soc/codecs/jz4760.c index e8f28ccc145a..5ae0e312bcfc 100644 --- a/sound/soc/codecs/jz4760.c +++ b/sound/soc/codecs/jz4760.c @@ -841,11 +841,8 @@ static int jz4760_codec_probe(struct platform_device *pdev) codec->dev = dev; codec->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(codec->base)) { - ret = PTR_ERR(codec->base); - dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret); - return ret; - } + if (IS_ERR(codec->base)) + return PTR_ERR(codec->base); codec->regmap = devm_regmap_init(dev, NULL, codec, &jz4760_codec_regmap_config); From 5d90fef6809138f0d31271b06940950896671677 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Tue, 2 Mar 2021 11:28:17 -0300 Subject: [PATCH 0163/1091] ASoC: sgtl5000: Fix identation of .driver elements The .driver elements are not correctly idented. Fix the identation of the .driver elements. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210302142817.2141923-1-festevam@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/sgtl5000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/sgtl5000.c b/sound/soc/codecs/sgtl5000.c index 6d9bb256a2cf..97bf1f222805 100644 --- a/sound/soc/codecs/sgtl5000.c +++ b/sound/soc/codecs/sgtl5000.c @@ -1819,9 +1819,9 @@ MODULE_DEVICE_TABLE(of, sgtl5000_dt_ids); static struct i2c_driver sgtl5000_i2c_driver = { .driver = { - .name = "sgtl5000", - .of_match_table = sgtl5000_dt_ids, - }, + .name = "sgtl5000", + .of_match_table = sgtl5000_dt_ids, + }, .probe = sgtl5000_i2c_probe, .remove = sgtl5000_i2c_remove, .id_table = sgtl5000_id, From 3d01f5ee19c37c2dcaa937f060014dfd46a8ab2f Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Wed, 3 Mar 2021 06:40:41 +0000 Subject: [PATCH 0164/1091] ASoC: rt1316: Fix return value check in rt1316_sdw_probe() In case of error, the function devm_regmap_init_sdw() returns ERR_PTR() and never returns NULL. The NULL test in the return value check should be replaced with IS_ERR(). Fixes: a262057df513 ("ASoC: rt1316: Add RT1316 SDCA vendor-specific driver") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20210303064041.898281-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1316-sdw.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt1316-sdw.c b/sound/soc/codecs/rt1316-sdw.c index a6fb34a48f33..3b029c56467d 100644 --- a/sound/soc/codecs/rt1316-sdw.c +++ b/sound/soc/codecs/rt1316-sdw.c @@ -669,8 +669,8 @@ static int rt1316_sdw_probe(struct sdw_slave *slave, /* Regmap Initialization */ regmap = devm_regmap_init_sdw(slave, &rt1316_sdw_regmap); - if (!regmap) - return -EINVAL; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); return rt1316_sdw_init(&slave->dev, regmap, slave); } From a5e78cfbd50e33c19236f32693516380d1a61c34 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 3 Mar 2021 17:08:01 +0800 Subject: [PATCH 0165/1091] ASoC: codecs: fix platform_no_drv_owner.cocci warnings ./sound/soc/codecs/lpass-rx-macro.c:3588:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Reported-by: Abaci Robot Signed-off-by: Yang Li Link: https://lore.kernel.org/r/1614762481-102466-1-git-send-email-yang.lee@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 76909c50d7b9..c0f7b5ecbf9e 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -3585,7 +3585,6 @@ static const struct of_device_id rx_macro_dt_match[] = { static struct platform_driver rx_macro_driver = { .driver = { .name = "rx_macro", - .owner = THIS_MODULE, .of_match_table = rx_macro_dt_match, .suppress_bind_attrs = true, }, From 51bc908fccb1b4ed322626185a786b790d081111 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 3 Mar 2021 09:18:35 +0000 Subject: [PATCH 0166/1091] ASoC: fsl: fsl_easrc: Fix uninitialized variable st2_mem_alloc A previous cleanup commit removed the ininitialization of st2_mem_alloc. Fix this by restoring the original behaviour by initializing it to zero. Addresses-Coverity: ("Uninitialized scalar variable") Fixes: e80382fe721f ("ASoC: fsl: fsl_easrc: remove useless assignments") Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20210303091835.5024-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 725a5d3aaa02..e823c9c13764 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -710,7 +710,7 @@ static int fsl_easrc_max_ch_for_slot(struct fsl_asrc_pair *ctx, struct fsl_easrc_slot *slot) { struct fsl_easrc_ctx_priv *ctx_priv = ctx->private; - int st1_mem_alloc = 0, st2_mem_alloc; + int st1_mem_alloc = 0, st2_mem_alloc = 0; int pf_mem_alloc = 0; int max_channels = 8 - slot->num_channel; int channels = 0; From aa4890f673f9d54d3cb0ea156acfe41958ea7f08 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 8 Mar 2021 10:34:37 +0800 Subject: [PATCH 0167/1091] ASoC: wm8962: Relax bit clock divider searching With S20_3LE format case, the sysclk = rate * 384, the bclk = rate * 20 * 2, there is no proper bclk divider for 384 / 40, because current condition needs exact match. So driver fails to configure the clocking: wm8962 3-001a: Unsupported BCLK ratio 9 Fix this by relaxing bitclk divider searching, so that when no exact value can be derived from sysclk pick the closest value greater than expected bitclk. Signed-off-by: Shengjiu Wang Reviewed-by: Daniel Baluta Acked-by: Charles Keepax Link: https://lore.kernel.org/r/1615170877-25918-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8962.c | 23 +++++++++++++---------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/wm8962.c b/sound/soc/codecs/wm8962.c index ce4666a74793..34080f497584 100644 --- a/sound/soc/codecs/wm8962.c +++ b/sound/soc/codecs/wm8962.c @@ -2403,6 +2403,7 @@ static const int sysclk_rates[] = { static void wm8962_configure_bclk(struct snd_soc_component *component) { struct wm8962_priv *wm8962 = snd_soc_component_get_drvdata(component); + int best, min_diff, diff; int dspclk, i; int clocking2 = 0; int clocking4 = 0; @@ -2473,23 +2474,25 @@ static void wm8962_configure_bclk(struct snd_soc_component *component) dev_dbg(component->dev, "DSPCLK is %dHz, BCLK %d\n", dspclk, wm8962->bclk); - /* We're expecting an exact match */ + /* Search a proper bclk, not exact match. */ + best = 0; + min_diff = INT_MAX; for (i = 0; i < ARRAY_SIZE(bclk_divs); i++) { if (bclk_divs[i] < 0) continue; - if (dspclk / bclk_divs[i] == wm8962->bclk) { - dev_dbg(component->dev, "Selected BCLK_DIV %d for %dHz\n", - bclk_divs[i], wm8962->bclk); - clocking2 |= i; + diff = (dspclk / bclk_divs[i]) - wm8962->bclk; + if (diff < 0) /* Table is sorted */ break; + if (diff < min_diff) { + best = i; + min_diff = diff; } } - if (i == ARRAY_SIZE(bclk_divs)) { - dev_err(component->dev, "Unsupported BCLK ratio %d\n", - dspclk / wm8962->bclk); - return; - } + wm8962->bclk = dspclk / bclk_divs[best]; + clocking2 |= best; + dev_dbg(component->dev, "Selected BCLK_DIV %d for %dHz\n", + bclk_divs[best], wm8962->bclk); aif2 |= wm8962->bclk / wm8962->lrclk; dev_dbg(component->dev, "Selected LRCLK divisor %d for %dHz\n", From 90b2d37338791311df484d671b262b2ee392962c Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Tue, 2 Mar 2021 20:50:02 +0800 Subject: [PATCH 0168/1091] ASoC: fsl_xcvr: Use devm_platform_ioremap_resource_byname() to simplify code In this function, devm_platform_ioremap_resource_byname() should be suitable to simplify code. Signed-off-by: Tang Bin Link: https://lore.kernel.org/r/20210302125002.23900-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_xcvr.c | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_xcvr.c b/sound/soc/fsl/fsl_xcvr.c index 80416e4ed53e..6cb558165848 100644 --- a/sound/soc/fsl/fsl_xcvr.c +++ b/sound/soc/fsl/fsl_xcvr.c @@ -1130,7 +1130,7 @@ static int fsl_xcvr_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct fsl_xcvr *xcvr; - struct resource *ram_res, *regs_res, *rx_res, *tx_res; + struct resource *rx_res, *tx_res; void __iomem *regs; int ret, irq; @@ -1165,13 +1165,11 @@ static int fsl_xcvr_probe(struct platform_device *pdev) return PTR_ERR(xcvr->pll_ipg_clk); } - ram_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ram"); - xcvr->ram_addr = devm_ioremap_resource(dev, ram_res); + xcvr->ram_addr = devm_platform_ioremap_resource_byname(pdev, "ram"); if (IS_ERR(xcvr->ram_addr)) return PTR_ERR(xcvr->ram_addr); - regs_res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "regs"); - regs = devm_ioremap_resource(dev, regs_res); + regs = devm_platform_ioremap_resource_byname(pdev, "regs"); if (IS_ERR(regs)) return PTR_ERR(regs); From 20d17057f0a8c7bfecfb9e05bd5ba33a100a9a15 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Tue, 2 Mar 2021 18:30:42 +0800 Subject: [PATCH 0169/1091] ASoC: rt715-sdca: Add RT715 sdca vendor-specific driver This is initial sdca version of codec driver for rt715. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20210302103042.19528-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt715-sdca-sdw.c | 278 ++++++++ sound/soc/codecs/rt715-sdca-sdw.h | 170 +++++ sound/soc/codecs/rt715-sdca.c | 1076 +++++++++++++++++++++++++++++ sound/soc/codecs/rt715-sdca.h | 136 ++++ 6 files changed, 1669 insertions(+) create mode 100644 sound/soc/codecs/rt715-sdca-sdw.c create mode 100644 sound/soc/codecs/rt715-sdca-sdw.h create mode 100644 sound/soc/codecs/rt715-sdca.c create mode 100644 sound/soc/codecs/rt715-sdca.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 0eb9f06660e7..00dfac882f94 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -181,6 +181,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT700_SDW imply SND_SOC_RT711_SDW imply SND_SOC_RT715_SDW + imply SND_SOC_RT715_SDCA_SDW imply SND_SOC_RT1308_SDW imply SND_SOC_RT1316_SDW imply SND_SOC_SGTL5000 @@ -1256,6 +1257,12 @@ config SND_SOC_RT715_SDW select SND_SOC_RT715 select REGMAP_SOUNDWIRE +config SND_SOC_RT715_SDCA_SDW + tristate "Realtek RT715 SDCA Codec - SDW" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + #Freescale sgtl5000 codec config SND_SOC_SGTL5000 tristate "Freescale SGTL5000 CODEC" diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1585bc1d9a25..09dd9c168aac 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -198,6 +198,7 @@ snd-soc-rt5682-i2c-objs := rt5682-i2c.o snd-soc-rt700-objs := rt700.o rt700-sdw.o snd-soc-rt711-objs := rt711.o rt711-sdw.o snd-soc-rt715-objs := rt715.o rt715-sdw.o +snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o snd-soc-sgtl5000-objs := sgtl5000.o snd-soc-alc5623-objs := alc5623.o snd-soc-alc5632-objs := alc5632.o @@ -514,6 +515,7 @@ obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o +obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o obj-$(CONFIG_SND_SOC_SIGMADSP) += snd-soc-sigmadsp.o obj-$(CONFIG_SND_SOC_SIGMADSP_I2C) += snd-soc-sigmadsp-i2c.o diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c new file mode 100644 index 000000000000..bcced85876b0 --- /dev/null +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -0,0 +1,278 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt715-sdca-sdw.c -- rt715 ALSA SoC audio driver +// +// Copyright(c) 2020 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "rt715-sdca.h" +#include "rt715-sdca-sdw.h" + +static bool rt715_sdca_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201a ... 0x2027: + case 0x2029 ... 0x202a: + case 0x202d ... 0x2034: + case 0x2200 ... 0x2204: + case 0x2206 ... 0x2212: + case 0x2230 ... 0x2239: + case 0x2f5b: + case SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, + RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00): + return true; + default: + return false; + } +} + +static bool rt715_sdca_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201b: + case 0x201c: + case 0x201d: + case 0x201f: + case 0x2021: + case 0x2023: + case 0x2230: + case 0x202d ... 0x202f: /* BRA */ + case 0x2200 ... 0x2212: /* i2c debug */ + case 0x2f07: + case 0x2f1b ... 0x2f1e: + case 0x2f30 ... 0x2f34: + case 0x2f50 ... 0x2f51: + case 0x2f53 ... 0x2f59: + case 0x2f5c ... 0x2f5f: + case SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, + RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00): /* VAD Searching status */ + return true; + default: + return false; + } +} + +static bool rt715_sdca_mbq_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000: + case 0x200002b: + case 0x2000036: + case 0x2000037: + case 0x2000039: + case 0x6100000: + return true; + default: + return false; + } +} + +static bool rt715_sdca_mbq_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000: + return true; + default: + return false; + } +} + +static const struct regmap_config rt715_sdca_regmap = { + .reg_bits = 32, + .val_bits = 8, + .readable_reg = rt715_sdca_readable_register, + .volatile_reg = rt715_sdca_volatile_register, + .max_register = 0x43ffffff, + .reg_defaults = rt715_reg_defaults_sdca, + .num_reg_defaults = ARRAY_SIZE(rt715_reg_defaults_sdca), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static const struct regmap_config rt715_sdca_mbq_regmap = { + .name = "sdw-mbq", + .reg_bits = 32, + .val_bits = 16, + .readable_reg = rt715_sdca_mbq_readable_register, + .volatile_reg = rt715_sdca_mbq_volatile_register, + .max_register = 0x43ffffff, + .reg_defaults = rt715_mbq_reg_defaults_sdca, + .num_reg_defaults = ARRAY_SIZE(rt715_mbq_reg_defaults_sdca), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static int rt715_sdca_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct rt715_sdca_priv *rt715 = dev_get_drvdata(&slave->dev); + + /* Update the status */ + rt715->status = status; + + /* + * Perform initialization only if slave status is present and + * hw_init flag is false + */ + if (rt715->hw_init || rt715->status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return rt715_sdca_io_init(&slave->dev, slave); +} + +static int rt715_sdca_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval, i; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->paging_support = true; + + /* first we need to allocate memory for set bits in port lists */ + prop->source_ports = 0x50;/* BITMAP: 01010000 */ + prop->sink_ports = 0x0; /* BITMAP: 00000000 */ + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), + GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + dpn = prop->src_dpn_prop; + i = 0; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* set the timeout values */ + prop->clk_stop_timeout = 20; + + return 0; +} + +static struct sdw_slave_ops rt715_sdca_slave_ops = { + .read_prop = rt715_sdca_read_prop, + .update_status = rt715_sdca_update_status, +}; + +static int rt715_sdca_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *mbq_regmap, *regmap; + + slave->ops = &rt715_sdca_slave_ops; + + /* Regmap Initialization */ + mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt715_sdca_mbq_regmap); + if (!mbq_regmap) + return -EINVAL; + + regmap = devm_regmap_init_sdw(slave, &rt715_sdca_regmap); + if (!regmap) + return -EINVAL; + + return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave); +} + +static const struct sdw_device_id rt715_sdca_id[] = { + SDW_SLAVE_ENTRY_EXT(0x025d, 0x715, 0x3, 0x1, 0), + SDW_SLAVE_ENTRY_EXT(0x025d, 0x714, 0x3, 0x1, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, rt715_sdca_id); + +static int __maybe_unused rt715_dev_suspend(struct device *dev) +{ + struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); + + if (!rt715->hw_init) + return 0; + + regcache_cache_only(rt715->regmap, true); + regcache_mark_dirty(rt715->regmap); + regcache_cache_only(rt715->mbq_regmap, true); + regcache_mark_dirty(rt715->mbq_regmap); + + return 0; +} + +#define RT715_PROBE_TIMEOUT 5000 + +static int __maybe_unused rt715_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); + unsigned long time; + + if (!rt715->hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->enumeration_complete, + msecs_to_jiffies(RT715_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Enumeration not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(rt715->regmap, false); + regcache_sync_region(rt715->regmap, + SDW_SDCA_CTL(FUN_JACK_CODEC, RT715_SDCA_ST_EN, RT715_SDCA_ST_CTRL, + CH_00), + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, + RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00)); + regcache_cache_only(rt715->mbq_regmap, false); + regcache_sync_region(rt715->mbq_regmap, 0x2000000, 0x61020ff); + regcache_sync_region(rt715->mbq_regmap, + SDW_SDCA_CTL(FUN_JACK_CODEC, RT715_SDCA_ST_EN, RT715_SDCA_ST_CTRL, + CH_00), + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, + RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00)); + + return 0; +} + +static const struct dev_pm_ops rt715_pm = { + SET_SYSTEM_SLEEP_PM_OPS(rt715_dev_suspend, rt715_dev_resume) + SET_RUNTIME_PM_OPS(rt715_dev_suspend, rt715_dev_resume, NULL) +}; + +static struct sdw_driver rt715_sdw_driver = { + .driver = { + .name = "rt715-sdca", + .owner = THIS_MODULE, + .pm = &rt715_pm, + }, + .probe = rt715_sdca_sdw_probe, + .ops = &rt715_sdca_slave_ops, + .id_table = rt715_sdca_id, +}; +module_sdw_driver(rt715_sdw_driver); + +MODULE_DESCRIPTION("ASoC RT715 driver SDW SDCA"); +MODULE_AUTHOR("Jack Yu "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt715-sdca-sdw.h b/sound/soc/codecs/rt715-sdca-sdw.h new file mode 100644 index 000000000000..cd365bb60747 --- /dev/null +++ b/sound/soc/codecs/rt715-sdca-sdw.h @@ -0,0 +1,170 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt715-sdca-sdw.h -- RT715 ALSA SoC audio driver header + * + * Copyright(c) 2020 Realtek Semiconductor Corp. + */ + +#ifndef __RT715_SDW_SDCA_H__ +#define __RT715_SDW_SDCA_H__ + +#include + +static const struct reg_default rt715_reg_defaults_sdca[] = { + { 0x201a, 0x00 }, + { 0x201e, 0x00 }, + { 0x2020, 0x00 }, + { 0x2021, 0x00 }, + { 0x2022, 0x00 }, + { 0x2023, 0x00 }, + { 0x2024, 0x00 }, + { 0x2025, 0x01 }, + { 0x2026, 0x00 }, + { 0x2027, 0x00 }, + { 0x2029, 0x00 }, + { 0x202a, 0x00 }, + { 0x202d, 0x00 }, + { 0x202e, 0x00 }, + { 0x202f, 0x00 }, + { 0x2030, 0x00 }, + { 0x2031, 0x00 }, + { 0x2032, 0x00 }, + { 0x2033, 0x00 }, + { 0x2034, 0x00 }, + { 0x2230, 0x00 }, + { 0x2231, 0x2f }, + { 0x2232, 0x80 }, + { 0x2233, 0x00 }, + { 0x2234, 0x00 }, + { 0x2235, 0x00 }, + { 0x2236, 0x00 }, + { 0x2237, 0x00 }, + { 0x2238, 0x00 }, + { 0x2239, 0x00 }, + { 0x2f01, 0x00 }, + { 0x2f02, 0x09 }, + { 0x2f03, 0x0b }, + { 0x2f04, 0x00 }, + { 0x2f05, 0x0e }, + { 0x2f06, 0x01 }, + { 0x2f08, 0x00 }, + { 0x2f09, 0x00 }, + { 0x2f0a, 0x00 }, + { 0x2f0b, 0x00 }, + { 0x2f0c, 0x00 }, + { 0x2f0d, 0x00 }, + { 0x2f0e, 0x12 }, + { 0x2f0f, 0x00 }, + { 0x2f10, 0x00 }, + { 0x2f11, 0x00 }, + { 0x2f12, 0x00 }, + { 0x2f13, 0x00 }, + { 0x2f14, 0x00 }, + { 0x2f15, 0x00 }, + { 0x2f16, 0x00 }, + { 0x2f17, 0x00 }, + { 0x2f18, 0x00 }, + { 0x2f19, 0x03 }, + { 0x2f1a, 0x00 }, + { 0x2f1f, 0x10 }, + { 0x2f20, 0x00 }, + { 0x2f21, 0x00 }, + { 0x2f22, 0x00 }, + { 0x2f23, 0x00 }, + { 0x2f24, 0x00 }, + { 0x2f25, 0x00 }, + { 0x2f52, 0x01 }, + { 0x2f5a, 0x02 }, + { 0x2f5b, 0x05 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CX_CLK_SEL_EN, + RT715_SDCA_CX_CLK_SEL_CTRL, CH_00), 0x1 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_03), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_04), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_03), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_04), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, + RT715_SDCA_SMPU_TRIG_EN_CTRL, CH_00), 0x02 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, + RT715_SDCA_SMPU_TRIG_ST_CTRL, CH_00), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_01), 0x01 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_02), 0x01 }, +}; + +static const struct reg_default rt715_mbq_reg_defaults_sdca[] = { + { 0x200002b, 0x0420 }, + { 0x2000036, 0x0000 }, + { 0x2000037, 0x0000 }, + { 0x2000039, 0xaa81 }, + { 0x6100000, 0x0100 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_01), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_02), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_03), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_04), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_01), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_02), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_03), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_04), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_01), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_02), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_02), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_03), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_04), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_05), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_06), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_07), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_08), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_02), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_03), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_04), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_05), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_06), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_07), 0x00 }, + { SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_08), 0x00 }, +}; +#endif /* __RT715_SDW_SDCA_H__ */ diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c new file mode 100644 index 000000000000..92ad6fa408ec --- /dev/null +++ b/sound/soc/codecs/rt715-sdca.c @@ -0,0 +1,1076 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt715-sdca.c -- rt715 ALSA SoC audio driver +// +// Copyright(c) 2020 Realtek Semiconductor Corp. +// +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt715-sdca.h" + +static int rt715_sdca_index_write(struct rt715_sdca_priv *rt715, + unsigned int nid, unsigned int reg, unsigned int value) +{ + struct regmap *regmap = rt715->mbq_regmap; + unsigned int addr; + int ret; + + addr = (nid << 20) | reg; + + ret = regmap_write(regmap, addr, value); + if (ret < 0) + dev_err(&rt715->slave->dev, + "Failed to set private value: %08x <= %04x %d\n", ret, addr, + value); + + return ret; +} + +static int rt715_sdca_index_read(struct rt715_sdca_priv *rt715, + unsigned int nid, unsigned int reg, unsigned int *value) +{ + struct regmap *regmap = rt715->mbq_regmap; + unsigned int addr; + int ret; + + addr = (nid << 20) | reg; + + ret = regmap_read(regmap, addr, value); + if (ret < 0) + dev_err(&rt715->slave->dev, + "Failed to get private value: %06x => %04x ret=%d\n", + addr, *value, ret); + + return ret; +} + +static int rt715_sdca_index_update_bits(struct rt715_sdca_priv *rt715, + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) +{ + unsigned int tmp; + int ret; + + ret = rt715_sdca_index_read(rt715, nid, reg, &tmp); + if (ret < 0) + return ret; + + set_mask_bits(&tmp, mask, val); + + return rt715_sdca_index_write(rt715, nid, reg, tmp); +} + +static inline unsigned int rt715_sdca_vol_gain(unsigned int u_ctrl_val, + unsigned int vol_max, unsigned int vol_gain_sft) +{ + unsigned int val; + + if (u_ctrl_val > vol_max) + u_ctrl_val = vol_max; + val = u_ctrl_val; + u_ctrl_val = + ((abs(u_ctrl_val - vol_gain_sft) * RT715_SDCA_DB_STEP) << 8) / 1000; + if (val <= vol_gain_sft) { + u_ctrl_val = ~u_ctrl_val; + u_ctrl_val += 1; + } + u_ctrl_val &= 0xffff; + + return u_ctrl_val; +} + +static inline unsigned int rt715_sdca_boost_gain(unsigned int u_ctrl_val, + unsigned int b_max, unsigned int b_gain_sft) +{ + if (u_ctrl_val > b_max) + u_ctrl_val = b_max; + + return (u_ctrl_val * 10) << b_gain_sft; +} + +static inline unsigned int rt715_sdca_get_gain(unsigned int reg_val, + unsigned int gain_sft) +{ + unsigned int neg_flag = 0; + + if (reg_val & BIT(15)) { + reg_val = ~(reg_val - 1) & 0xffff; + neg_flag = 1; + } + reg_val *= 1000; + reg_val >>= 8; + if (neg_flag) + reg_val = gain_sft - reg_val / RT715_SDCA_DB_STEP; + else + reg_val = gain_sft + reg_val / RT715_SDCA_DB_STEP; + + return reg_val; +} + +/* SDCA Volume/Boost control */ +static int rt715_sdca_set_amp_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int gain_val, i, k_changed = 0; + int ret; + + for (i = 0; i < 2; i++) { + if (ucontrol->value.integer.value[i] != rt715->kctl_2ch_orig[i]) { + k_changed = 1; + break; + } + } + + for (i = 0; i < 2; i++) { + rt715->kctl_2ch_orig[i] = ucontrol->value.integer.value[i]; + gain_val = + rt715_sdca_vol_gain(ucontrol->value.integer.value[i], mc->max, + mc->shift); + ret = regmap_write(rt715->mbq_regmap, mc->reg + i, gain_val); + if (ret != 0) { + dev_err(component->dev, "Failed to write 0x%x=0x%x\n", + mc->reg + i, gain_val); + return ret; + } + } + + return k_changed; +} + +static int rt715_sdca_set_amp_gain_4ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct rt715_sdca_kcontrol_private *p = + (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; + unsigned int reg_base = p->reg_base, k_changed = 0; + const unsigned int gain_sft = 0x2f; + unsigned int gain_val, i; + int ret; + + for (i = 0; i < 4; i++) { + if (ucontrol->value.integer.value[i] != rt715->kctl_4ch_orig[i]) { + k_changed = 1; + break; + } + } + + for (i = 0; i < 4; i++) { + rt715->kctl_4ch_orig[i] = ucontrol->value.integer.value[i]; + gain_val = + rt715_sdca_vol_gain(ucontrol->value.integer.value[i], p->max, + gain_sft); + ret = regmap_write(rt715->mbq_regmap, reg_base + i, + gain_val); + if (ret != 0) { + dev_err(component->dev, "Failed to write 0x%x=0x%x\n", + reg_base + i, gain_val); + return ret; + } + } + + return k_changed; +} + +static int rt715_sdca_set_amp_gain_8ch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct rt715_sdca_kcontrol_private *p = + (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; + unsigned int reg_base = p->reg_base, i, k_changed = 0; + const unsigned int gain_sft = 8; + unsigned int gain_val, reg; + int ret; + + for (i = 0; i < 8; i++) { + if (ucontrol->value.integer.value[i] != rt715->kctl_8ch_orig[i]) { + k_changed = 1; + break; + } + } + + for (i = 0; i < 8; i++) { + rt715->kctl_8ch_orig[i] = ucontrol->value.integer.value[i]; + gain_val = + rt715_sdca_boost_gain(ucontrol->value.integer.value[i], p->max, + gain_sft); + reg = i < 7 ? reg_base + i : (reg_base - 1) | BIT(15); + ret = regmap_write(rt715->mbq_regmap, reg, gain_val); + if (ret != 0) { + dev_err(component->dev, "Failed to write 0x%x=0x%x\n", + reg, gain_val); + return ret; + } + } + + return k_changed; +} + +static int rt715_sdca_set_amp_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int val, i; + int ret; + + for (i = 0; i < 2; i++) { + ret = regmap_read(rt715->mbq_regmap, mc->reg + i, &val); + if (ret < 0) { + dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", + mc->reg + i, ret); + return ret; + } + ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, mc->shift); + } + + return 0; +} + +static int rt715_sdca_set_amp_gain_4ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct rt715_sdca_kcontrol_private *p = + (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; + unsigned int reg_base = p->reg_base, i; + const unsigned int gain_sft = 0x2f; + unsigned int val; + int ret; + + for (i = 0; i < 4; i++) { + ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val); + if (ret < 0) { + dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", + reg_base + i, ret); + return ret; + } + ucontrol->value.integer.value[i] = rt715_sdca_get_gain(val, gain_sft); + } + + return 0; +} + +static int rt715_sdca_set_amp_gain_8ch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct rt715_sdca_kcontrol_private *p = + (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; + unsigned int reg_base = p->reg_base; + const unsigned int gain_sft = 8; + unsigned int val_l, val_r; + unsigned int i, reg; + int ret; + + for (i = 0; i < 8; i += 2) { + ret = regmap_read(rt715->mbq_regmap, reg_base + i, &val_l); + if (ret < 0) { + dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", + reg_base + i, ret); + return ret; + } + ucontrol->value.integer.value[i] = (val_l >> gain_sft) / 10; + + reg = (i == 6) ? (reg_base - 1) | BIT(15) : reg_base + 1 + i; + ret = regmap_read(rt715->mbq_regmap, reg, &val_r); + if (ret < 0) { + dev_err(component->dev, "Failed to read 0x%x, ret=%d\n", + reg, ret); + return ret; + } + ucontrol->value.integer.value[i + 1] = (val_r >> gain_sft) / 10; + } + + return 0; +} + +static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -17625, 375, 0); +static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); + +static int rt715_sdca_get_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_sdca_kcontrol_private *p = + (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; + unsigned int reg_base = p->reg_base; + unsigned int invert = p->invert, i; + int val; + + for (i = 0; i < p->count; i += 2) { + val = snd_soc_component_read(component, reg_base + i); + if (val < 0) + return -EINVAL; + ucontrol->value.integer.value[i] = invert ? p->max - val : val; + + val = snd_soc_component_read(component, reg_base + 1 + i); + if (val < 0) + return -EINVAL; + ucontrol->value.integer.value[i + 1] = + invert ? p->max - val : val; + } + + return 0; +} + +static int rt715_sdca_put_volsw(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct rt715_sdca_kcontrol_private *p = + (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; + unsigned int val[4] = {0}, val_mask, i, k_changed = 0; + unsigned int reg = p->reg_base; + unsigned int shift = p->shift; + unsigned int max = p->max; + unsigned int mask = (1 << fls(max)) - 1; + unsigned int invert = p->invert; + int err; + + for (i = 0; i < 4; i++) { + if (ucontrol->value.integer.value[i] != rt715->kctl_switch_orig[i]) { + k_changed = 1; + break; + } + } + + for (i = 0; i < 2; i++) { + rt715->kctl_switch_orig[i * 2] = ucontrol->value.integer.value[i * 2]; + val[i * 2] = ucontrol->value.integer.value[i * 2] & mask; + if (invert) + val[i * 2] = max - val[i * 2]; + val_mask = mask << shift; + val[i * 2] <<= shift; + + rt715->kctl_switch_orig[i * 2 + 1] = + ucontrol->value.integer.value[i * 2 + 1]; + val[i * 2 + 1] = + ucontrol->value.integer.value[i * 2 + 1] & mask; + if (invert) + val[i * 2 + 1] = max - val[i * 2 + 1]; + + val[i * 2 + 1] <<= shift; + + err = snd_soc_component_update_bits(component, reg + i * 2, val_mask, + val[i * 2]); + if (err < 0) + return err; + + err = snd_soc_component_update_bits(component, reg + 1 + i * 2, + val_mask, val[i * 2 + 1]); + if (err < 0) + return err; + } + + return k_changed; +} + +static int rt715_sdca_fu_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + struct rt715_sdca_kcontrol_private *p = + (struct rt715_sdca_kcontrol_private *)kcontrol->private_value; + + if (p->max == 1) + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + else + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = p->count; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = p->max; + return 0; +} + +#define RT715_SDCA_PR_VALUE(xreg_base, xcount, xmax, xshift, xinvert) \ + ((unsigned long)&(struct rt715_sdca_kcontrol_private) \ + {.reg_base = xreg_base, .count = xcount, .max = xmax, \ + .shift = xshift, .invert = xinvert}) + +#define RT715_SDCA_FU_CTRL(xname, reg_base, xshift, xmax, xinvert, xcount) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = rt715_sdca_fu_info, \ + .get = rt715_sdca_get_volsw, \ + .put = rt715_sdca_put_volsw, \ + .private_value = RT715_SDCA_PR_VALUE(reg_base, xcount, xmax, \ + xshift, xinvert)} + +#define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ + xhandler_get, xhandler_put) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = snd_soc_info_volsw, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ + xmax, xinvert) } + +#define RT715_SDCA_EXT_TLV(xname, reg_base, xhandler_get,\ + xhandler_put, tlv_array, xcount, xmax) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = rt715_sdca_fu_info, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = RT715_SDCA_PR_VALUE(reg_base, xcount, xmax, 0, 0) } + +#define RT715_SDCA_BOOST_EXT_TLV(xname, reg_base, xhandler_get,\ + xhandler_put, tlv_array, xcount, xmax) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = rt715_sdca_fu_info, \ + .get = xhandler_get, .put = xhandler_put, \ + .private_value = RT715_SDCA_PR_VALUE(reg_base, xcount, xmax, 0, 0) } + +static const struct snd_kcontrol_new rt715_sdca_snd_controls[] = { + /* Capture switch */ + SOC_DOUBLE_R("FU0A Capture Switch", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_01), + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_02), + 0, 1, 1), + RT715_SDCA_FU_CTRL("FU02 Capture Switch", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_01), + 0, 1, 1, 4), + RT715_SDCA_FU_CTRL("FU06 Capture Switch", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_MUTE_CTRL, CH_01), + 0, 1, 1, 4), + /* Volume Control */ + SOC_DOUBLE_R_EXT_TLV("FU0A Capture Volume", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_01), + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC7_27_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_02), + 0x2f, 0x7f, 0, + rt715_sdca_set_amp_gain_get, rt715_sdca_set_amp_gain_put, + in_vol_tlv), + RT715_SDCA_EXT_TLV("FU02 Capture Volume", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC8_9_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_01), + rt715_sdca_set_amp_gain_4ch_get, + rt715_sdca_set_amp_gain_4ch_put, + in_vol_tlv, 4, 0x7f), + RT715_SDCA_EXT_TLV("FU06 Capture Volume", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_ADC10_11_VOL, + RT715_SDCA_FU_VOL_CTRL, CH_01), + rt715_sdca_set_amp_gain_4ch_get, + rt715_sdca_set_amp_gain_4ch_put, + in_vol_tlv, 4, 0x7f), + /* MIC Boost Control */ + RT715_SDCA_BOOST_EXT_TLV("FU0E Boost", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_DMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), + rt715_sdca_set_amp_gain_8ch_get, + rt715_sdca_set_amp_gain_8ch_put, + mic_vol_tlv, 8, 3), + RT715_SDCA_BOOST_EXT_TLV("FU0C Boost", + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_FU_AMIC_GAIN_EN, + RT715_SDCA_FU_DMIC_GAIN_CTRL, CH_01), + rt715_sdca_set_amp_gain_8ch_get, + rt715_sdca_set_amp_gain_8ch_put, + mic_vol_tlv, 8, 3), +}; + +static int rt715_sdca_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int val, mask_sft; + + if (strstr(ucontrol->id.name, "ADC 22 Mux")) + mask_sft = 12; + else if (strstr(ucontrol->id.name, "ADC 23 Mux")) + mask_sft = 8; + else if (strstr(ucontrol->id.name, "ADC 24 Mux")) + mask_sft = 4; + else if (strstr(ucontrol->id.name, "ADC 25 Mux")) + mask_sft = 0; + else + return -EINVAL; + + rt715_sdca_index_read(rt715, RT715_VENDOR_HDA_CTL, + RT715_HDA_LEGACY_MUX_CTL1, &val); + val = (val >> mask_sft) & 0xf; + + /* + * The first two indices of ADC Mux 24/25 are routed to the same + * hardware source. ie, ADC Mux 24 0/1 will both connect to MIC2. + * To have a unique set of inputs, we skip the index1 of the muxes. + */ + if ((strstr(ucontrol->id.name, "ADC 24 Mux") || + strstr(ucontrol->id.name, "ADC 25 Mux")) && val > 0) + val -= 1; + ucontrol->value.enumerated.item[0] = val; + + return 0; +} + +static int rt715_sdca_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, val2 = 0, change, mask_sft; + + if (item[0] >= e->items) + return -EINVAL; + + if (strstr(ucontrol->id.name, "ADC 22 Mux")) + mask_sft = 12; + else if (strstr(ucontrol->id.name, "ADC 23 Mux")) + mask_sft = 8; + else if (strstr(ucontrol->id.name, "ADC 24 Mux")) + mask_sft = 4; + else if (strstr(ucontrol->id.name, "ADC 25 Mux")) + mask_sft = 0; + else + return -EINVAL; + + /* Verb ID = 0x701h, nid = e->reg */ + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; + + rt715_sdca_index_read(rt715, RT715_VENDOR_HDA_CTL, + RT715_HDA_LEGACY_MUX_CTL1, &val2); + val2 = (val2 >> mask_sft) & 0xf; + + change = val != val2; + + if (change) + rt715_sdca_index_update_bits(rt715, RT715_VENDOR_HDA_CTL, + RT715_HDA_LEGACY_MUX_CTL1, 0xf << mask_sft, val << mask_sft); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, item[0], e, NULL); + + return change; +} + +static const char * const adc_22_23_mux_text[] = { + "MIC1", + "MIC2", + "LINE1", + "LINE2", + "DMIC1", + "DMIC2", + "DMIC3", + "DMIC4", +}; + +/* + * Due to mux design for nid 24 (MUX_IN3)/25 (MUX_IN4), connection index 0 and + * 1 will be connected to the same dmic source, therefore we skip index 1 to + * avoid misunderstanding on usage of dapm routing. + */ +static int rt715_adc_24_25_values[] = { + 0, + 2, + 3, + 4, + 5, +}; + +static const char * const adc_24_mux_text[] = { + "MIC2", + "DMIC1", + "DMIC2", + "DMIC3", + "DMIC4", +}; + +static const char * const adc_25_mux_text[] = { + "MIC1", + "DMIC1", + "DMIC2", + "DMIC3", + "DMIC4", +}; + +static SOC_ENUM_SINGLE_DECL(rt715_adc22_enum, SND_SOC_NOPM, 0, + adc_22_23_mux_text); + +static SOC_ENUM_SINGLE_DECL(rt715_adc23_enum, SND_SOC_NOPM, 0, + adc_22_23_mux_text); + +static SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc24_enum, + SND_SOC_NOPM, 0, 0xf, + adc_24_mux_text, rt715_adc_24_25_values); +static SOC_VALUE_ENUM_SINGLE_DECL(rt715_adc25_enum, + SND_SOC_NOPM, 0, 0xf, + adc_25_mux_text, rt715_adc_24_25_values); + +static const struct snd_kcontrol_new rt715_adc22_mux = + SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt715_adc22_enum, + rt715_sdca_mux_get, rt715_sdca_mux_put); + +static const struct snd_kcontrol_new rt715_adc23_mux = + SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt715_adc23_enum, + rt715_sdca_mux_get, rt715_sdca_mux_put); + +static const struct snd_kcontrol_new rt715_adc24_mux = + SOC_DAPM_ENUM_EXT("ADC 24 Mux", rt715_adc24_enum, + rt715_sdca_mux_get, rt715_sdca_mux_put); + +static const struct snd_kcontrol_new rt715_adc25_mux = + SOC_DAPM_ENUM_EXT("ADC 25 Mux", rt715_adc25_enum, + rt715_sdca_mux_get, rt715_sdca_mux_put); + +static int rt715_sdca_pde23_24_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt715->regmap, + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CREQ_POW_EN, + RT715_SDCA_REQ_POW_CTRL, + CH_00), 0x00); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt715->regmap, + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CREQ_POW_EN, + RT715_SDCA_REQ_POW_CTRL, + CH_00), 0x03); + break; + } + return 0; +} + +static const struct snd_soc_dapm_widget rt715_sdca_dapm_widgets[] = { + SND_SOC_DAPM_INPUT("DMIC1"), + SND_SOC_DAPM_INPUT("DMIC2"), + SND_SOC_DAPM_INPUT("DMIC3"), + SND_SOC_DAPM_INPUT("DMIC4"), + SND_SOC_DAPM_INPUT("MIC1"), + SND_SOC_DAPM_INPUT("MIC2"), + SND_SOC_DAPM_INPUT("LINE1"), + SND_SOC_DAPM_INPUT("LINE2"), + + SND_SOC_DAPM_SUPPLY("PDE23_24", SND_SOC_NOPM, 0, 0, + rt715_sdca_pde23_24_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_ADC("ADC 07", NULL, SND_SOC_NOPM, 4, 0), + SND_SOC_DAPM_ADC("ADC 08", NULL, SND_SOC_NOPM, 4, 0), + SND_SOC_DAPM_ADC("ADC 09", NULL, SND_SOC_NOPM, 4, 0), + SND_SOC_DAPM_ADC("ADC 27", NULL, SND_SOC_NOPM, 4, 0), + SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0, + &rt715_adc22_mux), + SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0, + &rt715_adc23_mux), + SND_SOC_DAPM_MUX("ADC 24 Mux", SND_SOC_NOPM, 0, 0, + &rt715_adc24_mux), + SND_SOC_DAPM_MUX("ADC 25 Mux", SND_SOC_NOPM, 0, 0, + &rt715_adc25_mux), + SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP6TX", "DP6 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route rt715_sdca_audio_map[] = { + {"DP6TX", NULL, "ADC 09"}, + {"DP6TX", NULL, "ADC 08"}, + {"DP4TX", NULL, "ADC 07"}, + {"DP4TX", NULL, "ADC 27"}, + {"DP4TX", NULL, "ADC 09"}, + {"DP4TX", NULL, "ADC 08"}, + + {"LINE1", NULL, "PDE23_24"}, + {"LINE2", NULL, "PDE23_24"}, + {"MIC1", NULL, "PDE23_24"}, + {"MIC2", NULL, "PDE23_24"}, + {"DMIC1", NULL, "PDE23_24"}, + {"DMIC2", NULL, "PDE23_24"}, + {"DMIC3", NULL, "PDE23_24"}, + {"DMIC4", NULL, "PDE23_24"}, + + {"ADC 09", NULL, "ADC 22 Mux"}, + {"ADC 08", NULL, "ADC 23 Mux"}, + {"ADC 07", NULL, "ADC 24 Mux"}, + {"ADC 27", NULL, "ADC 25 Mux"}, + {"ADC 22 Mux", "MIC1", "MIC1"}, + {"ADC 22 Mux", "MIC2", "MIC2"}, + {"ADC 22 Mux", "LINE1", "LINE1"}, + {"ADC 22 Mux", "LINE2", "LINE2"}, + {"ADC 22 Mux", "DMIC1", "DMIC1"}, + {"ADC 22 Mux", "DMIC2", "DMIC2"}, + {"ADC 22 Mux", "DMIC3", "DMIC3"}, + {"ADC 22 Mux", "DMIC4", "DMIC4"}, + {"ADC 23 Mux", "MIC1", "MIC1"}, + {"ADC 23 Mux", "MIC2", "MIC2"}, + {"ADC 23 Mux", "LINE1", "LINE1"}, + {"ADC 23 Mux", "LINE2", "LINE2"}, + {"ADC 23 Mux", "DMIC1", "DMIC1"}, + {"ADC 23 Mux", "DMIC2", "DMIC2"}, + {"ADC 23 Mux", "DMIC3", "DMIC3"}, + {"ADC 23 Mux", "DMIC4", "DMIC4"}, + {"ADC 24 Mux", "MIC2", "MIC2"}, + {"ADC 24 Mux", "DMIC1", "DMIC1"}, + {"ADC 24 Mux", "DMIC2", "DMIC2"}, + {"ADC 24 Mux", "DMIC3", "DMIC3"}, + {"ADC 24 Mux", "DMIC4", "DMIC4"}, + {"ADC 25 Mux", "MIC1", "MIC1"}, + {"ADC 25 Mux", "DMIC1", "DMIC1"}, + {"ADC 25 Mux", "DMIC2", "DMIC2"}, + {"ADC 25 Mux", "DMIC3", "DMIC3"}, + {"ADC 25 Mux", "DMIC4", "DMIC4"}, +}; + +static const struct snd_soc_component_driver soc_codec_dev_rt715_sdca = { + .controls = rt715_sdca_snd_controls, + .num_controls = ARRAY_SIZE(rt715_sdca_snd_controls), + .dapm_widgets = rt715_sdca_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt715_sdca_dapm_widgets), + .dapm_routes = rt715_sdca_audio_map, + .num_dapm_routes = ARRAY_SIZE(rt715_sdca_audio_map), +}; + +static int rt715_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + struct rt715_sdw_stream_data *stream; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void rt715_sdca_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) + +{ + struct rt715_sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + if (!stream) + return; + + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int rt715_sdca_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct rt715_sdw_stream_data *stream; + int retval, port, num_channels; + unsigned int val; + + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -EINVAL; + + if (!rt715->slave) + return -EINVAL; + + switch (dai->id) { + case RT715_AIF1: + direction = SDW_DATA_DIR_TX; + port = 6; + rt715_sdca_index_write(rt715, RT715_VENDOR_REG, RT715_SDW_INPUT_SEL, + 0xa500); + break; + case RT715_AIF2: + direction = SDW_DATA_DIR_TX; + port = 4; + rt715_sdca_index_write(rt715, RT715_VENDOR_REG, RT715_SDW_INPUT_SEL, + 0xaf00); + break; + default: + dev_err(component->dev, "Invalid DAI id %d\n", dai->id); + return -EINVAL; + } + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + num_channels = params_channels(params); + port_config.ch_mask = GENMASK(num_channels - 1, 0); + port_config.num = port; + + retval = sdw_stream_add_slave(rt715->slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (retval) { + dev_err(component->dev, "Unable to configure port, retval:%d\n", + retval); + return retval; + } + + switch (params_rate(params)) { + case 8000: + val = 0x1; + break; + case 11025: + val = 0x2; + break; + case 12000: + val = 0x3; + break; + case 16000: + val = 0x4; + break; + case 22050: + val = 0x5; + break; + case 24000: + val = 0x6; + break; + case 32000: + val = 0x7; + break; + case 44100: + val = 0x8; + break; + case 48000: + val = 0x9; + break; + case 88200: + val = 0xa; + break; + case 96000: + val = 0xb; + break; + case 176400: + val = 0xc; + break; + case 192000: + val = 0xd; + break; + case 384000: + val = 0xe; + break; + case 768000: + val = 0xf; + break; + default: + dev_err(component->dev, "Unsupported sample rate %d\n", + params_rate(params)); + return -EINVAL; + } + + regmap_write(rt715->regmap, + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CS_FREQ_IND_EN, + RT715_SDCA_FREQ_IND_CTRL, CH_00), val); + + return 0; +} + +static int rt715_sdca_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt715_sdca_priv *rt715 = snd_soc_component_get_drvdata(component); + struct rt715_sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt715->slave) + return -EINVAL; + + sdw_stream_remove_slave(rt715->slave, stream->sdw_stream); + return 0; +} + +#define RT715_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000) +#define RT715_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) + +static struct snd_soc_dai_ops rt715_sdca_ops = { + .hw_params = rt715_sdca_pcm_hw_params, + .hw_free = rt715_sdca_pcm_hw_free, + .set_sdw_stream = rt715_sdca_set_sdw_stream, + .shutdown = rt715_sdca_shutdown, +}; + +static struct snd_soc_dai_driver rt715_sdca_dai[] = { + { + .name = "rt715-aif1", + .id = RT715_AIF1, + .capture = { + .stream_name = "DP6 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT715_STEREO_RATES, + .formats = RT715_FORMATS, + }, + .ops = &rt715_sdca_ops, + }, + { + .name = "rt715-aif2", + .id = RT715_AIF2, + .capture = { + .stream_name = "DP4 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT715_STEREO_RATES, + .formats = RT715_FORMATS, + }, + .ops = &rt715_sdca_ops, + }, +}; + +/* Bus clock frequency */ +#define RT715_CLK_FREQ_9600000HZ 9600000 +#define RT715_CLK_FREQ_12000000HZ 12000000 +#define RT715_CLK_FREQ_6000000HZ 6000000 +#define RT715_CLK_FREQ_4800000HZ 4800000 +#define RT715_CLK_FREQ_2400000HZ 2400000 +#define RT715_CLK_FREQ_12288000HZ 12288000 + +int rt715_sdca_init(struct device *dev, struct regmap *mbq_regmap, + struct regmap *regmap, struct sdw_slave *slave) +{ + struct rt715_sdca_priv *rt715; + int ret; + + rt715 = devm_kzalloc(dev, sizeof(*rt715), GFP_KERNEL); + if (!rt715) + return -ENOMEM; + + dev_set_drvdata(dev, rt715); + rt715->slave = slave; + rt715->regmap = regmap; + rt715->mbq_regmap = mbq_regmap; + rt715->hw_sdw_ver = slave->id.sdw_version; + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt715->hw_init = false; + rt715->first_init = false; + + ret = devm_snd_soc_register_component(dev, + &soc_codec_dev_rt715_sdca, + rt715_sdca_dai, + ARRAY_SIZE(rt715_sdca_dai)); + + return ret; +} + +int rt715_sdca_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt715_sdca_priv *rt715 = dev_get_drvdata(dev); + unsigned int hw_ver; + + if (rt715->hw_init) + return 0; + + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + if (!rt715->first_init) { + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + + rt715->first_init = true; + } + + pm_runtime_get_noresume(&slave->dev); + + rt715_sdca_index_read(rt715, RT715_VENDOR_REG, + RT715_PRODUCT_NUM, &hw_ver); + hw_ver = hw_ver & 0x000f; + + /* set clock selector = external */ + regmap_write(rt715->regmap, + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_CX_CLK_SEL_EN, + RT715_SDCA_CX_CLK_SEL_CTRL, CH_00), 0x1); + /* set GPIO_4/5/6 to be 3rd/4th DMIC usage */ + if (hw_ver == 0x0) + rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, + RT715_AD_FUNC_EN, 0x54, 0x54); + else if (hw_ver == 0x1) { + rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, + RT715_AD_FUNC_EN, 0x55, 0x55); + rt715_sdca_index_update_bits(rt715, RT715_VENDOR_REG, + RT715_REV_1, 0x40, 0x40); + } + /* trigger mode = VAD enable */ + regmap_write(rt715->regmap, + SDW_SDCA_CTL(FUN_MIC_ARRAY, RT715_SDCA_SMPU_TRIG_ST_EN, + RT715_SDCA_SMPU_TRIG_EN_CTRL, CH_00), 0x2); + /* SMPU-1 interrupt enable mask */ + regmap_update_bits(rt715->regmap, RT715_INT_MASK, 0x1, 0x1); + + /* Mark Slave initialization complete */ + rt715->hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + return 0; +} + +MODULE_DESCRIPTION("ASoC rt715 driver SDW SDCA"); +MODULE_AUTHOR("Jack Yu "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt715-sdca.h b/sound/soc/codecs/rt715-sdca.h new file mode 100644 index 000000000000..85ce4d95e5eb --- /dev/null +++ b/sound/soc/codecs/rt715-sdca.h @@ -0,0 +1,136 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt715-sdca.h -- RT715 ALSA SoC audio driver header + * + * Copyright(c) 2020 Realtek Semiconductor Corp. + */ + +#ifndef __RT715_SDCA_H__ +#define __RT715_SDCA_H__ + +#include +#include +#include +#include +#include +#include + +struct rt715_sdca_priv { + struct regmap *regmap; + struct regmap *mbq_regmap; + struct snd_soc_codec *codec; + struct sdw_slave *slave; + struct delayed_work adc_mute_work; + int dbg_nid; + int dbg_vid; + int dbg_payload; + enum sdw_slave_status status; + struct sdw_bus_params params; + bool hw_init; + bool first_init; + int l_is_unmute; + int r_is_unmute; + int hw_sdw_ver; + int kctl_switch_orig[4]; + int kctl_2ch_orig[2]; + int kctl_4ch_orig[4]; + int kctl_8ch_orig[8]; +}; + +struct rt715_sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +struct rt715_sdca_kcontrol_private { + unsigned int reg_base; + unsigned int count; + unsigned int max; + unsigned int shift; + unsigned int invert; +}; + +/* MIPI Register */ +#define RT715_INT_CTRL 0x005a +#define RT715_INT_MASK 0x005e + +/* NID */ +#define RT715_AUDIO_FUNCTION_GROUP 0x01 +#define RT715_MIC_ADC 0x07 +#define RT715_LINE_ADC 0x08 +#define RT715_MIX_ADC 0x09 +#define RT715_DMIC1 0x12 +#define RT715_DMIC2 0x13 +#define RT715_MIC1 0x18 +#define RT715_MIC2 0x19 +#define RT715_LINE1 0x1a +#define RT715_LINE2 0x1b +#define RT715_DMIC3 0x1d +#define RT715_DMIC4 0x29 +#define RT715_VENDOR_REG 0x20 +#define RT715_MUX_IN1 0x22 +#define RT715_MUX_IN2 0x23 +#define RT715_MUX_IN3 0x24 +#define RT715_MUX_IN4 0x25 +#define RT715_MIX_ADC2 0x27 +#define RT715_INLINE_CMD 0x55 +#define RT715_VENDOR_HDA_CTL 0x61 + +/* Index (NID:20h) */ +#define RT715_PRODUCT_NUM 0x0 +#define RT715_IRQ_CTRL 0x2b +#define RT715_AD_FUNC_EN 0x36 +#define RT715_REV_1 0x37 +#define RT715_SDW_INPUT_SEL 0x39 +#define RT715_EXT_DMIC_CLK_CTRL2 0x54 + +/* Index (NID:61h) */ +#define RT715_HDA_LEGACY_MUX_CTL1 0x00 + +/* SDCA (Function) */ +#define FUN_JACK_CODEC 0x01 +#define FUN_MIC_ARRAY 0x02 +#define FUN_HID 0x03 +/* SDCA (Entity) */ +#define RT715_SDCA_ST_EN 0x00 +#define RT715_SDCA_CS_FREQ_IND_EN 0x01 +#define RT715_SDCA_FU_ADC8_9_VOL 0x02 +#define RT715_SDCA_SMPU_TRIG_ST_EN 0x05 +#define RT715_SDCA_FU_ADC10_11_VOL 0x06 +#define RT715_SDCA_FU_ADC7_27_VOL 0x0a +#define RT715_SDCA_FU_AMIC_GAIN_EN 0x0c +#define RT715_SDCA_FU_DMIC_GAIN_EN 0x0e +#define RT715_SDCA_CX_CLK_SEL_EN 0x10 +#define RT715_SDCA_CREQ_POW_EN 0x18 +/* SDCA (Control) */ +#define RT715_SDCA_ST_CTRL 0x00 +#define RT715_SDCA_CX_CLK_SEL_CTRL 0x01 +#define RT715_SDCA_REQ_POW_CTRL 0x01 +#define RT715_SDCA_FU_MUTE_CTRL 0x01 +#define RT715_SDCA_FU_VOL_CTRL 0x02 +#define RT715_SDCA_FU_DMIC_GAIN_CTRL 0x0b +#define RT715_SDCA_FREQ_IND_CTRL 0x10 +#define RT715_SDCA_SMPU_TRIG_EN_CTRL 0x10 +#define RT715_SDCA_SMPU_TRIG_ST_CTRL 0x11 +/* SDCA (Channel) */ +#define CH_00 0x00 +#define CH_01 0x01 +#define CH_02 0x02 +#define CH_03 0x03 +#define CH_04 0x04 +#define CH_05 0x05 +#define CH_06 0x06 +#define CH_07 0x07 +#define CH_08 0x08 + +#define RT715_SDCA_DB_STEP 375 + +enum { + RT715_AIF1, + RT715_AIF2, +}; + +int rt715_sdca_io_init(struct device *dev, struct sdw_slave *slave); +int rt715_sdca_init(struct device *dev, struct regmap *mbq_regmap, + struct regmap *regmap, struct sdw_slave *slave); + +#endif /* __RT715_SDCA_H__ */ From cc2d7429d65c7ea9dc2f84694f47b030248d0d89 Mon Sep 17 00:00:00 2001 From: Tang Bin Date: Sun, 7 Mar 2021 15:21:33 +0800 Subject: [PATCH 0170/1091] ASoC: codecs/jz4770: Remove superfluous error message The function devm_platform_ioremap_resource has already contained error message if failed, so remove superfluous dev_err here. Signed-off-by: Zhang Shengju Signed-off-by: Tang Bin Acked-by: Paul Cercueil Link: https://lore.kernel.org/r/20210307072133.10832-1-tangbin@cmss.chinamobile.com Signed-off-by: Mark Brown --- sound/soc/codecs/jz4770.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/jz4770.c b/sound/soc/codecs/jz4770.c index c9fe7f72bfcb..6b60120f59a6 100644 --- a/sound/soc/codecs/jz4770.c +++ b/sound/soc/codecs/jz4770.c @@ -893,11 +893,8 @@ static int jz4770_codec_probe(struct platform_device *pdev) codec->dev = dev; codec->base = devm_platform_ioremap_resource(pdev, 0); - if (IS_ERR(codec->base)) { - ret = PTR_ERR(codec->base); - dev_err(dev, "Failed to ioremap mmio memory: %d\n", ret); - return ret; - } + if (IS_ERR(codec->base)) + return PTR_ERR(codec->base); codec->regmap = devm_regmap_init(dev, NULL, codec, &jz4770_codec_regmap_config); From 452801cabc0a0f0cb742e98617d3f0e8a2b11295 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 00:02:22 +0100 Subject: [PATCH 0171/1091] ASoC: rt5645: Move rt5645_platform_data to sound/soc/codecs/rt5645.c sound/soc/codecs/rt5645.c is the only user of the rt5645_platform_data, move its definition to sound/soc/codecs/rt5645.c and remove the now empty include/sound/rt5645.h file. Note since the DMI quirk mechanism uses pointers to the rt5645_platform_data struct we can NOT simply add its members to the rt5645_priv struct and completely remove the struct. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210306230223.516566-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- include/sound/rt5645.h | 32 -------------------------------- sound/soc/codecs/rt5645.c | 23 ++++++++++++++++++++++- sound/soc/codecs/rt5645.h | 2 -- 3 files changed, 22 insertions(+), 35 deletions(-) delete mode 100644 include/sound/rt5645.h diff --git a/include/sound/rt5645.h b/include/sound/rt5645.h deleted file mode 100644 index 710c95be5509..000000000000 --- a/include/sound/rt5645.h +++ /dev/null @@ -1,32 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ -/* - * linux/sound/rt5645.h -- Platform data for RT5645 - * - * Copyright 2013 Realtek Microelectronics - */ - -#ifndef __LINUX_SND_RT5645_H -#define __LINUX_SND_RT5645_H - -struct rt5645_platform_data { - /* IN2 can optionally be differential */ - bool in2_diff; - - unsigned int dmic1_data_pin; - /* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */ - unsigned int dmic2_data_pin; - /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ - - unsigned int jd_mode; - /* Use level triggered irq */ - bool level_trigger_irq; - /* Invert JD1_1 status polarity */ - bool inv_jd1_1; - /* Invert HP detect status polarity */ - bool inv_hp_pol; - - /* Value to asign to snd_soc_card.long_name */ - const char *long_name; -}; - -#endif diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index c39095fa14ce..3849a9987541 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -411,6 +411,27 @@ static const char *const rt5645_supply_names[] = { "cpvdd", }; +struct rt5645_platform_data { + /* IN2 can optionally be differential */ + bool in2_diff; + + unsigned int dmic1_data_pin; + /* 0 = IN2N; 1 = GPIO5; 2 = GPIO11 */ + unsigned int dmic2_data_pin; + /* 0 = IN2P; 1 = GPIO6; 2 = GPIO10; 3 = GPIO12 */ + + unsigned int jd_mode; + /* Use level triggered irq */ + bool level_trigger_irq; + /* Invert JD1_1 status polarity */ + bool inv_jd1_1; + /* Invert HP detect status polarity */ + bool inv_hp_pol; + + /* Value to assign to snd_soc_card.long_name */ + const char *long_name; +}; + struct rt5645_priv { struct snd_soc_component *component; struct rt5645_platform_data pdata; @@ -3834,7 +3855,7 @@ static int rt5645_parse_dt(struct rt5645_priv *rt5645, struct device *dev) static int rt5645_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { - struct rt5645_platform_data *pdata = dev_get_platdata(&i2c->dev); + struct rt5645_platform_data *pdata = NULL; const struct dmi_system_id *dmi_data; struct rt5645_priv *rt5645; int ret, i; diff --git a/sound/soc/codecs/rt5645.h b/sound/soc/codecs/rt5645.h index e2d72ae17484..ac3de6f3bc2f 100644 --- a/sound/soc/codecs/rt5645.h +++ b/sound/soc/codecs/rt5645.h @@ -9,8 +9,6 @@ #ifndef __RT5645_H__ #define __RT5645_H__ -#include - /* Info */ #define RT5645_RESET 0x00 #define RT5645_VENDOR_ID 0xfd From 3f004d2dc118e5e5d0162a077618aaa4bff9e555 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 00:02:23 +0100 Subject: [PATCH 0172/1091] ASoC: rt5645: The ALC3270 variant does not have a headset-mic pin The Asus T100HA and T101HA 2-in-1s use a rt5645 family codec and always report that a headset (rather then headphones) are plugged in even when regular headphones are plugged in. And when a headset is used, then the headset-microphone does not work. According to RealTek the ALC3270 variant used in these devices does not support headsets only headphones. Since the ALC3270 is a budget version of the regular ALC5645 codec, I assume that it is using a package with less pins and the headset-mic pin is simply not connected. Detect if the codec is an ALC3270 based on the ACPI HID and if it is an ALC3270 then always report SND_JACK_MICROPHONE as false, so that userspace will not try to use the not-connected headset-mic. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210306230223.516566-2-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5645.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt5645.c b/sound/soc/codecs/rt5645.c index 3849a9987541..9408ee63cb26 100644 --- a/sound/soc/codecs/rt5645.c +++ b/sound/soc/codecs/rt5645.c @@ -430,6 +430,9 @@ struct rt5645_platform_data { /* Value to assign to snd_soc_card.long_name */ const char *long_name; + + /* Some (package) variants have the headset-mic pin not-connected */ + bool no_headset_mic; }; struct rt5645_priv { @@ -3180,7 +3183,7 @@ static int rt5645_jack_detect(struct snd_soc_component *component, int jack_inse val &= 0x7; dev_dbg(component->dev, "val = %d\n", val); - if (val == 1 || val == 2) { + if ((val == 1 || val == 2) && !rt5645->pdata.no_headset_mic) { rt5645->jack_type = SND_JACK_HEADSET; if (rt5645->en_button_func) { rt5645_enable_push_button_irq(component, true); @@ -3893,9 +3896,16 @@ static int rt5645_i2c_probe(struct i2c_client *i2c, rt5645->pdata.dmic2_data_pin = QUIRK_DMIC2_DATA_PIN(quirk); } - if (cht_rt5645_gpios && has_acpi_companion(&i2c->dev)) - if (devm_acpi_dev_add_driver_gpios(&i2c->dev, cht_rt5645_gpios)) - dev_dbg(&i2c->dev, "Failed to add driver gpios\n"); + if (has_acpi_companion(&i2c->dev)) { + if (cht_rt5645_gpios) { + if (devm_acpi_dev_add_driver_gpios(&i2c->dev, cht_rt5645_gpios)) + dev_dbg(&i2c->dev, "Failed to add driver gpios\n"); + } + + /* The ALC3270 package has the headset-mic pin not-connected */ + if (acpi_dev_hid_uid_match(ACPI_COMPANION(&i2c->dev), "10EC3270", NULL)) + rt5645->pdata.no_headset_mic = true; + } rt5645->gpiod_hp_det = devm_gpiod_get_optional(&i2c->dev, "hp-detect", GPIOD_IN); From 7ad4d237e7c4a5dcc71cf438f646744b4484f1da Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 2 Mar 2021 17:15:06 +0800 Subject: [PATCH 0173/1091] ASoC: rt711-sdca: Add RT711 SDCA vendor-specific driver This is the initial codec driver for rt711 SDCA version. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210302091506.18745-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt711-sdca-sdw.c | 425 ++++++++ sound/soc/codecs/rt711-sdca-sdw.h | 99 ++ sound/soc/codecs/rt711-sdca.c | 1492 +++++++++++++++++++++++++++++ sound/soc/codecs/rt711-sdca.h | 238 +++++ 6 files changed, 2263 insertions(+) create mode 100644 sound/soc/codecs/rt711-sdca-sdw.c create mode 100644 sound/soc/codecs/rt711-sdca-sdw.h create mode 100644 sound/soc/codecs/rt711-sdca.c create mode 100644 sound/soc/codecs/rt711-sdca.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 00dfac882f94..6ce74c99a305 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -180,6 +180,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT5682_SDW imply SND_SOC_RT700_SDW imply SND_SOC_RT711_SDW + imply SND_SOC_RT711_SDCA_SDW imply SND_SOC_RT715_SDW imply SND_SOC_RT715_SDCA_SDW imply SND_SOC_RT1308_SDW @@ -1248,6 +1249,12 @@ config SND_SOC_RT711_SDW select SND_SOC_RT711 select REGMAP_SOUNDWIRE +config SND_SOC_RT711_SDCA_SDW + tristate "Realtek RT711 SDCA Codec - SDW" + depends on SOUNDWIRE + select REGMAP_SOUNDWIRE + select REGMAP_SOUNDWIRE_MBQ + config SND_SOC_RT715 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 09dd9c168aac..dcc2f757bb82 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -197,6 +197,7 @@ snd-soc-rt5682-sdw-objs := rt5682-sdw.o snd-soc-rt5682-i2c-objs := rt5682-i2c.o snd-soc-rt700-objs := rt700.o rt700-sdw.o snd-soc-rt711-objs := rt711.o rt711-sdw.o +snd-soc-rt711-sdca-objs := rt711-sdca.o rt711-sdca-sdw.o snd-soc-rt715-objs := rt715.o rt715-sdw.o snd-soc-rt715-sdca-objs := rt715-sdca.o rt715-sdca-sdw.o snd-soc-sgtl5000-objs := sgtl5000.o @@ -514,6 +515,7 @@ obj-$(CONFIG_SND_SOC_RT5682_I2C) += snd-soc-rt5682-i2c.o obj-$(CONFIG_SND_SOC_RT5682_SDW) += snd-soc-rt5682-sdw.o obj-$(CONFIG_SND_SOC_RT700) += snd-soc-rt700.o obj-$(CONFIG_SND_SOC_RT711) += snd-soc-rt711.o +obj-$(CONFIG_SND_SOC_RT711_SDCA_SDW) += snd-soc-rt711-sdca.o obj-$(CONFIG_SND_SOC_RT715) += snd-soc-rt715.o obj-$(CONFIG_SND_SOC_RT715_SDCA_SDW) += snd-soc-rt715-sdca.o obj-$(CONFIG_SND_SOC_SGTL5000) += snd-soc-sgtl5000.o diff --git a/sound/soc/codecs/rt711-sdca-sdw.c b/sound/soc/codecs/rt711-sdca-sdw.c new file mode 100644 index 000000000000..9685c8905468 --- /dev/null +++ b/sound/soc/codecs/rt711-sdca-sdw.c @@ -0,0 +1,425 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt711-sdw-sdca.c -- rt711 SDCA ALSA SoC audio driver +// +// Copyright(c) 2021 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include + +#include "rt711-sdca.h" +#include "rt711-sdca-sdw.h" + +static bool rt711_sdca_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201a ... 0x2027: + case 0x2029 ... 0x202a: + case 0x202d ... 0x2034: + case 0x2200 ... 0x2204: + case 0x2206 ... 0x2212: + case 0x2220 ... 0x2223: + case 0x2230 ... 0x2239: + case 0x2f01 ... 0x2f0f: + case 0x2f30 ... 0x2f36: + case 0x2f50 ... 0x2f5a: + case 0x2f60: + case 0x3200 ... 0x3212: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_SELECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... + SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case RT711_BUF_ADDR_HID1 ... RT711_BUF_ADDR_HID2: + return true; + default: + return false; + } +} + +static bool rt711_sdca_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x201b: + case 0x201c: + case 0x201d: + case 0x201f: + case 0x2021: + case 0x2023: + case 0x2230: + case 0x202d ... 0x202f: /* BRA */ + case 0x2200 ... 0x2212: /* i2c debug */ + case RT711_RC_CAL_STATUS: + case SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0): + case SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_CURRENT_OWNER, 0) ... + SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_LENGTH, 0): + case RT711_BUF_ADDR_HID1 ... RT711_BUF_ADDR_HID2: + return true; + default: + return false; + } +} + +static bool rt711_sdca_mbq_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000 ... 0x20000ff: + case 0x5600000 ... 0x56000ff: + case 0x5700000 ... 0x57000ff: + case 0x5800000 ... 0x58000ff: + case 0x5900000 ... 0x59000ff: + case 0x5b00000 ... 0x5b000ff: + case 0x5f00000 ... 0x5f000ff: + case 0x6100000 ... 0x61000ff: + return true; + default: + return false; + } +} + +static bool rt711_sdca_mbq_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case 0x2000000: + case 0x200001a: + case 0x2000046: + case 0x2000080: + case 0x2000081: + case 0x2000083: + case 0x5800000: + case 0x5800001: + case 0x5f00001: + case 0x6100008: + return true; + default: + return false; + } +} + +static const struct regmap_config rt711_sdca_regmap = { + .reg_bits = 32, + .val_bits = 8, + .readable_reg = rt711_sdca_readable_register, + .volatile_reg = rt711_sdca_volatile_register, + .max_register = 0x44ffffff, + .reg_defaults = rt711_sdca_reg_defaults, + .num_reg_defaults = ARRAY_SIZE(rt711_sdca_reg_defaults), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static const struct regmap_config rt711_sdca_mbq_regmap = { + .name = "sdw-mbq", + .reg_bits = 32, + .val_bits = 16, + .readable_reg = rt711_sdca_mbq_readable_register, + .volatile_reg = rt711_sdca_mbq_volatile_register, + .max_register = 0x40800f12, + .reg_defaults = rt711_sdca_mbq_defaults, + .num_reg_defaults = ARRAY_SIZE(rt711_sdca_mbq_defaults), + .cache_type = REGCACHE_RBTREE, + .use_single_read = true, + .use_single_write = true, +}; + +static int rt711_sdca_update_status(struct sdw_slave *slave, + enum sdw_slave_status status) +{ + struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev); + + /* Update the status */ + rt711->status = status; + + if (status == SDW_SLAVE_UNATTACHED) + rt711->hw_init = false; + + if (status == SDW_SLAVE_ATTACHED) { + if (rt711->hs_jack) { + /* + * Due to the SCP_SDCA_INTMASK will be cleared by any reset, and then + * if the device attached again, we will need to set the setting back. + * It could avoid losing the jack detection interrupt. + * This also could sync with the cache value as the rt711_sdca_jack_init set. + */ + sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK1, + SDW_SCP_SDCA_INTMASK_SDCA_0); + sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK2, + SDW_SCP_SDCA_INTMASK_SDCA_8); + } + } + + /* + * Perform initialization only if slave status is present and + * hw_init flag is false + */ + if (rt711->hw_init || rt711->status != SDW_SLAVE_ATTACHED) + return 0; + + /* perform I/O transfers required for Slave initialization */ + return rt711_sdca_io_init(&slave->dev, slave); +} + +static int rt711_sdca_read_prop(struct sdw_slave *slave) +{ + struct sdw_slave_prop *prop = &slave->prop; + int nval; + int i, j; + u32 bit; + unsigned long addr; + struct sdw_dpn_prop *dpn; + + prop->scp_int1_mask = SDW_SCP_INT1_BUS_CLASH | SDW_SCP_INT1_PARITY; + prop->quirks = SDW_SLAVE_QUIRKS_INVALID_INITIAL_PARITY; + prop->is_sdca = true; + + prop->paging_support = true; + + /* first we need to allocate memory for set bits in port lists */ + prop->source_ports = 0x14; /* BITMAP: 00010100 */ + prop->sink_ports = 0x8; /* BITMAP: 00001000 */ + + nval = hweight32(prop->source_ports); + prop->src_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->src_dpn_prop), GFP_KERNEL); + if (!prop->src_dpn_prop) + return -ENOMEM; + + i = 0; + dpn = prop->src_dpn_prop; + addr = prop->source_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[i].num = bit; + dpn[i].type = SDW_DPN_FULL; + dpn[i].simple_ch_prep_sm = true; + dpn[i].ch_prep_timeout = 10; + i++; + } + + /* do this again for sink now */ + nval = hweight32(prop->sink_ports); + prop->sink_dpn_prop = devm_kcalloc(&slave->dev, nval, + sizeof(*prop->sink_dpn_prop), GFP_KERNEL); + if (!prop->sink_dpn_prop) + return -ENOMEM; + + j = 0; + dpn = prop->sink_dpn_prop; + addr = prop->sink_ports; + for_each_set_bit(bit, &addr, 32) { + dpn[j].num = bit; + dpn[j].type = SDW_DPN_FULL; + dpn[j].simple_ch_prep_sm = true; + dpn[j].ch_prep_timeout = 10; + j++; + } + + /* set the timeout values */ + prop->clk_stop_timeout = 20; + + /* wake-up event */ + prop->wake_capable = 1; + + return 0; +} + +static int rt711_sdca_interrupt_callback(struct sdw_slave *slave, + struct sdw_slave_intr_status *status) +{ + struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev); + int ret, stat; + int count = 0, retry = 3; + unsigned int sdca_cascade, scp_sdca_stat1, scp_sdca_stat2 = 0; + + dev_dbg(&slave->dev, + "%s control_port_stat=%x, sdca_cascade=%x", __func__, + status->control_port, status->sdca_cascade); + + if (cancel_delayed_work_sync(&rt711->jack_detect_work)) { + dev_warn(&slave->dev, "%s the pending delayed_work was cancelled", __func__); + /* avoid the HID owner doesn't change to device */ + if (rt711->scp_sdca_stat2) + scp_sdca_stat2 = rt711->scp_sdca_stat2; + } + + ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + rt711->scp_sdca_stat1 = ret; + ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT2); + if (ret < 0) + goto io_error; + rt711->scp_sdca_stat2 = ret; + if (scp_sdca_stat2) + rt711->scp_sdca_stat2 |= scp_sdca_stat2; + + do { + /* clear flag */ + ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + if (ret & SDW_SCP_SDCA_INTMASK_SDCA_0) { + ret = sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INT1, + SDW_SCP_SDCA_INTMASK_SDCA_0); + if (ret < 0) + goto io_error; + } + ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT2); + if (ret < 0) + goto io_error; + if (ret & SDW_SCP_SDCA_INTMASK_SDCA_8) { + ret = sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INT2, + SDW_SCP_SDCA_INTMASK_SDCA_8); + if (ret < 0) + goto io_error; + } + + /* check if flag clear or not */ + ret = sdw_read_no_pm(rt711->slave, SDW_DP0_INT); + if (ret < 0) + goto io_error; + sdca_cascade = ret & SDW_DP0_SDCA_CASCADE; + + ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT1); + if (ret < 0) + goto io_error; + scp_sdca_stat1 = ret & SDW_SCP_SDCA_INTMASK_SDCA_0; + + ret = sdw_read_no_pm(rt711->slave, SDW_SCP_SDCA_INT2); + if (ret < 0) + goto io_error; + scp_sdca_stat2 = ret & SDW_SCP_SDCA_INTMASK_SDCA_8; + + stat = scp_sdca_stat1 || scp_sdca_stat2 || sdca_cascade; + + count++; + } while (stat != 0 && count < retry); + + if (stat) + dev_warn(&slave->dev, + "%s scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__, + rt711->scp_sdca_stat1, rt711->scp_sdca_stat2); + + if (status->sdca_cascade) + mod_delayed_work(system_power_efficient_wq, + &rt711->jack_detect_work, msecs_to_jiffies(30)); + + return 0; + +io_error: + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); + return ret; +} + +static struct sdw_slave_ops rt711_sdca_slave_ops = { + .read_prop = rt711_sdca_read_prop, + .interrupt_callback = rt711_sdca_interrupt_callback, + .update_status = rt711_sdca_update_status, +}; + +static int rt711_sdca_sdw_probe(struct sdw_slave *slave, + const struct sdw_device_id *id) +{ + struct regmap *regmap, *mbq_regmap; + + /* Regmap Initialization */ + mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt711_sdca_mbq_regmap); + if (IS_ERR(mbq_regmap)) + return PTR_ERR(mbq_regmap); + + regmap = devm_regmap_init_sdw(slave, &rt711_sdca_regmap); + if (IS_ERR(regmap)) + return PTR_ERR(regmap); + + return rt711_sdca_init(&slave->dev, regmap, mbq_regmap, slave); +} + +static int rt711_sdca_sdw_remove(struct sdw_slave *slave) +{ + struct rt711_sdca_priv *rt711 = dev_get_drvdata(&slave->dev); + + if (rt711 && rt711->hw_init) { + cancel_delayed_work_sync(&rt711->jack_detect_work); + cancel_delayed_work_sync(&rt711->jack_btn_check_work); + } + + return 0; +} + +static const struct sdw_device_id rt711_sdca_id[] = { + SDW_SLAVE_ENTRY_EXT(0x025d, 0x711, 0x3, 0x1, 0), + {}, +}; +MODULE_DEVICE_TABLE(sdw, rt711_sdca_id); + +static int __maybe_unused rt711_sdca_dev_suspend(struct device *dev) +{ + struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); + + if (!rt711->hw_init) + return 0; + + cancel_delayed_work_sync(&rt711->jack_detect_work); + cancel_delayed_work_sync(&rt711->jack_btn_check_work); + + regcache_cache_only(rt711->regmap, true); + regcache_cache_only(rt711->mbq_regmap, true); + + return 0; +} + +#define RT711_PROBE_TIMEOUT 5000 + +static int __maybe_unused rt711_sdca_dev_resume(struct device *dev) +{ + struct sdw_slave *slave = dev_to_sdw_dev(dev); + struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); + unsigned long time; + + if (!rt711->hw_init) + return 0; + + if (!slave->unattach_request) + goto regmap_sync; + + time = wait_for_completion_timeout(&slave->initialization_complete, + msecs_to_jiffies(RT711_PROBE_TIMEOUT)); + if (!time) { + dev_err(&slave->dev, "Initialization not complete, timed out\n"); + return -ETIMEDOUT; + } + +regmap_sync: + slave->unattach_request = 0; + regcache_cache_only(rt711->regmap, false); + regcache_sync(rt711->regmap); + regcache_cache_only(rt711->mbq_regmap, false); + regcache_sync(rt711->mbq_regmap); + return 0; +} + +static const struct dev_pm_ops rt711_sdca_pm = { + SET_SYSTEM_SLEEP_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume) + SET_RUNTIME_PM_OPS(rt711_sdca_dev_suspend, rt711_sdca_dev_resume, NULL) +}; + +static struct sdw_driver rt711_sdca_sdw_driver = { + .driver = { + .name = "rt711-sdca", + .owner = THIS_MODULE, + .pm = &rt711_sdca_pm, + }, + .probe = rt711_sdca_sdw_probe, + .remove = rt711_sdca_sdw_remove, + .ops = &rt711_sdca_slave_ops, + .id_table = rt711_sdca_id, +}; +module_sdw_driver(rt711_sdca_sdw_driver); + +MODULE_DESCRIPTION("ASoC RT711 SDCA SDW driver"); +MODULE_AUTHOR("Shuming Fan "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt711-sdca-sdw.h b/sound/soc/codecs/rt711-sdca-sdw.h new file mode 100644 index 000000000000..0d774e473ab9 --- /dev/null +++ b/sound/soc/codecs/rt711-sdca-sdw.h @@ -0,0 +1,99 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt711-sdw-sdca.h -- RT711 SDCA ALSA SoC audio driver header + * + * Copyright(c) 2021 Realtek Semiconductor Corp. + */ + +#ifndef __RT711_SDW_SDCA_H__ +#define __RT711_SDW_SDCA_H__ + +#include +#include + +static const struct reg_default rt711_sdca_reg_defaults[] = { + { 0x201a, 0x00 }, + { 0x201e, 0x00 }, + { 0x201f, 0x00 }, + { 0x2020, 0x00 }, + { 0x2021, 0x00 }, + { 0x2022, 0x00 }, + { 0x2023, 0x00 }, + { 0x2024, 0x00 }, + { 0x2025, 0x01 }, + { 0x2026, 0x00 }, + { 0x2027, 0x00 }, + { 0x2029, 0x00 }, + { 0x202a, 0x00 }, + { 0x202d, 0x00 }, + { 0x202e, 0x00 }, + { 0x202f, 0x00 }, + { 0x2030, 0x00 }, + { 0x2031, 0x00 }, + { 0x2032, 0x00 }, + { 0x2033, 0x00 }, + { 0x2230, 0x00 }, + { 0x2231, 0x2f }, + { 0x2232, 0x80 }, + { 0x2233, 0x00 }, + { 0x2234, 0x00 }, + { 0x2235, 0x00 }, + { 0x2236, 0x00 }, + { 0x2237, 0x00 }, + { 0x2238, 0x00 }, + { 0x2239, 0x00 }, + { 0x2f01, 0x00 }, + { 0x2f02, 0x09 }, + { 0x2f03, 0x00 }, + { 0x2f04, 0x00 }, + { 0x2f05, 0x0b }, + { 0x2f06, 0x01 }, + { 0x2f08, 0x00 }, + { 0x2f09, 0x00 }, + { 0x2f0a, 0x00 }, + { 0x2f0b, 0x00 }, + { 0x2f0c, 0x00 }, + { 0x2f0d, 0x00 }, + { 0x2f0e, 0x14 }, + { 0x2f0f, 0x00 }, + { 0x2f50, 0x03 }, + { 0x2f5a, 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_CS01, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), 0x09 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE28, RT711_SDCA_CTL_REQ_POWER_STATE, 0), 0x03 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_MUTE, CH_L), 0x01 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_MUTE, CH_R), 0x01 }, +}; + +static const struct reg_default rt711_sdca_mbq_defaults[] = { + { 0x2000009, 0x1029 }, + { 0x2000011, 0x007a }, + { 0x200001a, 0x8003 }, + { 0x2000045, 0x5289 }, + { 0x2000048, 0x8049 }, + { 0x200004a, 0xa83b }, + { 0x200006b, 0x5064 }, + { 0x200006f, 0x058b }, + { 0x5800000, 0x0008 }, + { 0x5800001, 0x0000 }, + { 0x5f00001, 0x000a }, + { 0x6100000, 0x6100 }, + { 0x6100035, 0x0060 }, + { 0x6100036, 0x0029 }, + { 0x610003f, 0xff12 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_L), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_R), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_L), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_R), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_L), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_R), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), 0x00 }, + { SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), 0x00 }, +}; + +#endif /* __RT711_SDW_SDCA_H__ */ diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c new file mode 100644 index 000000000000..381893b640c6 --- /dev/null +++ b/sound/soc/codecs/rt711-sdca.c @@ -0,0 +1,1492 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt711-sdca.c -- rt711 SDCA ALSA SoC audio driver +// +// Copyright(c) 2021 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rt711-sdca.h" + +static int rt711_sdca_index_write(struct rt711_sdca_priv *rt711, + unsigned int nid, unsigned int reg, unsigned int value) +{ + int ret; + struct regmap *regmap = rt711->mbq_regmap; + unsigned int addr = (nid << 20) | reg; + + ret = regmap_write(regmap, addr, value); + if (ret < 0) + dev_err(rt711->component->dev, + "Failed to set private value: %06x <= %04x ret=%d\n", + addr, value, ret); + + return ret; +} + +static int rt711_sdca_index_read(struct rt711_sdca_priv *rt711, + unsigned int nid, unsigned int reg, unsigned int *value) +{ + int ret; + struct regmap *regmap = rt711->mbq_regmap; + unsigned int addr = (nid << 20) | reg; + + ret = regmap_read(regmap, addr, value); + if (ret < 0) + dev_err(rt711->component->dev, + "Failed to get private value: %06x => %04x ret=%d\n", + addr, *value, ret); + + return ret; +} + +static int rt711_sdca_index_update_bits(struct rt711_sdca_priv *rt711, + unsigned int nid, unsigned int reg, unsigned int mask, unsigned int val) +{ + unsigned int tmp; + int ret; + + ret = rt711_sdca_index_read(rt711, nid, reg, &tmp); + if (ret < 0) + return ret; + + set_mask_bits(&tmp, mask, val); + return rt711_sdca_index_write(rt711, nid, reg, tmp); +} + +static void rt711_sdca_reset(struct rt711_sdca_priv *rt711) +{ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_PARA_VERB_CTL, RT711_HIDDEN_REG_SW_RESET, + RT711_HIDDEN_REG_SW_RESET); + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_RESET_CTL, 0x1, 0x1); +} + +static int rt711_sdca_calibration(struct rt711_sdca_priv *rt711) +{ + unsigned int val, loop_rc = 0, loop_dc = 0; + struct device *dev; + struct regmap *regmap = rt711->regmap; + int chk_cnt = 100; + int ret = 0; + + mutex_lock(&rt711->calibrate_mutex); + dev = regmap_get_device(regmap); + + regmap_read(rt711->regmap, RT711_RC_CAL_STATUS, &val); + /* RC calibration */ + if (!(val & 0x40)) + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_ANALOG_CTL, + RT711_MISC_POWER_CTL0, 0x0010, 0x0010); + + for (loop_rc = 0; loop_rc < chk_cnt && !(val & 0x40); loop_rc++) { + usleep_range(10000, 11000); + ret = regmap_read(rt711->regmap, RT711_RC_CAL_STATUS, &val); + if (ret < 0) + goto _cali_fail_; + } + if (loop_rc == chk_cnt) + dev_err(dev, "%s, RC calibration time-out!\n", __func__); + + /* HP calibration by manual mode setting */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_FSM_CTL, 0x2000, 0x2000); + + /* Calibration manual mode */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_FSM_CTL, 0xf, RT711_CALI_CTL); + + /* reset HP calibration */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, + RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_FORCE_CALI_RST, 0x00); + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, + RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_FORCE_CALI_RST, + RT711_DAC_DC_FORCE_CALI_RST); + + /* cal_clk_en_reg */ + if (rt711->hw_ver == RT711_VER_VD0) + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, + RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_CLK_EN, + RT711_DAC_DC_CALI_CLK_EN); + + /* trigger */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_CALI, + RT711_DAC_DC_CALI_CTL1, RT711_DAC_DC_CALI_TRIGGER, + RT711_DAC_DC_CALI_TRIGGER); + + /* wait for calibration process */ + rt711_sdca_index_read(rt711, RT711_VENDOR_CALI, + RT711_DAC_DC_CALI_CTL1, &val); + + for (loop_dc = 0; loop_dc < chk_cnt && + (val & RT711_DAC_DC_CALI_TRIGGER); loop_dc++) { + usleep_range(10000, 11000); + ret = rt711_sdca_index_read(rt711, RT711_VENDOR_CALI, + RT711_DAC_DC_CALI_CTL1, &val); + if (ret < 0) + goto _cali_fail_; + } + if (loop_dc == chk_cnt) + dev_err(dev, "%s, calibration time-out!\n", __func__); + + if (loop_dc == chk_cnt || loop_rc == chk_cnt) + ret = -ETIMEDOUT; + +_cali_fail_: + /* enable impedance sense */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_FSM_CTL, RT711_FSM_IMP_EN, RT711_FSM_IMP_EN); + + /* release HP-JD and trigger FSM */ + rt711_sdca_index_write(rt711, RT711_VENDOR_REG, + RT711_DIGITAL_MISC_CTRL4, 0x201b); + + mutex_unlock(&rt711->calibrate_mutex); + dev_dbg(dev, "%s calibration complete, ret=%d\n", __func__, ret); + return ret; +} + +static unsigned int rt711_sdca_button_detect(struct rt711_sdca_priv *rt711) +{ + unsigned int btn_type = 0, offset, idx, val, owner; + int ret; + unsigned char buf[3]; + + /* get current UMP message owner */ + ret = regmap_read(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_CURRENT_OWNER, 0), + &owner); + if (ret < 0) + return 0; + + /* if owner is device then there is no button event from device */ + if (owner == 1) + return 0; + + /* read UMP message offset */ + ret = regmap_read(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), + &offset); + if (ret < 0) + goto _end_btn_det_; + + for (idx = 0; idx < sizeof(buf); idx++) { + ret = regmap_read(rt711->regmap, + RT711_BUF_ADDR_HID1 + offset + idx, &val); + if (ret < 0) + goto _end_btn_det_; + buf[idx] = val & 0xff; + } + + if (buf[0] == 0x11) { + switch (buf[1] & 0xf0) { + case 0x10: + btn_type |= SND_JACK_BTN_2; + break; + case 0x20: + btn_type |= SND_JACK_BTN_3; + break; + case 0x40: + btn_type |= SND_JACK_BTN_0; + break; + case 0x80: + btn_type |= SND_JACK_BTN_1; + break; + } + switch (buf[2]) { + case 0x01: + case 0x10: + btn_type |= SND_JACK_BTN_2; + break; + case 0x02: + case 0x20: + btn_type |= SND_JACK_BTN_3; + break; + case 0x04: + case 0x40: + btn_type |= SND_JACK_BTN_0; + break; + case 0x08: + case 0x80: + btn_type |= SND_JACK_BTN_1; + break; + } + } + +_end_btn_det_: + /* Host is owner, so set back to device */ + if (owner == 0) + /* set owner to device */ + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, + RT711_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE, 0), 0x01); + + return btn_type; +} + +static int rt711_sdca_headset_detect(struct rt711_sdca_priv *rt711) +{ + unsigned int det_mode; + int ret; + + /* get detected_mode */ + ret = regmap_read(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0), + &det_mode); + if (ret < 0) + goto io_error; + + switch (det_mode) { + case 0x00: + rt711->jack_type = 0; + break; + case 0x03: + rt711->jack_type = SND_JACK_HEADPHONE; + break; + case 0x05: + rt711->jack_type = SND_JACK_HEADSET; + break; + } + + /* write selected_mode */ + if (det_mode) { + ret = regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_SELECTED_MODE, 0), + det_mode); + if (ret < 0) + goto io_error; + } + + dev_dbg(&rt711->slave->dev, + "%s, detected_mode=0x%x\n", __func__, det_mode); + + return 0; + +io_error: + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); + return ret; +} + +static void rt711_sdca_jack_detect_handler(struct work_struct *work) +{ + struct rt711_sdca_priv *rt711 = + container_of(work, struct rt711_sdca_priv, jack_detect_work.work); + int btn_type = 0, ret; + + if (!rt711->hs_jack) + return; + + if (!rt711->component->card->instantiated) + return; + + /* SDW_SCP_SDCA_INT_SDCA_0 is used for jack detection */ + if (rt711->scp_sdca_stat1 & SDW_SCP_SDCA_INT_SDCA_0) { + ret = rt711_sdca_headset_detect(rt711); + if (ret < 0) + return; + } + + /* SDW_SCP_SDCA_INT_SDCA_8 is used for button detection */ + if (rt711->scp_sdca_stat2 & SDW_SCP_SDCA_INT_SDCA_8) + btn_type = rt711_sdca_button_detect(rt711); + + if (rt711->jack_type == 0) + btn_type = 0; + + dev_dbg(&rt711->slave->dev, + "in %s, jack_type=0x%x\n", __func__, rt711->jack_type); + dev_dbg(&rt711->slave->dev, + "in %s, btn_type=0x%x\n", __func__, btn_type); + dev_dbg(&rt711->slave->dev, + "in %s, scp_sdca_stat1=0x%x, scp_sdca_stat2=0x%x\n", __func__, + rt711->scp_sdca_stat1, rt711->scp_sdca_stat2); + + snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + if (btn_type) { + /* button released */ + snd_soc_jack_report(rt711->hs_jack, rt711->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + mod_delayed_work(system_power_efficient_wq, + &rt711->jack_btn_check_work, msecs_to_jiffies(200)); + } +} + +static void rt711_sdca_btn_check_handler(struct work_struct *work) +{ + struct rt711_sdca_priv *rt711 = + container_of(work, struct rt711_sdca_priv, jack_btn_check_work.work); + int btn_type = 0, ret, idx; + unsigned int det_mode, offset, val; + unsigned char buf[3]; + + ret = regmap_read(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, RT711_SDCA_CTL_DETECTED_MODE, 0), + &det_mode); + if (ret < 0) + goto io_error; + + /* pin attached */ + if (det_mode) { + /* read UMP message offset */ + ret = regmap_read(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_HID, RT711_SDCA_ENT_HID01, RT711_SDCA_CTL_HIDTX_MESSAGE_OFFSET, 0), + &offset); + if (ret < 0) + goto io_error; + + for (idx = 0; idx < sizeof(buf); idx++) { + ret = regmap_read(rt711->regmap, + RT711_BUF_ADDR_HID1 + offset + idx, &val); + if (ret < 0) + goto io_error; + buf[idx] = val & 0xff; + } + + if (buf[0] == 0x11) { + switch (buf[1] & 0xf0) { + case 0x10: + btn_type |= SND_JACK_BTN_2; + break; + case 0x20: + btn_type |= SND_JACK_BTN_3; + break; + case 0x40: + btn_type |= SND_JACK_BTN_0; + break; + case 0x80: + btn_type |= SND_JACK_BTN_1; + break; + } + switch (buf[2]) { + case 0x01: + case 0x10: + btn_type |= SND_JACK_BTN_2; + break; + case 0x02: + case 0x20: + btn_type |= SND_JACK_BTN_3; + break; + case 0x04: + case 0x40: + btn_type |= SND_JACK_BTN_0; + break; + case 0x08: + case 0x80: + btn_type |= SND_JACK_BTN_1; + break; + } + } + } else + rt711->jack_type = 0; + + dev_dbg(&rt711->slave->dev, "%s, btn_type=0x%x\n", __func__, btn_type); + snd_soc_jack_report(rt711->hs_jack, rt711->jack_type | btn_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + if (btn_type) { + /* button released */ + snd_soc_jack_report(rt711->hs_jack, rt711->jack_type, + SND_JACK_HEADSET | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); + + mod_delayed_work(system_power_efficient_wq, + &rt711->jack_btn_check_work, msecs_to_jiffies(200)); + } + + return; + +io_error: + pr_err_ratelimited("IO error in %s, ret %d\n", __func__, ret); +} + +static void rt711_sdca_jack_init(struct rt711_sdca_priv *rt711) +{ + mutex_lock(&rt711->calibrate_mutex); + + if (rt711->hs_jack) { + /* Enable HID1 event & set button RTC mode */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_PUSH_BTN_INT_CTL6, 0x80f0, 0x8000); + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_PUSH_BTN_INT_CTL2, 0x11dd, 0x11dd); + rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, + RT711_PUSH_BTN_INT_CTL7, 0xffff); + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_PUSH_BTN_INT_CTL9, 0xf000, 0x0000); + + /* GE_mode_change_event_en & Hid1_push_button_event_en */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_GE_MODE_RELATED_CTL, 0x0c00, 0x0c00); + + switch (rt711->jd_src) { + case RT711_JD1: + /* default settings was already for JD1 */ + break; + case RT711_JD2: + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_JD_CTL1, RT711_JD2_DIGITAL_MODE_SEL, + RT711_JD2_DIGITAL_MODE_SEL); + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_JD_CTL2, RT711_JD2_2PORT_200K_DECODE_HP | RT711_HP_JD_SEL_JD2, + RT711_JD2_2PORT_200K_DECODE_HP | RT711_HP_JD_SEL_JD2); + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_CC_DET1, + RT711_HP_JD_FINAL_RESULT_CTL_JD12, + RT711_HP_JD_FINAL_RESULT_CTL_JD12); + break; + default: + dev_warn(rt711->component->dev, "Wrong JD source\n"); + break; + } + + /* set SCP_SDCA_IntMask1[0]=1 */ + sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK1, SDW_SCP_SDCA_INTMASK_SDCA_0); + /* set SCP_SDCA_IntMask2[0]=1 */ + sdw_write_no_pm(rt711->slave, SDW_SCP_SDCA_INTMASK2, SDW_SCP_SDCA_INTMASK_SDCA_8); + dev_dbg(&rt711->slave->dev, "in %s enable\n", __func__); + } else { + /* disable HID 1/2 event */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_GE_MODE_RELATED_CTL, 0x0c00, 0x0000); + + dev_dbg(&rt711->slave->dev, "in %s disable\n", __func__); + } + + mutex_unlock(&rt711->calibrate_mutex); +} + +static int rt711_sdca_set_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *hs_jack, void *data) +{ + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + + rt711->hs_jack = hs_jack; + + if (!rt711->hw_init) { + dev_dbg(&rt711->slave->dev, + "%s hw_init not ready yet\n", __func__); + return 0; + } + + rt711_sdca_jack_init(rt711); + return 0; +} + +/* For SDCA control DAC/ADC Gain */ +static int rt711_sdca_set_gain_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned int read_l, read_r, gain_l_val, gain_r_val; + unsigned int i, adc_vol_flag = 0; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume") || + strstr(ucontrol->id.name, "FU0F Capture Volume")) + adc_vol_flag = 1; + + /* control value to 2's complement value */ + /* L Channel */ + gain_l_val = ucontrol->value.integer.value[0]; + if (gain_l_val > mc->max) + gain_l_val = mc->max; + read_l = gain_l_val; + + if (mc->shift == 8) /* boost gain */ + gain_l_val = (gain_l_val * 10) << mc->shift; + else { /* ADC/DAC gain */ + if (adc_vol_flag && gain_l_val > mc->shift) + gain_l_val = (gain_l_val - mc->shift) * 75; + else + gain_l_val = (mc->shift - gain_l_val) * 75; + gain_l_val <<= 8; + gain_l_val /= 100; + if (!(adc_vol_flag && read_l > mc->shift)) { + gain_l_val = ~gain_l_val; + gain_l_val += 1; + } + gain_l_val &= 0xffff; + } + + /* R Channel */ + gain_r_val = ucontrol->value.integer.value[1]; + if (gain_r_val > mc->max) + gain_r_val = mc->max; + read_r = gain_r_val; + + if (mc->shift == 8) /* boost gain */ + gain_r_val = (gain_r_val * 10) << mc->shift; + else { /* ADC/DAC gain */ + if (adc_vol_flag && gain_r_val > mc->shift) + gain_r_val = (gain_r_val - mc->shift) * 75; + else + gain_r_val = (mc->shift - gain_r_val) * 75; + gain_r_val <<= 8; + gain_r_val /= 100; + if (!(adc_vol_flag && read_r > mc->shift)) { + gain_r_val = ~gain_r_val; + gain_r_val += 1; + } + gain_r_val &= 0xffff; + } + + for (i = 0; i < 3; i++) { /* retry 3 times at most */ + /* Lch*/ + regmap_write(rt711->mbq_regmap, mc->reg, gain_l_val); + + /* Rch */ + regmap_write(rt711->mbq_regmap, mc->rreg, gain_r_val); + + regmap_read(rt711->mbq_regmap, mc->reg, &read_l); + regmap_read(rt711->mbq_regmap, mc->rreg, &read_r); + if (read_r == gain_r_val && read_l == gain_l_val) + break; + } + + return i == 3 ? -EIO : 0; +} + +static int rt711_sdca_set_gain_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + struct soc_mixer_control *mc = + (struct soc_mixer_control *)kcontrol->private_value; + unsigned int read_l, read_r, ctl_l = 0, ctl_r = 0; + unsigned int adc_vol_flag = 0, neg_flag = 0; + + if (strstr(ucontrol->id.name, "FU1E Capture Volume") || + strstr(ucontrol->id.name, "FU0F Capture Volume")) + adc_vol_flag = 1; + + regmap_read(rt711->mbq_regmap, mc->reg, &read_l); + regmap_read(rt711->mbq_regmap, mc->rreg, &read_r); + + /* 2's complement value to control value */ + if (mc->shift == 8) /* boost gain */ + ctl_l = (read_l >> mc->shift) / 10; + else { /* ADC/DAC gain */ + ctl_l = read_l; + if (read_l & BIT(15)) { + ctl_l = 0xffff & ~(read_l - 1); + neg_flag = 1; + } + ctl_l *= 100; + ctl_l >>= 8; + if (adc_vol_flag) { + if (neg_flag) + ctl_l = mc->shift - (ctl_l / 75); + else + ctl_l = mc->shift + (ctl_l / 75); + } else + ctl_l = mc->max - (ctl_l / 75); + } + + neg_flag = 0; + if (read_l != read_r) { + if (mc->shift == 8) /* boost gain */ + ctl_r = (read_r >> mc->shift) / 10; + else { /* ADC/DAC gain */ + ctl_r = read_r; + if (read_r & BIT(15)) { + ctl_r = 0xffff & ~(read_r - 1); + neg_flag = 1; + } + ctl_r *= 100; + ctl_r >>= 8; + if (adc_vol_flag) { + if (neg_flag) + ctl_r = mc->shift - (ctl_r / 75); + else + ctl_r = mc->shift + (ctl_r / 75); + } else + ctl_r = mc->max - (ctl_r / 75); + } + } else + ctl_r = ctl_l; + + ucontrol->value.integer.value[0] = ctl_l; + ucontrol->value.integer.value[1] = ctl_r; + + return 0; +} + +static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); +static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); +static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); + +static const struct snd_kcontrol_new rt711_sdca_snd_controls[] = { + SOC_DOUBLE_R_EXT_TLV("FU05 Playback Volume", + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_L), + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_R), + 0x57, 0x57, 0, + rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, out_vol_tlv), + SOC_DOUBLE_R("FU1E Capture Switch", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_MUTE, CH_L), + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_MUTE, CH_R), + 0, 1, 1), + SOC_DOUBLE_R("FU0F Capture Switch", + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_MUTE, CH_L), + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_MUTE, CH_R), + 0, 1, 1), + SOC_DOUBLE_R_EXT_TLV("FU1E Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_L), + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_R), + 0x17, 0x3f, 0, + rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, in_vol_tlv), + SOC_DOUBLE_R_EXT_TLV("FU0F Capture Volume", + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_L), + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_VOLUME, CH_R), + 0x17, 0x3f, 0, + rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, in_vol_tlv), + SOC_DOUBLE_R_EXT_TLV("FU44 Gain Volume", + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PLATFORM_FU44, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), + 8, 3, 0, + rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv), + SOC_DOUBLE_R_EXT_TLV("FU15 Gain Volume", + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_L), + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PLATFORM_FU15, RT711_SDCA_CTL_FU_CH_GAIN, CH_R), + 8, 3, 0, + rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, mic_vol_tlv), +}; + +static int rt711_sdca_mux_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned int val = 0, mask_sft; + + if (strstr(ucontrol->id.name, "ADC 22 Mux")) + mask_sft = 10; + else if (strstr(ucontrol->id.name, "ADC 23 Mux")) + mask_sft = 13; + else + return -EINVAL; + + rt711_sdca_index_read(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_MUX_CTL1, &val); + + ucontrol->value.enumerated.item[0] = (val >> mask_sft) & 0x7; + + return 0; +} + +static int rt711_sdca_mux_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = + snd_soc_dapm_kcontrol_component(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_dapm_kcontrol_dapm(kcontrol); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + struct soc_enum *e = (struct soc_enum *)kcontrol->private_value; + unsigned int *item = ucontrol->value.enumerated.item; + unsigned int val, val2 = 0, change, mask_sft; + + if (item[0] >= e->items) + return -EINVAL; + + if (strstr(ucontrol->id.name, "ADC 22 Mux")) + mask_sft = 10; + else if (strstr(ucontrol->id.name, "ADC 23 Mux")) + mask_sft = 13; + else + return -EINVAL; + + val = snd_soc_enum_item_to_val(e, item[0]) << e->shift_l; + + rt711_sdca_index_read(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_MUX_CTL1, &val2); + val2 = (val2 >> mask_sft) & 0x7; + + if (val == val2) + change = 0; + else + change = 1; + + if (change) + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_MUX_CTL1, 0x7 << mask_sft, + val << mask_sft); + + snd_soc_dapm_mux_update_power(dapm, kcontrol, + item[0], e, NULL); + + return change; +} + +static const char * const adc_mux_text[] = { + "MIC2", + "LINE1", + "LINE2", + "DMIC", +}; + +static SOC_ENUM_SINGLE_DECL( + rt711_adc22_enum, SND_SOC_NOPM, 0, adc_mux_text); + +static SOC_ENUM_SINGLE_DECL( + rt711_adc23_enum, SND_SOC_NOPM, 0, adc_mux_text); + +static const struct snd_kcontrol_new rt711_sdca_adc22_mux = + SOC_DAPM_ENUM_EXT("ADC 22 Mux", rt711_adc22_enum, + rt711_sdca_mux_get, rt711_sdca_mux_put); + +static const struct snd_kcontrol_new rt711_sdca_adc23_mux = + SOC_DAPM_ENUM_EXT("ADC 23 Mux", rt711_adc23_enum, + rt711_sdca_mux_get, rt711_sdca_mux_put); + +static int rt711_sdca_fu05_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned char unmute = 0x0, mute = 0x1; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, + RT711_SDCA_CTL_FU_MUTE, CH_L), + unmute); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, + RT711_SDCA_CTL_FU_MUTE, CH_R), + unmute); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, + RT711_SDCA_CTL_FU_MUTE, CH_L), + mute); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, + RT711_SDCA_CTL_FU_MUTE, CH_R), + mute); + break; + } + return 0; +} + +static int rt711_sdca_fu0f_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned char unmute = 0x0, mute = 0x1; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, + RT711_SDCA_CTL_FU_MUTE, CH_L), + unmute); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, + RT711_SDCA_CTL_FU_MUTE, CH_R), + unmute); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, + RT711_SDCA_CTL_FU_MUTE, CH_L), + mute); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, + RT711_SDCA_CTL_FU_MUTE, CH_R), + mute); + break; + } + return 0; +} + +static int rt711_sdca_fu1e_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned char unmute = 0x0, mute = 0x1; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, + RT711_SDCA_CTL_FU_MUTE, CH_L), + unmute); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, + RT711_SDCA_CTL_FU_MUTE, CH_R), + unmute); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, + RT711_SDCA_CTL_FU_MUTE, CH_L), + mute); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, + RT711_SDCA_CTL_FU_MUTE, CH_R), + mute); + break; + } + return 0; +} + +static int rt711_sdca_pde28_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE28, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE28, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + } + return 0; +} + +static int rt711_sdca_pde29_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE29, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDE29, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + } + return 0; +} + +static int rt711_sdca_pde2a_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PDE2A, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_PDE2A, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + } + return 0; +} + +static int rt711_sdca_line1_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + static unsigned int sel_mode = 0xffff; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_read(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, + RT711_SDCA_CTL_SELECTED_MODE, 0), + &sel_mode); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE1, + RT711_SDCA_CTL_VENDOR_DEF, 0), + 0x1); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, + RT711_SDCA_CTL_SELECTED_MODE, 0), + 0x7); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE1, + RT711_SDCA_CTL_VENDOR_DEF, 0), + 0x0); + if (sel_mode != 0xffff) + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_GE49, + RT711_SDCA_CTL_SELECTED_MODE, 0), + sel_mode); + break; + } + + return 0; +} + +static int rt711_sdca_line2_power_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = + snd_soc_dapm_to_component(w->dapm); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + unsigned char ps0 = 0x0, ps3 = 0x3; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDELINE2, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps0); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE2, + RT711_SDCA_CTL_VENDOR_DEF, 0), + 0x1); + break; + case SND_SOC_DAPM_PRE_PMD: + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_LINE2, + RT711_SDCA_CTL_VENDOR_DEF, 0), + 0x0); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_PDELINE2, + RT711_SDCA_CTL_REQ_POWER_STATE, 0), + ps3); + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rt711_sdca_dapm_widgets[] = { + SND_SOC_DAPM_OUTPUT("HP"), + SND_SOC_DAPM_INPUT("MIC2"), + SND_SOC_DAPM_INPUT("DMIC1"), + SND_SOC_DAPM_INPUT("DMIC2"), + SND_SOC_DAPM_INPUT("LINE1"), + SND_SOC_DAPM_INPUT("LINE2"), + + SND_SOC_DAPM_PGA_E("LINE1 Power", SND_SOC_NOPM, + 0, 0, NULL, 0, rt711_sdca_line1_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_PGA_E("LINE2 Power", SND_SOC_NOPM, + 0, 0, NULL, 0, rt711_sdca_line2_power_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_SUPPLY("PDE 28", SND_SOC_NOPM, 0, 0, + rt711_sdca_pde28_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("PDE 29", SND_SOC_NOPM, 0, 0, + rt711_sdca_pde29_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_SUPPLY("PDE 2A", SND_SOC_NOPM, 0, 0, + rt711_sdca_pde2a_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + + SND_SOC_DAPM_DAC_E("FU 05", NULL, SND_SOC_NOPM, 0, 0, + rt711_sdca_fu05_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_ADC_E("FU 0F", NULL, SND_SOC_NOPM, 0, 0, + rt711_sdca_fu0f_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_ADC_E("FU 1E", NULL, SND_SOC_NOPM, 0, 0, + rt711_sdca_fu1e_event, + SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_PRE_PMD), + SND_SOC_DAPM_MUX("ADC 22 Mux", SND_SOC_NOPM, 0, 0, + &rt711_sdca_adc22_mux), + SND_SOC_DAPM_MUX("ADC 23 Mux", SND_SOC_NOPM, 0, 0, + &rt711_sdca_adc23_mux), + + SND_SOC_DAPM_AIF_IN("DP3RX", "DP3 Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP2TX", "DP2 Capture", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_AIF_OUT("DP4TX", "DP4 Capture", 0, SND_SOC_NOPM, 0, 0), +}; + +static const struct snd_soc_dapm_route rt711_sdca_audio_map[] = { + {"FU 05", NULL, "DP3RX"}, + {"DP2TX", NULL, "FU 0F"}, + {"DP4TX", NULL, "FU 1E"}, + + {"LINE1 Power", NULL, "LINE1"}, + {"LINE2 Power", NULL, "LINE2"}, + {"HP", NULL, "PDE 28"}, + {"FU 0F", NULL, "PDE 29"}, + {"FU 1E", NULL, "PDE 2A"}, + + {"FU 0F", NULL, "ADC 22 Mux"}, + {"FU 1E", NULL, "ADC 23 Mux"}, + {"ADC 22 Mux", "DMIC", "DMIC1"}, + {"ADC 22 Mux", "LINE1", "LINE1 Power"}, + {"ADC 22 Mux", "LINE2", "LINE2 Power"}, + {"ADC 22 Mux", "MIC2", "MIC2"}, + {"ADC 23 Mux", "DMIC", "DMIC2"}, + {"ADC 23 Mux", "LINE1", "LINE1 Power"}, + {"ADC 23 Mux", "LINE2", "LINE2 Power"}, + {"ADC 23 Mux", "MIC2", "MIC2"}, + + {"HP", NULL, "FU 05"}, +}; + +static int rt711_sdca_parse_dt(struct rt711_sdca_priv *rt711, struct device *dev) +{ + device_property_read_u32(dev, "realtek,jd-src", &rt711->jd_src); + + return 0; +} + +static int rt711_sdca_probe(struct snd_soc_component *component) +{ + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + + rt711_sdca_parse_dt(rt711, &rt711->slave->dev); + rt711->component = component; + + return 0; +} + +static void rt711_sdca_remove(struct snd_soc_component *component) +{ + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + + regcache_cache_only(rt711->regmap, true); + regcache_cache_only(rt711->mbq_regmap, true); +} + +static const struct snd_soc_component_driver soc_sdca_dev_rt711 = { + .probe = rt711_sdca_probe, + .controls = rt711_sdca_snd_controls, + .num_controls = ARRAY_SIZE(rt711_sdca_snd_controls), + .dapm_widgets = rt711_sdca_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt711_sdca_dapm_widgets), + .dapm_routes = rt711_sdca_audio_map, + .num_dapm_routes = ARRAY_SIZE(rt711_sdca_audio_map), + .set_jack = rt711_sdca_set_jack_detect, + .remove = rt711_sdca_remove, +}; + +static int rt711_sdca_set_sdw_stream(struct snd_soc_dai *dai, void *sdw_stream, + int direction) +{ + struct sdw_stream_data *stream; + + if (!sdw_stream) + return 0; + + stream = kzalloc(sizeof(*stream), GFP_KERNEL); + if (!stream) + return -ENOMEM; + + stream->sdw_stream = sdw_stream; + + /* Use tx_mask or rx_mask to configure stream tag and set dma_data */ + if (direction == SNDRV_PCM_STREAM_PLAYBACK) + dai->playback_dma_data = stream; + else + dai->capture_dma_data = stream; + + return 0; +} + +static void rt711_sdca_shutdown(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct sdw_stream_data *stream; + + stream = snd_soc_dai_get_dma_data(dai, substream); + snd_soc_dai_set_dma_data(dai, substream, NULL); + kfree(stream); +} + +static int rt711_sdca_pcm_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + struct sdw_stream_config stream_config; + struct sdw_port_config port_config; + enum sdw_data_direction direction; + struct sdw_stream_data *stream; + int retval, port, num_channels; + unsigned int sampling_rate; + + dev_dbg(dai->dev, "%s %s", __func__, dai->name); + stream = snd_soc_dai_get_dma_data(dai, substream); + + if (!stream) + return -EINVAL; + + if (!rt711->slave) + return -EINVAL; + + /* SoundWire specific configuration */ + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + direction = SDW_DATA_DIR_RX; + port = 3; + } else { + direction = SDW_DATA_DIR_TX; + if (dai->id == RT711_AIF1) + port = 2; + else if (dai->id == RT711_AIF2) + port = 4; + else + return -EINVAL; + } + + stream_config.frame_rate = params_rate(params); + stream_config.ch_count = params_channels(params); + stream_config.bps = snd_pcm_format_width(params_format(params)); + stream_config.direction = direction; + + num_channels = params_channels(params); + port_config.ch_mask = GENMASK(num_channels - 1, 0); + port_config.num = port; + + retval = sdw_stream_add_slave(rt711->slave, &stream_config, + &port_config, 1, stream->sdw_stream); + if (retval) { + dev_err(dai->dev, "Unable to configure port\n"); + return retval; + } + + if (params_channels(params) > 16) { + dev_err(component->dev, "Unsupported channels %d\n", + params_channels(params)); + return -EINVAL; + } + + /* sampling rate configuration */ + switch (params_rate(params)) { + case 44100: + sampling_rate = RT711_SDCA_RATE_44100HZ; + break; + case 48000: + sampling_rate = RT711_SDCA_RATE_48000HZ; + break; + case 96000: + sampling_rate = RT711_SDCA_RATE_96000HZ; + break; + case 192000: + sampling_rate = RT711_SDCA_RATE_192000HZ; + break; + default: + dev_err(component->dev, "Rate %d is not supported\n", + params_rate(params)); + return -EINVAL; + } + + /* set sampling frequency */ + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_CS01, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_CS11, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_CS1F, RT711_SDCA_CTL_SAMPLE_FREQ_INDEX, 0), + sampling_rate); + + return 0; +} + +static int rt711_sdca_pcm_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + struct sdw_stream_data *stream = + snd_soc_dai_get_dma_data(dai, substream); + + if (!rt711->slave) + return -EINVAL; + + sdw_stream_remove_slave(rt711->slave, stream->sdw_stream); + return 0; +} + +#define RT711_STEREO_RATES (SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 | SNDRV_PCM_RATE_96000 | \ + SNDRV_PCM_RATE_192000) +#define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE) + +static struct snd_soc_dai_ops rt711_sdca_ops = { + .hw_params = rt711_sdca_pcm_hw_params, + .hw_free = rt711_sdca_pcm_hw_free, + .set_sdw_stream = rt711_sdca_set_sdw_stream, + .shutdown = rt711_sdca_shutdown, +}; + +static struct snd_soc_dai_driver rt711_sdca_dai[] = { + { + .name = "rt711-sdca-aif1", + .id = RT711_AIF1, + .playback = { + .stream_name = "DP3 Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT711_STEREO_RATES, + .formats = RT711_FORMATS, + }, + .capture = { + .stream_name = "DP2 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT711_STEREO_RATES, + .formats = RT711_FORMATS, + }, + .ops = &rt711_sdca_ops, + }, + { + .name = "rt711-sdca-aif2", + .id = RT711_AIF2, + .capture = { + .stream_name = "DP4 Capture", + .channels_min = 1, + .channels_max = 2, + .rates = RT711_STEREO_RATES, + .formats = RT711_FORMATS, + }, + .ops = &rt711_sdca_ops, + } +}; + +int rt711_sdca_init(struct device *dev, struct regmap *regmap, + struct regmap *mbq_regmap, struct sdw_slave *slave) +{ + struct rt711_sdca_priv *rt711; + int ret; + + rt711 = devm_kzalloc(dev, sizeof(*rt711), GFP_KERNEL); + if (!rt711) + return -ENOMEM; + + dev_set_drvdata(dev, rt711); + rt711->slave = slave; + rt711->regmap = regmap; + rt711->mbq_regmap = mbq_regmap; + + /* + * Mark hw_init to false + * HW init will be performed when device reports present + */ + rt711->hw_init = false; + rt711->first_hw_init = false; + + /* JD source uses JD2 in default */ + rt711->jd_src = RT711_JD2; + + ret = devm_snd_soc_register_component(dev, + &soc_sdca_dev_rt711, + rt711_sdca_dai, + ARRAY_SIZE(rt711_sdca_dai)); + + dev_dbg(&slave->dev, "%s\n", __func__); + + return ret; +} + +static void rt711_sdca_vd0_io_init(struct rt711_sdca_priv *rt711) +{ + rt711_sdca_index_write(rt711, RT711_VENDOR_REG, + RT711_GPIO_TEST_MODE_CTL2, 0x0e00); + rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_GPIO_CTL, 0x0008); + + regmap_write(rt711->regmap, 0x2f5a, 0x01); + + rt711_sdca_index_write(rt711, RT711_VENDOR_REG, + RT711_ADC27_VOL_SET, 0x8728); + + rt711_sdca_index_write(rt711, RT711_VENDOR_REG, + RT711_COMBO_JACK_AUTO_CTL3, 0xa472); + + regmap_write(rt711->regmap, 0x2f50, 0x02); + + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_ANALOG_CTL, + RT711_MISC_POWER_CTL4, 0x6000, 0x6000); + + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_COMBO_JACK_AUTO_CTL3, 0x000c, 0x000c); + + rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_CONFIG_CTL, 0x0000); + + rt711_sdca_index_write(rt711, RT711_VENDOR_VAD, + RT711_VAD_SRAM_CTL1, 0x0050); +} + +static void rt711_sdca_vd1_io_init(struct rt711_sdca_priv *rt711) +{ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_UNSOLICITED_CTL, 0x0300, 0x0000); + + rt711_sdca_index_write(rt711, RT711_VENDOR_REG, + RT711_COMBO_JACK_AUTO_CTL3, 0xa43e); + + regmap_write(rt711->regmap, 0x2f5a, 0x05); + + rt711_sdca_index_write(rt711, RT711_VENDOR_REG, + RT711_JD_CTRL6, 0x0500); + + rt711_sdca_index_write(rt711, RT711_VENDOR_REG, + RT711_DMIC_CTL1, 0x6173); + + rt711_sdca_index_write(rt711, RT711_VENDOR_HDA_CTL, + RT711_HDA_LEGACY_CONFIG_CTL, 0x0000); + + rt711_sdca_index_write(rt711, RT711_VENDOR_VAD, + RT711_VAD_SRAM_CTL1, 0x0050); +} + +int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave) +{ + struct rt711_sdca_priv *rt711 = dev_get_drvdata(dev); + int ret = 0; + unsigned int val; + + if (rt711->hw_init) + return 0; + + if (rt711->first_hw_init) { + regcache_cache_only(rt711->regmap, false); + regcache_cache_bypass(rt711->regmap, true); + } else { + /* + * PM runtime is only enabled when a Slave reports as Attached + */ + + /* set autosuspend parameters */ + pm_runtime_set_autosuspend_delay(&slave->dev, 3000); + pm_runtime_use_autosuspend(&slave->dev); + + /* update count of parent 'active' children */ + pm_runtime_set_active(&slave->dev); + + /* make sure the device does not suspend immediately */ + pm_runtime_mark_last_busy(&slave->dev); + + pm_runtime_enable(&slave->dev); + } + + pm_runtime_get_noresume(&slave->dev); + + rt711_sdca_reset(rt711); + + rt711_sdca_index_read(rt711, RT711_VENDOR_REG, RT711_JD_PRODUCT_NUM, &val); + rt711->hw_ver = val & 0xf; + + if (rt711->hw_ver == RT711_VER_VD0) + rt711_sdca_vd0_io_init(rt711); + else + rt711_sdca_vd1_io_init(rt711); + + /* DP4 mux select from 08_filter_Out_pri */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_REG, + RT711_FILTER_SRC_SEL, 0x1800, 0x0800); + + /* ge_exclusive_inbox_en disable */ + rt711_sdca_index_update_bits(rt711, RT711_VENDOR_HDA_CTL, + RT711_PUSH_BTN_INT_CTL0, 0x20, 0x00); + + if (!rt711->first_hw_init) { + INIT_DELAYED_WORK(&rt711->jack_detect_work, + rt711_sdca_jack_detect_handler); + INIT_DELAYED_WORK(&rt711->jack_btn_check_work, + rt711_sdca_btn_check_handler); + mutex_init(&rt711->calibrate_mutex); + } + + /* calibration */ + ret = rt711_sdca_calibration(rt711); + if (ret < 0) + dev_err(dev, "%s, calibration failed!\n", __func__); + + /* HP output enable */ + regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_OT1, RT711_SDCA_CTL_VENDOR_DEF, 0), 0x4); + + /* + * if set_jack callback occurred early than io_init, + * we set up the jack detection function now + */ + if (rt711->hs_jack) + rt711_sdca_jack_init(rt711); + + if (rt711->first_hw_init) { + regcache_cache_bypass(rt711->regmap, false); + regcache_mark_dirty(rt711->regmap); + } else + rt711->first_hw_init = true; + + /* Mark Slave initialization complete */ + rt711->hw_init = true; + + pm_runtime_mark_last_busy(&slave->dev); + pm_runtime_put_autosuspend(&slave->dev); + + dev_dbg(&slave->dev, "%s hw_init complete\n", __func__); + return 0; +} + +MODULE_DESCRIPTION("ASoC RT711 SDCA SDW driver"); +MODULE_AUTHOR("Shuming Fan "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/rt711-sdca.h b/sound/soc/codecs/rt711-sdca.h new file mode 100644 index 000000000000..98a022cec0bd --- /dev/null +++ b/sound/soc/codecs/rt711-sdca.h @@ -0,0 +1,238 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt711-sdca.h -- RT711 SDCA ALSA SoC audio driver header + * + * Copyright(c) 2021 Realtek Semiconductor Corp. + */ + +#ifndef __RT711_SDCA_H__ +#define __RT711_SDCA_H__ + +#include +#include +#include +#include +#include +#include + +struct rt711_sdca_priv { + struct regmap *regmap, *mbq_regmap; + struct snd_soc_component *component; + struct sdw_slave *slave; + enum sdw_slave_status status; + struct sdw_bus_params params; + bool hw_init; + bool first_hw_init; + struct snd_soc_jack *hs_jack; + struct delayed_work jack_detect_work; + struct delayed_work jack_btn_check_work; + struct mutex calibrate_mutex; /* for headset calibration */ + int jack_type, jd_src; + unsigned int scp_sdca_stat1, scp_sdca_stat2; + int hw_ver; +}; + +struct sdw_stream_data { + struct sdw_stream_runtime *sdw_stream; +}; + +/* NID */ +#define RT711_AUDIO_FUNCTION_GROUP 0x01 +#define RT711_DAC_OUT2 0x03 +#define RT711_ADC_IN1 0x09 +#define RT711_ADC_IN2 0x08 +#define RT711_DMIC1 0x12 +#define RT711_DMIC2 0x13 +#define RT711_MIC2 0x19 +#define RT711_LINE1 0x1a +#define RT711_LINE2 0x1b +#define RT711_BEEP 0x1d +#define RT711_VENDOR_REG 0x20 +#define RT711_HP_OUT 0x21 +#define RT711_MIXER_IN1 0x22 +#define RT711_MIXER_IN2 0x23 +#define RT711_INLINE_CMD 0x55 +#define RT711_VENDOR_CALI 0x58 +#define RT711_VENDOR_IMS_DRE 0x5b +#define RT711_VENDOR_VAD 0x5e +#define RT711_VENDOR_ANALOG_CTL 0x5f +#define RT711_VENDOR_HDA_CTL 0x61 + +/* Index (NID:20h) */ +#define RT711_JD_PRODUCT_NUM 0x00 +#define RT711_DMIC_CTL1 0x06 +#define RT711_JD_CTL1 0x08 +#define RT711_JD_CTL2 0x09 +#define RT711_CC_DET1 0x11 +#define RT711_PARA_VERB_CTL 0x1a +#define RT711_COMBO_JACK_AUTO_CTL1 0x45 +#define RT711_COMBO_JACK_AUTO_CTL2 0x46 +#define RT711_COMBO_JACK_AUTO_CTL3 0x47 +#define RT711_INLINE_CMD_CTL 0x48 +#define RT711_DIGITAL_MISC_CTRL4 0x4a +#define RT711_JD_CTRL6 0x6a +#define RT711_VREFOUT_CTL 0x6b +#define RT711_GPIO_TEST_MODE_CTL2 0x6d +#define RT711_FSM_CTL 0x6f +#define RT711_IRQ_FLAG_TABLE1 0x80 +#define RT711_IRQ_FLAG_TABLE2 0x81 +#define RT711_IRQ_FLAG_TABLE3 0x82 +#define RT711_HP_FSM_CTL 0x83 +#define RT711_TX_RX_MUX_CTL 0x91 +#define RT711_FILTER_SRC_SEL 0xb0 +#define RT711_ADC27_VOL_SET 0xb7 + +/* Index (NID:58h) */ +#define RT711_DAC_DC_CALI_CTL1 0x00 +#define RT711_DAC_DC_CALI_CTL2 0x01 + +/* Index (NID:5bh) */ +#define RT711_IMS_DIGITAL_CTL1 0x00 +#define RT711_HP_IMS_RESULT_L 0x20 +#define RT711_HP_IMS_RESULT_R 0x21 + +/* Index (NID:5eh) */ +#define RT711_VAD_SRAM_CTL1 0x10 + +/* Index (NID:5fh) */ +#define RT711_MISC_POWER_CTL0 0x01 +#define RT711_MISC_POWER_CTL4 0x05 + +/* Index (NID:61h) */ +#define RT711_HDA_LEGACY_MUX_CTL1 0x00 +#define RT711_HDA_LEGACY_UNSOLICITED_CTL 0x03 +#define RT711_HDA_LEGACY_CONFIG_CTL 0x06 +#define RT711_HDA_LEGACY_RESET_CTL 0x08 +#define RT711_HDA_LEGACY_GPIO_CTL 0x0a +#define RT711_ADC08_09_PDE_CTL 0x24 +#define RT711_GE_MODE_RELATED_CTL 0x35 +#define RT711_PUSH_BTN_INT_CTL0 0x36 +#define RT711_PUSH_BTN_INT_CTL1 0x37 +#define RT711_PUSH_BTN_INT_CTL2 0x38 +#define RT711_PUSH_BTN_INT_CTL6 0x3c +#define RT711_PUSH_BTN_INT_CTL7 0x3d +#define RT711_PUSH_BTN_INT_CTL9 0x3f + +/* DAC DC offset calibration control-1 (0x00)(NID:20h) */ +#define RT711_DAC_DC_CALI_TRIGGER (0x1 << 15) +#define RT711_DAC_DC_CALI_CLK_EN (0x1 << 14) +#define RT711_DAC_DC_FORCE_CALI_RST (0x1 << 3) + +/* jack detect control 1 (0x08)(NID:20h) */ +#define RT711_JD2_DIGITAL_MODE_SEL (0x1 << 1) + +/* jack detect control 2 (0x09)(NID:20h) */ +#define RT711_JD2_2PORT_200K_DECODE_HP (0x1 << 13) +#define RT711_HP_JD_SEL_JD1 (0x0 << 1) +#define RT711_HP_JD_SEL_JD2 (0x1 << 1) + +/* CC DET1 (0x11)(NID:20h) */ +#define RT711_HP_JD_FINAL_RESULT_CTL_JD12 (0x1 << 10) +#define RT711_HP_JD_FINAL_RESULT_CTL_CCDET (0x0 << 10) + +/* Parameter & Verb control (0x1a)(NID:20h) */ +#define RT711_HIDDEN_REG_SW_RESET (0x1 << 14) + +/* combo jack auto switch control 2 (0x46)(NID:20h) */ +#define RT711_COMBOJACK_AUTO_DET_STATUS (0x1 << 11) +#define RT711_COMBOJACK_AUTO_DET_TRS (0x1 << 10) +#define RT711_COMBOJACK_AUTO_DET_CTIA (0x1 << 9) +#define RT711_COMBOJACK_AUTO_DET_OMTP (0x1 << 8) + +/* FSM control (0x6f)(NID:20h) */ +#define RT711_CALI_CTL (0x0 << 0) +#define RT711_COMBOJACK_CTL (0x1 << 0) +#define RT711_IMS_CTL (0x2 << 0) +#define RT711_DEPOP_CTL (0x3 << 0) +#define RT711_FSM_IMP_EN (0x1 << 6) + +/* Impedance Sense Digital Control 1 (0x00)(NID:5bh) */ +#define RT711_TRIGGER_IMS (0x1 << 15) +#define RT711_IMS_EN (0x1 << 6) + +#define RT711_EAPD_HIGH 0x2 +#define RT711_EAPD_LOW 0x0 +#define RT711_MUTE_SFT 7 +/* set input/output mapping to payload[14][15] separately */ +#define RT711_DIR_IN_SFT 6 +#define RT711_DIR_OUT_SFT 7 + +/* RC Calibration register */ +#define RT711_RC_CAL_STATUS 0x320c + +/* Buffer address for HID */ +#define RT711_BUF_ADDR_HID1 0x44030000 +#define RT711_BUF_ADDR_HID2 0x44030020 + +/* RT711 SDCA Control - function number */ +#define FUNC_NUM_JACK_CODEC 0x01 +#define FUNC_NUM_MIC_ARRAY 0x02 +#define FUNC_NUM_HID 0x03 + +/* RT711 SDCA entity */ +#define RT711_SDCA_ENT_HID01 0x01 +#define RT711_SDCA_ENT_GE49 0x49 +#define RT711_SDCA_ENT_USER_FU05 0x05 +#define RT711_SDCA_ENT_USER_FU0F 0x0f +#define RT711_SDCA_ENT_USER_FU1E 0x1e +#define RT711_SDCA_ENT_PLATFORM_FU15 0x15 +#define RT711_SDCA_ENT_PLATFORM_FU44 0x44 +#define RT711_SDCA_ENT_PDE28 0x28 +#define RT711_SDCA_ENT_PDE29 0x29 +#define RT711_SDCA_ENT_PDE2A 0x2a +#define RT711_SDCA_ENT_CS01 0x01 +#define RT711_SDCA_ENT_CS11 0x11 +#define RT711_SDCA_ENT_CS1F 0x1f +#define RT711_SDCA_ENT_OT1 0x06 +#define RT711_SDCA_ENT_LINE1 0x09 +#define RT711_SDCA_ENT_LINE2 0x31 +#define RT711_SDCA_ENT_PDELINE2 0x36 +#define RT711_SDCA_ENT_USER_FU9 0x41 + +/* RT711 SDCA control */ +#define RT711_SDCA_CTL_SAMPLE_FREQ_INDEX 0x10 +#define RT711_SDCA_CTL_FU_CH_GAIN 0x0b +#define RT711_SDCA_CTL_FU_MUTE 0x01 +#define RT711_SDCA_CTL_FU_VOLUME 0x02 +#define RT711_SDCA_CTL_HIDTX_CURRENT_OWNER 0x10 +#define RT711_SDCA_CTL_HIDTX_SET_OWNER_TO_DEVICE 0x11 +#define RT711_SDCA_CTL_HIDTX_MESSAGE_OFFSET 0x12 +#define RT711_SDCA_CTL_HIDTX_MESSAGE_LENGTH 0x13 +#define RT711_SDCA_CTL_SELECTED_MODE 0x01 +#define RT711_SDCA_CTL_DETECTED_MODE 0x02 +#define RT711_SDCA_CTL_REQ_POWER_STATE 0x01 +#define RT711_SDCA_CTL_VENDOR_DEF 0x30 + +/* RT711 SDCA channel */ +#define CH_L 0x01 +#define CH_R 0x02 + +/* sample frequency index */ +#define RT711_SDCA_RATE_44100HZ 0x08 +#define RT711_SDCA_RATE_48000HZ 0x09 +#define RT711_SDCA_RATE_96000HZ 0x0b +#define RT711_SDCA_RATE_192000HZ 0x0d + +enum { + RT711_AIF1, + RT711_AIF2, + RT711_AIFS, +}; + +enum rt711_sdca_jd_src { + RT711_JD_NULL, + RT711_JD1, + RT711_JD2 +}; + +enum rt711_sdca_ver { + RT711_VER_VD0, + RT711_VER_VD1 +}; + +int rt711_sdca_io_init(struct device *dev, struct sdw_slave *slave); +int rt711_sdca_init(struct device *dev, struct regmap *regmap, + struct regmap *mbq_regmap, struct sdw_slave *slave); + +int rt711_sdca_jack_detect(struct rt711_sdca_priv *rt711, bool *hp, bool *mic); +#endif /* __RT711_SDCA_H__ */ From ac922edc80aa0b83f4760e3086bc154fdc2a4837 Mon Sep 17 00:00:00 2001 From: Codrin Ciubotariu Date: Mon, 1 Mar 2021 19:09:05 +0200 Subject: [PATCH 0174/1091] ASoC: convert Microchip I2SMCC binding to yaml This patch converts the Microchip I2SMCC bindings to DT schema format using json-schema. Signed-off-by: Codrin Ciubotariu Reviewed-by: Rob Herring Link: https://lore.kernel.org/r/20210301170905.835091-8-codrin.ciubotariu@microchip.com Signed-off-by: Mark Brown --- .../bindings/sound/mchp,i2s-mcc.yaml | 108 ++++++++++++++++++ .../bindings/sound/mchp-i2s-mcc.txt | 49 -------- 2 files changed, 108 insertions(+), 49 deletions(-) create mode 100644 Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml delete mode 100644 Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt diff --git a/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml new file mode 100644 index 000000000000..0481315cb5f2 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mchp,i2s-mcc.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mchp,i2s-mcc.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Microchip I2S Multi-Channel Controller + +maintainers: + - Codrin Ciubotariu + +description: + The I2SMCC complies with the Inter-IC Sound (I2S) bus specification and + supports a Time Division Multiplexed (TDM) interface with external + multi-channel audio codecs. It consists of a receiver, a transmitter and a + common clock generator that can be enabled separately to provide Adapter, + Client or Controller modes with receiver and/or transmitter active. + On later I2SMCC versions (starting with Microchip's SAMA7G5) I2S + multi-channel is supported by using multiple data pins, output and + input, without TDM. + +properties: + "#sound-dai-cells": + const: 0 + + compatible: + enum: + - microchip,sam9x60-i2smcc + - microchip,sama7g5-i2smcc + + reg: + maxItems: 1 + + interrupts: + maxItems: 1 + + clocks: + items: + - description: Peripheral Bus Clock + - description: Generic Clock (Optional). Should be set mostly when Master + Mode is required. + minItems: 1 + + clock-names: + items: + - const: pclk + - const: gclk + minItems: 1 + + dmas: + items: + - description: TX DMA Channel + - description: RX DMA Channel + + dma-names: + items: + - const: tx + - const: rx + + microchip,tdm-data-pair: + description: + Represents the DIN/DOUT pair pins that are used to receive/send + TDM data. It is optional and it is only needed if the controller + uses the TDM mode. + $ref: /schemas/types.yaml#/definitions/uint8 + enum: [0, 1, 2, 3] + default: 0 + +if: + properties: + compatible: + const: microchip,sam9x60-i2smcc +then: + properties: + microchip,tdm-data-pair: false + +required: + - "#sound-dai-cells" + - compatible + - reg + - interrupts + - clocks + - clock-names + - dmas + - dma-names + +additionalProperties: false + +examples: + - | + #include + #include + + i2s@f001c000 { + #sound-dai-cells = <0>; + compatible = "microchip,sam9x60-i2smcc"; + reg = <0xf001c000 0x100>; + interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>; + dmas = <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(36))>, + <&dma0 (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | + AT91_XDMAC_DT_PERID(37))>; + dma-names = "tx", "rx"; + clocks = <&i2s_clk>, <&i2s_gclk>; + clock-names = "pclk", "gclk"; + pinctrl-names = "default"; + pinctrl-0 = <&pinctrl_i2s_default>; + }; diff --git a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt b/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt deleted file mode 100644 index af8fe3e657df..000000000000 --- a/Documentation/devicetree/bindings/sound/mchp-i2s-mcc.txt +++ /dev/null @@ -1,49 +0,0 @@ -* Microchip I2S Multi-Channel Controller - -Required properties: -- compatible: Should be "microchip,sam9x60-i2smcc" or - "microchip,sama7g5-i2smcc". -- reg: Should be the physical base address of the controller and the - length of memory mapped region. -- interrupts: Should contain the interrupt for the controller. -- dmas: Should be one per channel name listed in the dma-names property, - as described in atmel-dma.txt and dma.txt files. -- dma-names: Identifier string for each DMA request line in the dmas property. - Two dmas have to be defined, "tx" and "rx". -- clocks: Must contain an entry for each entry in clock-names. - Please refer to clock-bindings.txt. -- clock-names: Should be one of each entry matching the clocks phandles list: - - "pclk" (peripheral clock) Required. - - "gclk" (generated clock) Optional (1). - -Optional properties: -- pinctrl-0: Should specify pin control groups used for this controller. -- princtrl-names: Should contain only one value - "default". -- microchip,tdm-data-pair: 8 bit value that represents the DIN/DOUT pair pins - which are used to receive/send TDM data. It is optional - and it is only needed if the controller uses the TDM - mode. Not available for "microchip,sam9x60-i2smcc" - compatible. If it's not present, the default value is 0, - so the DIN/DOUT 0 pins are used. - -(1) : Only the peripheral clock is required. The generated clock is optional - and should be set mostly when Master Mode is required. - -Example: - - i2s@f001c000 { - compatible = "microchip,sam9x60-i2smcc"; - reg = <0xf001c000 0x100>; - interrupts = <34 IRQ_TYPE_LEVEL_HIGH 7>; - dmas = <&dma0 - (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | - AT91_XDMAC_DT_PERID(36))>, - <&dma0 - (AT91_XDMAC_DT_MEM_IF(0) | AT91_XDMAC_DT_PER_IF(1) | - AT91_XDMAC_DT_PERID(37))>; - dma-names = "tx", "rx"; - clocks = <&i2s_clk>, <&i2s_gclk>; - clock-names = "pclk", "gclk"; - pinctrl-names = "default"; - pinctrl-0 = <&pinctrl_i2s_default>; - }; From 2b869e0ea598263e0fd60872430899fa0660b2fa Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Sat, 6 Mar 2021 18:55:44 +0000 Subject: [PATCH 0175/1091] ASoC: cs42l42: Remove power if the driver is being removed Ensure the power supplies are turned off when removing the driver Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-7-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 811b7b1c9732..f61404de139b 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -25,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -1842,8 +1843,9 @@ static int cs42l42_i2c_remove(struct i2c_client *i2c_client) { struct cs42l42_private *cs42l42 = i2c_get_clientdata(i2c_client); - /* Hold down reset */ - gpiod_set_value_cansleep(cs42l42->reset_gpio, 0); + devm_free_irq(&i2c_client->dev, i2c_client->irq, cs42l42); + pm_runtime_suspend(&i2c_client->dev); + pm_runtime_disable(&i2c_client->dev); return 0; } From 1abca8e1c77bd9c5f5c0bed21c5b075b6852a178 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Sat, 6 Mar 2021 18:55:45 +0000 Subject: [PATCH 0176/1091] ASoC: cs42l42: Disable regulators if probe fails In case of cs42l42_i2c_probe() fail, the regulators were left enabled. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-8-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index f61404de139b..81cdd09d80bb 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -1750,8 +1750,10 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, /* Reset the Device */ cs42l42->reset_gpio = devm_gpiod_get_optional(&i2c_client->dev, "reset", GPIOD_OUT_LOW); - if (IS_ERR(cs42l42->reset_gpio)) - return PTR_ERR(cs42l42->reset_gpio); + if (IS_ERR(cs42l42->reset_gpio)) { + ret = PTR_ERR(cs42l42->reset_gpio); + goto err_disable; + } if (cs42l42->reset_gpio) { dev_dbg(&i2c_client->dev, "Found reset GPIO\n"); @@ -1785,13 +1787,13 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, dev_err(&i2c_client->dev, "CS42L42 Device ID (%X). Expected %X\n", devid, CS42L42_CHIP_ID); - return ret; + goto err_disable; } ret = regmap_read(cs42l42->regmap, CS42L42_REVID, ®); if (ret < 0) { dev_err(&i2c_client->dev, "Get Revision ID failed\n"); - return ret; + goto err_disable; } dev_info(&i2c_client->dev, @@ -1817,7 +1819,7 @@ static int cs42l42_i2c_probe(struct i2c_client *i2c_client, if (i2c_client->dev.of_node) { ret = cs42l42_handle_device_data(i2c_client, cs42l42); if (ret != 0) - return ret; + goto err_disable; } /* Setup headset detection */ From 621d65f3b868611df62ae4dc4eb1a37b85e4e8c0 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Sat, 6 Mar 2021 18:55:46 +0000 Subject: [PATCH 0177/1091] ASoC: cs42l42: Provide finer control on playback path Removing cs42l42_hpdrv_evt that enables the entire chain and replace by a set of widgets that can better define the codec Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-9-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 65 +++++++++++++------------------------- sound/soc/codecs/cs42l42.h | 8 ++--- 2 files changed, 26 insertions(+), 47 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 81cdd09d80bb..0b5c8e4afff0 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -462,54 +462,33 @@ static const struct snd_kcontrol_new cs42l42_snd_controls[] = { 0x3f, 1, mixer_tlv) }; -static int cs42l42_hpdrv_evt(struct snd_soc_dapm_widget *w, - struct snd_kcontrol *kcontrol, int event) -{ - struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); - - if (event & SND_SOC_DAPM_POST_PMU) { - /* Enable the channels */ - snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_EN, - CS42L42_ASP_RX0_CH_EN_MASK, - (CS42L42_ASP_RX0_CH1_EN | - CS42L42_ASP_RX0_CH2_EN) << - CS42L42_ASP_RX0_CH_EN_SHIFT); - - /* Power up */ - snd_soc_component_update_bits(component, CS42L42_PWR_CTL1, - CS42L42_ASP_DAI_PDN_MASK | CS42L42_MIXER_PDN_MASK | - CS42L42_HP_PDN_MASK, 0); - } else if (event & SND_SOC_DAPM_PRE_PMD) { - /* Disable the channels */ - snd_soc_component_update_bits(component, CS42L42_ASP_RX_DAI0_EN, - CS42L42_ASP_RX0_CH_EN_MASK, 0); - - /* Power down */ - snd_soc_component_update_bits(component, CS42L42_PWR_CTL1, - CS42L42_ASP_DAI_PDN_MASK | CS42L42_MIXER_PDN_MASK | - CS42L42_HP_PDN_MASK, - CS42L42_ASP_DAI_PDN_MASK | CS42L42_MIXER_PDN_MASK | - CS42L42_HP_PDN_MASK); - } else { - dev_err(component->dev, "Invalid event 0x%x\n", event); - } - return 0; -} - static const struct snd_soc_dapm_widget cs42l42_dapm_widgets[] = { + /* Playback Path */ SND_SOC_DAPM_OUTPUT("HP"), - SND_SOC_DAPM_AIF_IN("SDIN", NULL, 0, CS42L42_ASP_CLK_CFG, - CS42L42_ASP_SCLK_EN_SHIFT, false), - SND_SOC_DAPM_OUT_DRV_E("HPDRV", SND_SOC_NOPM, 0, - 0, NULL, 0, cs42l42_hpdrv_evt, - SND_SOC_DAPM_POST_PMU | - SND_SOC_DAPM_PRE_PMD) + SND_SOC_DAPM_DAC("DAC", NULL, CS42L42_PWR_CTL1, CS42L42_HP_PDN_SHIFT, 1), + SND_SOC_DAPM_MIXER("MIXER", CS42L42_PWR_CTL1, CS42L42_MIXER_PDN_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_AIF_IN("SDIN1", NULL, 0, CS42L42_ASP_RX_DAI0_EN, CS42L42_ASP_RX0_CH1_SHIFT, 0), + SND_SOC_DAPM_AIF_IN("SDIN2", NULL, 1, CS42L42_ASP_RX_DAI0_EN, CS42L42_ASP_RX0_CH2_SHIFT, 0), + + /* Playback Requirements */ + SND_SOC_DAPM_SUPPLY("ASP DAI0", CS42L42_PWR_CTL1, CS42L42_ASP_DAI_PDN_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("SCLK", CS42L42_ASP_CLK_CFG, CS42L42_ASP_SCLK_EN_SHIFT, 0, NULL, 0), }; static const struct snd_soc_dapm_route cs42l42_audio_map[] = { - {"SDIN", NULL, "Playback"}, - {"HPDRV", NULL, "SDIN"}, - {"HP", NULL, "HPDRV"} + /* Playback Path */ + {"HP", NULL, "DAC"}, + {"DAC", NULL, "MIXER"}, + {"MIXER", NULL, "SDIN1"}, + {"MIXER", NULL, "SDIN2"}, + {"SDIN1", NULL, "Playback"}, + {"SDIN2", NULL, "Playback"}, + + /* Playback Requirements */ + {"SDIN1", NULL, "ASP DAI0"}, + {"SDIN2", NULL, "ASP DAI0"}, + {"SDIN1", NULL, "SCLK"}, + {"SDIN2", NULL, "SCLK"}, }; static int cs42l42_component_probe(struct snd_soc_component *component) diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 866d7c873e3c..4b448c102f53 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -695,10 +695,10 @@ #define CS42L42_ASP_RX_DAI0_EN (CS42L42_PAGE_2A + 0x01) #define CS42L42_ASP_RX0_CH_EN_SHIFT 2 #define CS42L42_ASP_RX0_CH_EN_MASK (0xf << CS42L42_ASP_RX0_CH_EN_SHIFT) -#define CS42L42_ASP_RX0_CH1_EN 1 -#define CS42L42_ASP_RX0_CH2_EN 2 -#define CS42L42_ASP_RX0_CH3_EN 4 -#define CS42L42_ASP_RX0_CH4_EN 8 +#define CS42L42_ASP_RX0_CH1_SHIFT 2 +#define CS42L42_ASP_RX0_CH2_SHIFT 3 +#define CS42L42_ASP_RX0_CH3_SHIFT 4 +#define CS42L42_ASP_RX0_CH4_SHIFT 5 #define CS42L42_ASP_RX_DAI0_CH1_AP_RES (CS42L42_PAGE_2A + 0x02) #define CS42L42_ASP_RX_DAI0_CH1_BIT_MSB (CS42L42_PAGE_2A + 0x03) From 43fc357199f90c0e6ee7082fb0a989b0560be2d6 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Sat, 6 Mar 2021 18:55:47 +0000 Subject: [PATCH 0178/1091] ASoC: cs42l42: Set clock source for both ways of stream Move the enable/disable of clocks to cs42l42_mute_stream so the record path also get clocks. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-10-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 86 +++++++++++++++++++++----------------- sound/soc/codecs/cs42l42.h | 1 + 2 files changed, 49 insertions(+), 38 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 0b5c8e4afff0..2dca55dfa46d 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -784,52 +784,63 @@ static int cs42l42_set_sysclk(struct snd_soc_dai *dai, return 0; } -static int cs42l42_mute(struct snd_soc_dai *dai, int mute, int direction) +static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) { struct snd_soc_component *component = dai->component; + struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); unsigned int regval; u8 fullScaleVol; if (mute) { - /* Mark SCLK as not present to turn on the internal - * oscillator. - */ - snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, - CS42L42_SCLK_PRESENT_MASK, 0); - - snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, - CS42L42_PLL_START_MASK, - 0 << CS42L42_PLL_START_SHIFT); - /* Mute the headphone */ - snd_soc_component_update_bits(component, CS42L42_HP_CTL, - CS42L42_HP_ANA_AMUTE_MASK | - CS42L42_HP_ANA_BMUTE_MASK, - CS42L42_HP_ANA_AMUTE_MASK | - CS42L42_HP_ANA_BMUTE_MASK); - } else { - snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, - CS42L42_PLL_START_MASK, - 1 << CS42L42_PLL_START_SHIFT); - /* Read the headphone load */ - regval = snd_soc_component_read(component, CS42L42_LOAD_DET_RCSTAT); - if (((regval & CS42L42_RLA_STAT_MASK) >> - CS42L42_RLA_STAT_SHIFT) == CS42L42_RLA_STAT_15_OHM) { - fullScaleVol = CS42L42_HP_FULL_SCALE_VOL_MASK; - } else { - fullScaleVol = 0; + if (stream == SNDRV_PCM_STREAM_PLAYBACK) + snd_soc_component_update_bits(component, CS42L42_HP_CTL, + CS42L42_HP_ANA_AMUTE_MASK | + CS42L42_HP_ANA_BMUTE_MASK, + CS42L42_HP_ANA_AMUTE_MASK | + CS42L42_HP_ANA_BMUTE_MASK); + + cs42l42->stream_use &= ~(1 << stream); + if(!cs42l42->stream_use) { + /* + * Switch to the internal oscillator. + * SCLK must remain running until after this clock switch. + * Without a source of clock the I2C bus doesn't work. + */ + snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, + CS42L42_SCLK_PRESENT_MASK, 0); + snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, + CS42L42_PLL_START_MASK, 0); } + } else { + if (!cs42l42->stream_use) { + /* SCLK must be running before codec unmute */ + snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, + CS42L42_PLL_START_MASK, 1); - /* Un-mute the headphone, set the full scale volume flag */ - snd_soc_component_update_bits(component, CS42L42_HP_CTL, - CS42L42_HP_ANA_AMUTE_MASK | - CS42L42_HP_ANA_BMUTE_MASK | - CS42L42_HP_FULL_SCALE_VOL_MASK, fullScaleVol); + /* Mark SCLK as present, turn off internal oscillator */ + snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, + CS42L42_SCLK_PRESENT_MASK, + CS42L42_SCLK_PRESENT_MASK); + } + cs42l42->stream_use |= 1 << stream; - /* Mark SCLK as present, turn off internal oscillator */ - snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, - CS42L42_SCLK_PRESENT_MASK, - CS42L42_SCLK_PRESENT_MASK); + if (stream == SNDRV_PCM_STREAM_PLAYBACK) { + /* Read the headphone load */ + regval = snd_soc_component_read(component, CS42L42_LOAD_DET_RCSTAT); + if (((regval & CS42L42_RLA_STAT_MASK) >> CS42L42_RLA_STAT_SHIFT) == + CS42L42_RLA_STAT_15_OHM) { + fullScaleVol = CS42L42_HP_FULL_SCALE_VOL_MASK; + } else { + fullScaleVol = 0; + } + + /* Un-mute the headphone, set the full scale volume flag */ + snd_soc_component_update_bits(component, CS42L42_HP_CTL, + CS42L42_HP_ANA_AMUTE_MASK | + CS42L42_HP_ANA_BMUTE_MASK | + CS42L42_HP_FULL_SCALE_VOL_MASK, fullScaleVol); + } } return 0; @@ -844,8 +855,7 @@ static const struct snd_soc_dai_ops cs42l42_ops = { .hw_params = cs42l42_pcm_hw_params, .set_fmt = cs42l42_set_dai_fmt, .set_sysclk = cs42l42_set_sysclk, - .mute_stream = cs42l42_mute, - .no_capture_mute = 1, + .mute_stream = cs42l42_mute_stream, }; static struct snd_soc_dai_driver cs42l42_dai = { diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 4b448c102f53..3dcbfebc53b0 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -768,6 +768,7 @@ struct cs42l42_private { u8 bias_thresholds[CS42L42_NUM_BIASES]; u8 hs_bias_ramp_rate; u8 hs_bias_ramp_time; + u8 stream_use; }; #endif /* __CS42L42_H__ */ From 585e7079de0eac555bcdfe6284e439ee05fb18cb Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Sat, 6 Mar 2021 18:55:48 +0000 Subject: [PATCH 0179/1091] ASoC: cs42l42: Add Capture Support Add support for capture path on headseat pins Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-11-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 39 ++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/cs42l42.h | 12 ++++++++++++ 2 files changed, 51 insertions(+) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 2dca55dfa46d..b5084681aaab 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -472,6 +472,18 @@ static const struct snd_soc_dapm_widget cs42l42_dapm_widgets[] = { /* Playback Requirements */ SND_SOC_DAPM_SUPPLY("ASP DAI0", CS42L42_PWR_CTL1, CS42L42_ASP_DAI_PDN_SHIFT, 1, NULL, 0), + + /* Capture Path */ + SND_SOC_DAPM_INPUT("HS"), + SND_SOC_DAPM_ADC("ADC", NULL, CS42L42_PWR_CTL1, CS42L42_ADC_PDN_SHIFT, 1), + SND_SOC_DAPM_AIF_OUT("SDOUT1", NULL, 0, CS42L42_ASP_TX_CH_EN, CS42L42_ASP_TX0_CH1_SHIFT, 0), + SND_SOC_DAPM_AIF_OUT("SDOUT2", NULL, 1, CS42L42_ASP_TX_CH_EN, CS42L42_ASP_TX0_CH2_SHIFT, 0), + + /* Capture Requirements */ + SND_SOC_DAPM_SUPPLY("ASP DAO0", CS42L42_PWR_CTL1, CS42L42_ASP_DAO_PDN_SHIFT, 1, NULL, 0), + SND_SOC_DAPM_SUPPLY("ASP TX EN", CS42L42_ASP_TX_SZ_EN, CS42L42_ASP_TX_EN_SHIFT, 0, NULL, 0), + + /* Playback/Capture Requirements */ SND_SOC_DAPM_SUPPLY("SCLK", CS42L42_ASP_CLK_CFG, CS42L42_ASP_SCLK_EN_SHIFT, 0, NULL, 0), }; @@ -489,6 +501,21 @@ static const struct snd_soc_dapm_route cs42l42_audio_map[] = { {"SDIN2", NULL, "ASP DAI0"}, {"SDIN1", NULL, "SCLK"}, {"SDIN2", NULL, "SCLK"}, + + /* Capture Path */ + {"ADC", NULL, "HS"}, + { "SDOUT1", NULL, "ADC" }, + { "SDOUT2", NULL, "ADC" }, + { "Capture", NULL, "SDOUT1" }, + { "Capture", NULL, "SDOUT2" }, + + /* Capture Requirements */ + { "SDOUT1", NULL, "ASP DAO0" }, + { "SDOUT2", NULL, "ASP DAO0" }, + { "SDOUT1", NULL, "SCLK" }, + { "SDOUT2", NULL, "SCLK" }, + { "SDOUT1", NULL, "ASP TX EN" }, + { "SDOUT2", NULL, "ASP TX EN" }, }; static int cs42l42_component_probe(struct snd_soc_component *component) @@ -748,12 +775,24 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream, { struct snd_soc_component *component = dai->component; struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); + unsigned int channels = params_channels(params); unsigned int width = (params_width(params) / 8) - 1; unsigned int val = 0; cs42l42->srate = params_rate(params); switch(substream->stream) { + case SNDRV_PCM_STREAM_CAPTURE: + if (channels == 2) { + val |= CS42L42_ASP_TX_CH2_AP_MASK; + val |= width << CS42L42_ASP_TX_CH2_RES_SHIFT; + } + val |= width << CS42L42_ASP_TX_CH1_RES_SHIFT; + + snd_soc_component_update_bits(component, CS42L42_ASP_TX_CH_AP_RES, + CS42L42_ASP_TX_CH1_AP_MASK | CS42L42_ASP_TX_CH2_AP_MASK | + CS42L42_ASP_TX_CH2_RES_MASK | CS42L42_ASP_TX_CH1_RES_MASK, val); + break; case SNDRV_PCM_STREAM_PLAYBACK: val |= width << CS42L42_ASP_RX_CH_RES_SHIFT; /* channel 1 on low LRCLK */ diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 3dcbfebc53b0..c373259ed46f 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -683,8 +683,20 @@ /* Page 0x29 Serial Port TX Registers */ #define CS42L42_ASP_TX_SZ_EN (CS42L42_PAGE_29 + 0x01) +#define CS42L42_ASP_TX_EN_SHIFT 0 #define CS42L42_ASP_TX_CH_EN (CS42L42_PAGE_29 + 0x02) +#define CS42L42_ASP_TX0_CH2_SHIFT 1 +#define CS42L42_ASP_TX0_CH1_SHIFT 0 + #define CS42L42_ASP_TX_CH_AP_RES (CS42L42_PAGE_29 + 0x03) +#define CS42L42_ASP_TX_CH1_AP_SHIFT 7 +#define CS42L42_ASP_TX_CH1_AP_MASK (1 << CS42L42_ASP_TX_CH1_AP_SHIFT) +#define CS42L42_ASP_TX_CH2_AP_SHIFT 6 +#define CS42L42_ASP_TX_CH2_AP_MASK (1 << CS42L42_ASP_TX_CH2_AP_SHIFT) +#define CS42L42_ASP_TX_CH2_RES_SHIFT 2 +#define CS42L42_ASP_TX_CH2_RES_MASK (3 << CS42L42_ASP_TX_CH2_RES_SHIFT) +#define CS42L42_ASP_TX_CH1_RES_SHIFT 0 +#define CS42L42_ASP_TX_CH1_RES_MASK (3 << CS42L42_ASP_TX_CH1_RES_SHIFT) #define CS42L42_ASP_TX_CH1_BIT_MSB (CS42L42_PAGE_29 + 0x04) #define CS42L42_ASP_TX_CH1_BIT_LSB (CS42L42_PAGE_29 + 0x05) #define CS42L42_ASP_TX_HIZ_DLY_CFG (CS42L42_PAGE_29 + 0x06) From c5b8ee0879bcdc5082d42fe92d3c235b74feef37 Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Sat, 6 Mar 2021 18:55:49 +0000 Subject: [PATCH 0180/1091] ASoC: cs42l42: Report jack and button detection Report the Jack events to the user space through ALSA. Also moves request_threaded_irq() to component_probe so it don't get interrupts before the initialization the struct snd_soc_jack. Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-12-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 70 ++++++++++++++++++++++++++++++-------- sound/soc/codecs/cs42l42.h | 3 ++ 2 files changed, 59 insertions(+), 14 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index b5084681aaab..594bf2252103 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -522,10 +522,18 @@ static int cs42l42_component_probe(struct snd_soc_component *component) { struct cs42l42_private *cs42l42 = (struct cs42l42_private *)snd_soc_component_get_drvdata(component); + struct snd_soc_card *crd = component->card; + int ret = 0; cs42l42->component = component; - return 0; + ret = snd_soc_card_jack_new(crd, "CS42L42 Headset", SND_JACK_HEADSET | SND_JACK_BTN_0 | + SND_JACK_BTN_1 | SND_JACK_BTN_2 | SND_JACK_BTN_3, + &cs42l42->jack, NULL, 0); + if (ret < 0) + dev_err(component->dev, "Cannot create CS42L42 Headset: %d\n", ret); + + return ret; } static const struct snd_soc_component_driver soc_component_dev_cs42l42 = { @@ -1198,7 +1206,7 @@ static void cs42l42_cancel_hs_type_detect(struct cs42l42_private *cs42l42) (3 << CS42L42_HSDET_AUTO_TIME_SHIFT)); } -static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42) +static int cs42l42_handle_button_press(struct cs42l42_private *cs42l42) { int bias_level; unsigned int detect_status; @@ -1241,17 +1249,24 @@ static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42) switch (bias_level) { case 1: /* Function C button press */ + bias_level = SND_JACK_BTN_2; dev_dbg(cs42l42->component->dev, "Function C button press\n"); break; case 2: /* Function B button press */ + bias_level = SND_JACK_BTN_1; dev_dbg(cs42l42->component->dev, "Function B button press\n"); break; case 3: /* Function D button press */ + bias_level = SND_JACK_BTN_3; dev_dbg(cs42l42->component->dev, "Function D button press\n"); break; case 4: /* Function A button press */ + bias_level = SND_JACK_BTN_0; dev_dbg(cs42l42->component->dev, "Function A button press\n"); break; + default: + bias_level = 0; + break; } /* Set button detect level sensitivity back to default */ @@ -1281,6 +1296,8 @@ static void cs42l42_handle_button_press(struct cs42l42_private *cs42l42) (0 << CS42L42_M_HSBIAS_HIZ_SHIFT) | (1 << CS42L42_M_SHORT_RLS_SHIFT) | (1 << CS42L42_M_SHORT_DET_SHIFT)); + + return bias_level; } struct cs42l42_irq_params { @@ -1325,6 +1342,8 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data) unsigned int current_plug_status; unsigned int current_button_status; unsigned int i; + int report = 0; + /* Read sticky registers to clear interurpt */ for (i = 0; i < ARRAY_SIZE(stickies); i++) { @@ -1351,9 +1370,20 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data) if ((~masks[5]) & irq_params_table[5].mask) { if (stickies[5] & CS42L42_HSDET_AUTO_DONE_MASK) { cs42l42_process_hs_type_detect(cs42l42); - dev_dbg(component->dev, - "Auto detect done (%d)\n", - cs42l42->hs_type); + switch(cs42l42->hs_type){ + case CS42L42_PLUG_CTIA: + case CS42L42_PLUG_OMTP: + snd_soc_jack_report(&cs42l42->jack, SND_JACK_HEADSET, + SND_JACK_HEADSET); + break; + case CS42L42_PLUG_HEADPHONE: + snd_soc_jack_report(&cs42l42->jack, SND_JACK_HEADPHONE, + SND_JACK_HEADPHONE); + break; + default: + break; + } + dev_dbg(component->dev, "Auto detect done (%d)\n", cs42l42->hs_type); } } @@ -1371,8 +1401,19 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data) if (cs42l42->plug_state != CS42L42_TS_UNPLUG) { cs42l42->plug_state = CS42L42_TS_UNPLUG; cs42l42_cancel_hs_type_detect(cs42l42); - dev_dbg(component->dev, - "Unplug event\n"); + + switch(cs42l42->hs_type){ + case CS42L42_PLUG_CTIA: + case CS42L42_PLUG_OMTP: + snd_soc_jack_report(&cs42l42->jack, 0, SND_JACK_HEADSET); + break; + case CS42L42_PLUG_HEADPHONE: + snd_soc_jack_report(&cs42l42->jack, 0, SND_JACK_HEADPHONE); + break; + default: + break; + } + dev_dbg(component->dev, "Unplug event\n"); } break; @@ -1387,14 +1428,15 @@ static irqreturn_t cs42l42_irq_thread(int irq, void *data) if (!(current_button_status & CS42L42_M_HSBIAS_HIZ_MASK)) { - if (current_button_status & - CS42L42_M_DETECT_TF_MASK) { - dev_dbg(component->dev, - "Button released\n"); - } else if (current_button_status & - CS42L42_M_DETECT_FT_MASK) { - cs42l42_handle_button_press(cs42l42); + if (current_button_status & CS42L42_M_DETECT_TF_MASK) { + dev_dbg(component->dev, "Button released\n"); + report = 0; + } else if (current_button_status & CS42L42_M_DETECT_FT_MASK) { + report = cs42l42_handle_button_press(cs42l42); + } + snd_soc_jack_report(&cs42l42->jack, report, SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3); } } diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index c373259ed46f..e12828877a20 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -12,6 +12,8 @@ #ifndef __CS42L42_H__ #define __CS42L42_H__ +#include + #define CS42L42_PAGE_REGISTER 0x00 /* Page Select Register */ #define CS42L42_WIN_START 0x00 #define CS42L42_WIN_LEN 0x100 @@ -768,6 +770,7 @@ struct cs42l42_private { struct regulator_bulk_data supplies[CS42L42_NUM_SUPPLIES]; struct gpio_desc *reset_gpio; struct completion pdn_done; + struct snd_soc_jack jack; u32 sclk; u32 srate; u8 plug_state; From 2cdba9b045c745139ae56227d71f261f5d3c6fae Mon Sep 17 00:00:00 2001 From: Lucas Tanure Date: Sat, 6 Mar 2021 18:55:50 +0000 Subject: [PATCH 0181/1091] ASoC: cs42l42: Use bclk from hw_params if set_sysclk was not called Add support for reading the source clock from snd_soc_params_to_bclk so the machine driver is not required to call cs42l42_set_sysclk Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-13-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 17 +++++++++++++---- sound/soc/codecs/cs42l42.h | 1 + 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 594bf2252103..68b7ed71ad54 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -588,10 +588,16 @@ static int cs42l42_pll_config(struct snd_soc_component *component) { struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); int i; + u32 clk; u32 fsync; + if (!cs42l42->sclk) + clk = cs42l42->bclk; + else + clk = cs42l42->sclk; + for (i = 0; i < ARRAY_SIZE(pll_ratio_table); i++) { - if (pll_ratio_table[i].sclk == cs42l42->sclk) { + if (pll_ratio_table[i].sclk == clk) { /* Configure the internal sample rate */ snd_soc_component_update_bits(component, CS42L42_MCLK_CTL, CS42L42_INTERNAL_FS_MASK, @@ -611,12 +617,12 @@ static int cs42l42_pll_config(struct snd_soc_component *component) (pll_ratio_table[i].mclk_div << CS42L42_MCLKDIV_SHIFT)); /* Set up the LRCLK */ - fsync = cs42l42->sclk / cs42l42->srate; - if (((fsync * cs42l42->srate) != cs42l42->sclk) + fsync = clk / cs42l42->srate; + if (((fsync * cs42l42->srate) != clk) || ((fsync % 2) != 0)) { dev_err(component->dev, "Unsupported sclk %d/sample rate %d\n", - cs42l42->sclk, + clk, cs42l42->srate); return -EINVAL; } @@ -788,6 +794,7 @@ static int cs42l42_pcm_hw_params(struct snd_pcm_substream *substream, unsigned int val = 0; cs42l42->srate = params_rate(params); + cs42l42->bclk = snd_soc_params_to_bclk(params); switch(substream->stream) { case SNDRV_PCM_STREAM_CAPTURE: @@ -921,6 +928,8 @@ static struct snd_soc_dai_driver cs42l42_dai = { .rates = SNDRV_PCM_RATE_8000_192000, .formats = CS42L42_FORMATS, }, + .symmetric_rate = 1, + .symmetric_sample_bits = 1, .ops = &cs42l42_ops, }; diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index e12828877a20..429c6833fc81 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -771,6 +771,7 @@ struct cs42l42_private { struct gpio_desc *reset_gpio; struct completion pdn_done; struct snd_soc_jack jack; + int bclk; u32 sclk; u32 srate; u8 plug_state; From 0ea23660c7170124fc06ec363b4d2adfa350cf2f Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Sat, 6 Mar 2021 18:55:51 +0000 Subject: [PATCH 0182/1091] ASoC: cs42l42: Wait at least 150us after writing SCLK_PRESENT There must be a delay of at least 150us after writing SCLK_PRESENT before issuing another I2C write. This is done using struct reg_sequence because it can specify a delay after the write and the whole sequence is written atomically. Signed-off-by: Richard Fitzgerald Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-14-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 27 ++++++++++++++++++++++----- sound/soc/codecs/cs42l42.h | 1 + 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 68b7ed71ad54..08718fd10fb9 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -549,6 +549,24 @@ static const struct snd_soc_component_driver soc_component_dev_cs42l42 = { .non_legacy_dai_naming = 1, }; +/* Switch to SCLK. Atomic delay after the write to allow the switch to complete. */ +static const struct reg_sequence cs42l42_to_sclk_seq[] = { + { + .reg = CS42L42_OSC_SWITCH, + .def = CS42L42_SCLK_PRESENT_MASK, + .delay_us = CS42L42_CLOCK_SWITCH_DELAY_US, + }, +}; + +/* Switch to OSC. Atomic delay after the write to allow the switch to complete. */ +static const struct reg_sequence cs42l42_to_osc_seq[] = { + { + .reg = CS42L42_OSC_SWITCH, + .def = 0, + .delay_us = CS42L42_CLOCK_SWITCH_DELAY_US, + }, +}; + struct cs42l42_pll_params { u32 sclk; u8 mclk_div; @@ -861,8 +879,8 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) * SCLK must remain running until after this clock switch. * Without a source of clock the I2C bus doesn't work. */ - snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, - CS42L42_SCLK_PRESENT_MASK, 0); + regmap_multi_reg_write(cs42l42->regmap, cs42l42_to_osc_seq, + ARRAY_SIZE(cs42l42_to_osc_seq)); snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, CS42L42_PLL_START_MASK, 0); } @@ -873,9 +891,8 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) CS42L42_PLL_START_MASK, 1); /* Mark SCLK as present, turn off internal oscillator */ - snd_soc_component_update_bits(component, CS42L42_OSC_SWITCH, - CS42L42_SCLK_PRESENT_MASK, - CS42L42_SCLK_PRESENT_MASK); + regmap_multi_reg_write(cs42l42->regmap, cs42l42_to_sclk_seq, + ARRAY_SIZE(cs42l42_to_sclk_seq)); } cs42l42->stream_use |= 1 << stream; diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 429c6833fc81..214cee762709 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -755,6 +755,7 @@ #define CS42L42_NUM_SUPPLIES 5 #define CS42L42_BOOT_TIME_US 3000 +#define CS42L42_CLOCK_SWITCH_DELAY_US 150 static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = { "VA", From 882589bb707ba78d25dd193beefde97e00a3da6b Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Sat, 6 Mar 2021 18:55:52 +0000 Subject: [PATCH 0183/1091] ASoC: cs42l42: Only start PLL if it is needed The PLL is only needed for sclk < 11289600 Hz and cs42l42_pll_config() will not configure it for higher rates. So it must only be enabled when it is needed. Signed-off-by: Richard Fitzgerald Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-15-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index 08718fd10fb9..d7a314aa59b7 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -887,8 +887,9 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) } else { if (!cs42l42->stream_use) { /* SCLK must be running before codec unmute */ - snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, - CS42L42_PLL_START_MASK, 1); + if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) + snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, + CS42L42_PLL_START_MASK, 1); /* Mark SCLK as present, turn off internal oscillator */ regmap_multi_reg_write(cs42l42->regmap, cs42l42_to_sclk_seq, From b7d00776ebf79402216434ce24a87f072e1438e1 Mon Sep 17 00:00:00 2001 From: Richard Fitzgerald Date: Sat, 6 Mar 2021 18:55:53 +0000 Subject: [PATCH 0184/1091] ASoC: cs42l42: Wait for PLL to lock before switching to it The PLL should have locked before using it to supply MCLK. Signed-off-by: Richard Fitzgerald Signed-off-by: Lucas Tanure Link: https://lore.kernel.org/r/20210306185553.62053-16-tanureal@opensource.cirrus.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs42l42.c | 12 +++++++++++- sound/soc/codecs/cs42l42.h | 2 ++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs42l42.c b/sound/soc/codecs/cs42l42.c index d7a314aa59b7..bf982e145e94 100644 --- a/sound/soc/codecs/cs42l42.c +++ b/sound/soc/codecs/cs42l42.c @@ -862,6 +862,7 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) struct cs42l42_private *cs42l42 = snd_soc_component_get_drvdata(component); unsigned int regval; u8 fullScaleVol; + int ret; if (mute) { /* Mute the headphone */ @@ -887,9 +888,18 @@ static int cs42l42_mute_stream(struct snd_soc_dai *dai, int mute, int stream) } else { if (!cs42l42->stream_use) { /* SCLK must be running before codec unmute */ - if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) + if ((cs42l42->bclk < 11289600) && (cs42l42->sclk < 11289600)) { snd_soc_component_update_bits(component, CS42L42_PLL_CTL1, CS42L42_PLL_START_MASK, 1); + ret = regmap_read_poll_timeout(cs42l42->regmap, + CS42L42_PLL_LOCK_STATUS, + regval, + (regval & 1), + CS42L42_PLL_LOCK_POLL_US, + CS42L42_PLL_LOCK_TIMEOUT_US); + if (ret < 0) + dev_warn(component->dev, "PLL failed to lock: %d\n", ret); + } /* Mark SCLK as present, turn off internal oscillator */ regmap_multi_reg_write(cs42l42->regmap, cs42l42_to_sclk_seq, diff --git a/sound/soc/codecs/cs42l42.h b/sound/soc/codecs/cs42l42.h index 214cee762709..36b763f0d1a0 100644 --- a/sound/soc/codecs/cs42l42.h +++ b/sound/soc/codecs/cs42l42.h @@ -756,6 +756,8 @@ #define CS42L42_NUM_SUPPLIES 5 #define CS42L42_BOOT_TIME_US 3000 #define CS42L42_CLOCK_SWITCH_DELAY_US 150 +#define CS42L42_PLL_LOCK_POLL_US 250 +#define CS42L42_PLL_LOCK_TIMEOUT_US 1250 static const char *const cs42l42_supply_names[CS42L42_NUM_SUPPLIES] = { "VA", From d3223608c5bcd938bcf751702ebf4a8b130976da Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 9 Mar 2021 13:14:58 +0000 Subject: [PATCH 0185/1091] ASoC: rt715-sdca: Fix return value check in rt715_sdca_sdw_probe() In case of error, the function devm_regmap_init_sdw_mbq() and devm_regmap_init_sdw() returns ERR_PTR() not NULL. The NULL test in the return value check should be replaced with IS_ERR(). Fixes: 393c52d2d109 ("ASoC: rt715-sdca: Add RT715 sdca vendor-specific driver") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20210309131458.1884899-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca-sdw.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt715-sdca-sdw.c b/sound/soc/codecs/rt715-sdca-sdw.c index bcced85876b0..1350798406f0 100644 --- a/sound/soc/codecs/rt715-sdca-sdw.c +++ b/sound/soc/codecs/rt715-sdca-sdw.c @@ -184,12 +184,12 @@ static int rt715_sdca_sdw_probe(struct sdw_slave *slave, /* Regmap Initialization */ mbq_regmap = devm_regmap_init_sdw_mbq(slave, &rt715_sdca_mbq_regmap); - if (!mbq_regmap) - return -EINVAL; + if (IS_ERR(mbq_regmap)) + return PTR_ERR(mbq_regmap); regmap = devm_regmap_init_sdw(slave, &rt715_sdca_regmap); - if (!regmap) - return -EINVAL; + if (IS_ERR(regmap)) + return PTR_ERR(regmap); return rt715_sdca_init(&slave->dev, mbq_regmap, regmap, slave); } From d59cfc6544dc19a1d1c1e47d95dd2150da3daf56 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Tue, 9 Mar 2021 13:14:55 +0000 Subject: [PATCH 0186/1091] ASoC: rt715-sdca: Remove unused including Remove including that don't need it. Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20210309131455.1883120-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 92ad6fa408ec..20528afbdc57 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include From 542712826f8d3b0a72e66d7feec2dedba5dfa297 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Tue, 9 Mar 2021 16:58:27 +0800 Subject: [PATCH 0187/1091] ASoC: rt5682: add delay time of workqueue to control next IRQ event This patch keeps the delay time (50 ms) for jack detection and zero delay time for the button press. This patch improves the reaction of the button press. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210309085827.32032-1-shumingf@realtek.com Tested-by Curtis Malainey Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682-i2c.c | 2 +- sound/soc/codecs/rt5682-sdw.c | 2 +- sound/soc/codecs/rt5682.c | 2 ++ sound/soc/codecs/rt5682.h | 1 + 4 files changed, 5 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt5682-i2c.c b/sound/soc/codecs/rt5682-i2c.c index 93c1603b42f1..8ea9f1d9fec0 100644 --- a/sound/soc/codecs/rt5682-i2c.c +++ b/sound/soc/codecs/rt5682-i2c.c @@ -78,7 +78,7 @@ static irqreturn_t rt5682_irq(int irq, void *data) struct rt5682_priv *rt5682 = data; mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); + &rt5682->jack_detect_work, msecs_to_jiffies(rt5682->irq_work_delay_time)); return IRQ_HANDLED; } diff --git a/sound/soc/codecs/rt5682-sdw.c b/sound/soc/codecs/rt5682-sdw.c index 5e097f776561..fed80c8f994f 100644 --- a/sound/soc/codecs/rt5682-sdw.c +++ b/sound/soc/codecs/rt5682-sdw.c @@ -677,7 +677,7 @@ static int rt5682_interrupt_callback(struct sdw_slave *slave, if (status->control_port & 0x4) { mod_delayed_work(system_power_efficient_wq, - &rt5682->jack_detect_work, msecs_to_jiffies(250)); + &rt5682->jack_detect_work, msecs_to_jiffies(rt5682->irq_work_delay_time)); } return 0; diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 559dc6db1f7c..0e2a10ed11da 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -1094,6 +1094,7 @@ void rt5682_jack_detect_handler(struct work_struct *work) /* jack was out, report jack type */ rt5682->jack_type = rt5682_headset_detect(rt5682->component, 1); + rt5682->irq_work_delay_time = 0; } else if ((rt5682->jack_type & SND_JACK_HEADSET) == SND_JACK_HEADSET) { /* jack is already in, report button event */ @@ -1139,6 +1140,7 @@ void rt5682_jack_detect_handler(struct work_struct *work) } else { /* jack out */ rt5682->jack_type = rt5682_headset_detect(rt5682->component, 0); + rt5682->irq_work_delay_time = 50; } snd_soc_jack_report(rt5682->hs_jack, rt5682->jack_type, diff --git a/sound/soc/codecs/rt5682.h b/sound/soc/codecs/rt5682.h index 1f9c51a5b9bf..74ff66767016 100644 --- a/sound/soc/codecs/rt5682.h +++ b/sound/soc/codecs/rt5682.h @@ -1439,6 +1439,7 @@ struct rt5682_priv { int pll_out[RT5682_PLLS]; int jack_type; + int irq_work_delay_time; }; extern const char *rt5682_supply_names[RT5682_NUM_SUPPLIES]; From 5d5f2919273d1089a00556cad68e7f462f3dd2eb Mon Sep 17 00:00:00 2001 From: Lars Povlsen Date: Wed, 3 Feb 2021 13:38:25 +0100 Subject: [PATCH 0188/1091] pinctrl: microchip-sgpio: Fix wrong register offset for IRQ trigger This patch fixes using a wrong register offset when configuring an IRQ trigger type. Fixes: be2dc859abd4 ("pinctrl: pinctrl-microchip-sgpio: Add irq support (for sparx5)") Reported-by: Gustavo A. R. Silva Signed-off-by: Lars Povlsen Reviewed-by: Gustavo A. R. Silva Link: https://lore.kernel.org/r/20210203123825.611576-1-lars.povlsen@microchip.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-microchip-sgpio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/pinctrl-microchip-sgpio.c b/drivers/pinctrl/pinctrl-microchip-sgpio.c index f35edb0eac40..c12fa57ebd12 100644 --- a/drivers/pinctrl/pinctrl-microchip-sgpio.c +++ b/drivers/pinctrl/pinctrl-microchip-sgpio.c @@ -572,7 +572,7 @@ static void microchip_sgpio_irq_settype(struct irq_data *data, /* Type value spread over 2 registers sets: low, high bit */ sgpio_clrsetbits(bank->priv, REG_INT_TRIGGER, addr.bit, BIT(addr.port), (!!(type & 0x1)) << addr.port); - sgpio_clrsetbits(bank->priv, REG_INT_TRIGGER + SGPIO_MAX_BITS, addr.bit, + sgpio_clrsetbits(bank->priv, REG_INT_TRIGGER, SGPIO_MAX_BITS + addr.bit, BIT(addr.port), (!!(type & 0x2)) << addr.port); if (type == SGPIO_INT_TRG_LEVEL) From c971af25cda94afe71617790826a86253e88eab0 Mon Sep 17 00:00:00 2001 From: Wang Panzhenzhuan Date: Tue, 23 Feb 2021 18:07:25 +0800 Subject: [PATCH 0189/1091] pinctrl: rockchip: fix restore error in resume The restore in resume should match to suspend which only set for RK3288 SoCs pinctrl. Fixes: 8dca933127024 ("pinctrl: rockchip: save and restore gpio6_c6 pinmux in suspend/resume") Reviewed-by: Jianqun Xu Reviewed-by: Heiko Stuebner Signed-off-by: Wang Panzhenzhuan Signed-off-by: Jianqun Xu Link: https://lore.kernel.org/r/20210223100725.269240-1-jay.xu@rock-chips.com Signed-off-by: Linus Walleij --- drivers/pinctrl/pinctrl-rockchip.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/pinctrl/pinctrl-rockchip.c b/drivers/pinctrl/pinctrl-rockchip.c index aa1a1c850d05..53a0badc6b03 100644 --- a/drivers/pinctrl/pinctrl-rockchip.c +++ b/drivers/pinctrl/pinctrl-rockchip.c @@ -3727,12 +3727,15 @@ static int __maybe_unused rockchip_pinctrl_suspend(struct device *dev) static int __maybe_unused rockchip_pinctrl_resume(struct device *dev) { struct rockchip_pinctrl *info = dev_get_drvdata(dev); - int ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, - rk3288_grf_gpio6c_iomux | - GPIO6C6_SEL_WRITE_ENABLE); + int ret; - if (ret) - return ret; + if (info->ctrl->type == RK3288) { + ret = regmap_write(info->regmap_base, RK3288_GRF_GPIO6C_IOMUX, + rk3288_grf_gpio6c_iomux | + GPIO6C6_SEL_WRITE_ENABLE); + if (ret) + return ret; + } return pinctrl_force_default(info->pctl_dev); } From 2a9be38099e338f597c14d3cb851849b01db05f6 Mon Sep 17 00:00:00 2001 From: Jonathan Marek Date: Thu, 4 Mar 2021 14:48:16 -0500 Subject: [PATCH 0190/1091] pinctrl: qcom: lpass lpi: use default pullup/strength values If these fields are not set in dts, the driver will use these variables uninitialized to set the fields. Not only will it set garbage values for these fields, but it can overflow into other fields and break those. In the current sm8250 dts, the dmic01 entries do not have a pullup setting, and might not work without this change. Reported-by: kernel test robot Reported-by: Dan Carpenter Fixes: 6e261d1090d6 ("pinctrl: qcom: Add sm8250 lpass lpi pinctrl driver") Signed-off-by: Jonathan Marek Reviewed-by: Bjorn Andersson Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210304194816.3843-1-jonathan@marek.ca Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-lpass-lpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c index 369ee20a7ea9..2f19ab4db720 100644 --- a/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c +++ b/drivers/pinctrl/qcom/pinctrl-lpass-lpi.c @@ -392,7 +392,7 @@ static int lpi_config_set(struct pinctrl_dev *pctldev, unsigned int group, unsigned long *configs, unsigned int nconfs) { struct lpi_pinctrl *pctrl = dev_get_drvdata(pctldev->dev); - unsigned int param, arg, pullup, strength; + unsigned int param, arg, pullup = LPI_GPIO_BIAS_DISABLE, strength = 2; bool value, output_enabled = false; const struct lpi_pingroup *g; unsigned long sval; From 07abd8db9358751107cc46d1cdbd44a92c76a934 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 2 Mar 2021 10:51:50 +0530 Subject: [PATCH 0191/1091] pinctrl: qcom: sc7280: Fix SDC_QDSD_PINGROUP and UFS_RESET offsets The offsets for SDC_QDSD_PINGROUP and UFS_RESET were off by 0x100000 due to an issue in the scripts generating the data. Fixes: ecb454594c43: ("pinctrl: qcom: Add sc7280 pinctrl driver") Reported-by: Veerabhadrarao Badiganti Signed-off-by: Rajendra Nayak Reviewed-by: Bjorn Andersson Link: https://lore.kernel.org/r/1614662511-26519-1-git-send-email-rnayak@codeaurora.org Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-sc7280.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c index 8daccd530285..49c434788304 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -1439,14 +1439,14 @@ static const struct msm_pingroup sc7280_groups[] = { [172] = PINGROUP(172, qdss, _, _, _, _, _, _, _, _), [173] = PINGROUP(173, qdss, _, _, _, _, _, _, _, _), [174] = PINGROUP(174, qdss, _, _, _, _, _, _, _, _), - [175] = UFS_RESET(ufs_reset, 0x1be000), - [176] = SDC_QDSD_PINGROUP(sdc1_rclk, 0x1b3000, 15, 0), - [177] = SDC_QDSD_PINGROUP(sdc1_clk, 0x1b3000, 13, 6), - [178] = SDC_QDSD_PINGROUP(sdc1_cmd, 0x1b3000, 11, 3), - [179] = SDC_QDSD_PINGROUP(sdc1_data, 0x1b3000, 9, 0), - [180] = SDC_QDSD_PINGROUP(sdc2_clk, 0x1b4000, 14, 6), - [181] = SDC_QDSD_PINGROUP(sdc2_cmd, 0x1b4000, 11, 3), - [182] = SDC_QDSD_PINGROUP(sdc2_data, 0x1b4000, 9, 0), + [175] = UFS_RESET(ufs_reset, 0xbe000), + [176] = SDC_QDSD_PINGROUP(sdc1_rclk, 0xb3000, 15, 0), + [177] = SDC_QDSD_PINGROUP(sdc1_clk, 0xb3000, 13, 6), + [178] = SDC_QDSD_PINGROUP(sdc1_cmd, 0xb3000, 11, 3), + [179] = SDC_QDSD_PINGROUP(sdc1_data, 0xb3000, 9, 0), + [180] = SDC_QDSD_PINGROUP(sdc2_clk, 0xb4000, 14, 6), + [181] = SDC_QDSD_PINGROUP(sdc2_cmd, 0xb4000, 11, 3), + [182] = SDC_QDSD_PINGROUP(sdc2_data, 0xb4000, 9, 0), }; static const struct msm_pinctrl_soc_data sc7280_pinctrl = { From d0f9f47c07fe52b34e2ff8590cf09e0a9d8d6f99 Mon Sep 17 00:00:00 2001 From: Rajendra Nayak Date: Tue, 2 Mar 2021 10:51:51 +0530 Subject: [PATCH 0192/1091] pinctrl: qcom: sc7280: Fix SDC1_RCLK configurations Fix SDC1_RCLK configurations which are in a different register so fix the offset from 0xb3000 to 0xb3004. Fixes: ecb454594c43: ("pinctrl: qcom: Add sc7280 pinctrl driver") Reported-by: Veerabhadrarao Badiganti Signed-off-by: Rajendra Nayak Acked-by: Bjorn Andersson Link: https://lore.kernel.org/r/1614662511-26519-2-git-send-email-rnayak@codeaurora.org Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-sc7280.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-sc7280.c b/drivers/pinctrl/qcom/pinctrl-sc7280.c index 49c434788304..9d41abfca37e 100644 --- a/drivers/pinctrl/qcom/pinctrl-sc7280.c +++ b/drivers/pinctrl/qcom/pinctrl-sc7280.c @@ -1440,7 +1440,7 @@ static const struct msm_pingroup sc7280_groups[] = { [173] = PINGROUP(173, qdss, _, _, _, _, _, _, _, _), [174] = PINGROUP(174, qdss, _, _, _, _, _, _, _, _), [175] = UFS_RESET(ufs_reset, 0xbe000), - [176] = SDC_QDSD_PINGROUP(sdc1_rclk, 0xb3000, 15, 0), + [176] = SDC_QDSD_PINGROUP(sdc1_rclk, 0xb3004, 0, 6), [177] = SDC_QDSD_PINGROUP(sdc1_clk, 0xb3000, 13, 6), [178] = SDC_QDSD_PINGROUP(sdc1_cmd, 0xb3000, 11, 3), [179] = SDC_QDSD_PINGROUP(sdc1_data, 0xb3000, 9, 0), From 2fb164f0ce95e504e2688b4f984893c29ebd19ab Mon Sep 17 00:00:00 2001 From: Hauke Mehrtens Date: Tue, 9 Mar 2021 01:01:07 +0100 Subject: [PATCH 0193/1091] mtd: rawnand: mtk: Fix WAITRDY break condition and timeout This fixes NAND_OP_WAITRDY_INSTR operation in the driver. Without this change the driver waits till the system is busy, but we should wait till the busy flag is cleared. The readl_poll_timeout() function gets a break condition, not a wait condition. In addition fix the timeout. The timeout_ms is given in ms, but the readl_poll_timeout() function takes the timeout in us. Multiple the given timeout by 1000 to convert it. Without this change, the driver does not work at all, it doesn't even identify the NAND chip. Fixes: 5197360f9e09 ("mtd: rawnand: mtk: Convert the driver to exec_op()") Signed-off-by: Hauke Mehrtens Reviewed-by: Boris Brezillon Signed-off-by: Miquel Raynal Link: https://lore.kernel.org/linux-mtd/20210309000107.1368404-1-hauke@hauke-m.de --- drivers/mtd/nand/raw/mtk_nand.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/mtd/nand/raw/mtk_nand.c b/drivers/mtd/nand/raw/mtk_nand.c index 57f1f1708994..5c5c92132287 100644 --- a/drivers/mtd/nand/raw/mtk_nand.c +++ b/drivers/mtd/nand/raw/mtk_nand.c @@ -488,8 +488,8 @@ static int mtk_nfc_exec_instr(struct nand_chip *chip, return 0; case NAND_OP_WAITRDY_INSTR: return readl_poll_timeout(nfc->regs + NFI_STA, status, - status & STA_BUSY, 20, - instr->ctx.waitrdy.timeout_ms); + !(status & STA_BUSY), 20, + instr->ctx.waitrdy.timeout_ms * 1000); default: break; } From 4988f0cc254a1955d5c3244298055f5f7b538e6b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:23 -0600 Subject: [PATCH 0194/1091] ASoC: arizona: fix function argument Cppcheck warning: sound/soc/codecs/arizona.c:2042:53: style:inconclusive: Function 'arizona_init_dai' argument 2 names different: declaration 'dai' definition 'id'. [funcArgNamesDifferent] int arizona_init_dai(struct arizona_priv *priv, int id) ^ sound/soc/codecs/arizona.h:320:53: note: Function 'arizona_init_dai' argument 2 names different: declaration 'dai' definition 'id'. int arizona_init_dai(struct arizona_priv *priv, int dai); ^ sound/soc/codecs/arizona.c:2042:53: note: Function 'arizona_init_dai' argument 2 names different: declaration 'dai' definition 'id'. int arizona_init_dai(struct arizona_priv *priv, int id) ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/arizona.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index b893d3e4c97c..b3abbe80f11d 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -317,7 +317,7 @@ int arizona_init_vol_limit(struct arizona *arizona); int arizona_init_spk_irqs(struct arizona *arizona); int arizona_free_spk_irqs(struct arizona *arizona); -int arizona_init_dai(struct arizona_priv *priv, int dai); +int arizona_init_dai(struct arizona_priv *priv, int id); int arizona_set_output_mode(struct snd_soc_component *component, int output, bool diff); From b6021b5623b93da05375ae8060f8e8d5dcae0ba9 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:24 -0600 Subject: [PATCH 0195/1091] ASoC: madera: align function prototype cppcheck warning: sound/soc/codecs/madera.c:3372:51: style:inconclusive: Function 'madera_init_dai' argument 2 names different: declaration 'dai' definition 'id'. [funcArgNamesDifferent] int madera_init_dai(struct madera_priv *priv, int id) ^ sound/soc/codecs/madera.h:433:51: note: Function 'madera_init_dai' argument 2 names different: declaration 'dai' definition 'id'. int madera_init_dai(struct madera_priv *priv, int dai); ^ sound/soc/codecs/madera.c:3372:51: note: Function 'madera_init_dai' argument 2 names different: declaration 'dai' definition 'id'. int madera_init_dai(struct madera_priv *priv, int id) ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/madera.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/madera.h b/sound/soc/codecs/madera.h index e0c0be59e2ef..09ad6e9bce4b 100644 --- a/sound/soc/codecs/madera.h +++ b/sound/soc/codecs/madera.h @@ -430,7 +430,7 @@ int madera_init_bus_error_irq(struct madera_priv *priv, int dsp_num, irq_handler_t handler); void madera_free_bus_error_irq(struct madera_priv *priv, int dsp_num); -int madera_init_dai(struct madera_priv *priv, int dai); +int madera_init_dai(struct madera_priv *priv, int id); int madera_set_output_mode(struct snd_soc_component *component, int output, bool differential); From 43fe3fe8b31685ccb2e248799ce3e9f9a15938fb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:25 -0600 Subject: [PATCH 0196/1091] ASoC: wm2200: remove unused structure cppcheck complains about some members not being used, but it's really the entire structure that is never used anywhere. Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm2200.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sound/soc/codecs/wm2200.c b/sound/soc/codecs/wm2200.c index c62f7ad0022c..b0a6d31299bb 100644 --- a/sound/soc/codecs/wm2200.c +++ b/sound/soc/codecs/wm2200.c @@ -72,13 +72,6 @@ static const char *wm2200_core_supply_names[WM2200_NUM_CORE_SUPPLIES] = { "LDOVDD", }; -struct wm2200_fll { - int fref; - int fout; - int src; - struct completion lock; -}; - /* codec private data */ struct wm2200_priv { struct wm_adsp dsp[2]; From 13119a311aeb5a91ea751f10e4158a86361c2f08 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:26 -0600 Subject: [PATCH 0197/1091] ASoC: wm8903: remove useless assignments cppcheck warnings: sound/soc/codecs/wm8903.c:1552:11: style: Variable 'best_val' is assigned a value that is never used. [unreadVariable] best_val = ((clk_sys * 10) / bclk_divs[0].ratio) - bclk; ^ sound/soc/codecs/wm8903.c:1559:12: style: Variable 'best_val' is assigned a value that is never used. [unreadVariable] best_val = cur_val; ^ Indeed what matters in the code is the blck_div, the best_val is assigned but never tested or used. Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8903.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/wm8903.c b/sound/soc/codecs/wm8903.c index 026603ae44ce..75f30154c809 100644 --- a/sound/soc/codecs/wm8903.c +++ b/sound/soc/codecs/wm8903.c @@ -1549,14 +1549,12 @@ static int wm8903_hw_params(struct snd_pcm_substream *substream, * BCLKs to clock out the samples). */ bclk_div = 0; - best_val = ((clk_sys * 10) / bclk_divs[0].ratio) - bclk; i = 1; while (i < ARRAY_SIZE(bclk_divs)) { cur_val = ((clk_sys * 10) / bclk_divs[i].ratio) - bclk; if (cur_val < 0) /* BCLK table is sorted */ break; bclk_div = i; - best_val = cur_val; i++; } From d28a9dfeb8071b9ac0e79c8b8b4a0111c3b54c70 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:27 -0600 Subject: [PATCH 0198/1091] ASoC: wm8958-dsp2: rename local 'control' arrays cppcheck complains about shadowed variables: sound/soc/codecs/wm8958-dsp2.c:926:27: style: Local variable 'control' shadows outer variable [shadowVariable] struct snd_kcontrol_new control[] = { ^ sound/soc/codecs/wm8958-dsp2.c:900:17: note: Shadowed declaration struct wm8994 *control = wm8994->wm8994; ^ sound/soc/codecs/wm8958-dsp2.c:926:27: note: Shadow variable struct snd_kcontrol_new control[] = { ^ sound/soc/codecs/wm8958-dsp2.c:952:27: style: Local variable 'control' shadows outer variable [shadowVariable] struct snd_kcontrol_new control[] = { ^ sound/soc/codecs/wm8958-dsp2.c:900:17: note: Shadowed declaration struct wm8994 *control = wm8994->wm8994; ^ sound/soc/codecs/wm8958-dsp2.c:952:27: note: Shadow variable struct snd_kcontrol_new control[] = { ^ sound/soc/codecs/wm8958-dsp2.c:978:27: style: Local variable 'control' shadows outer variable [shadowVariable] struct snd_kcontrol_new control[] = { ^ sound/soc/codecs/wm8958-dsp2.c:900:17: note: Shadowed declaration struct wm8994 *control = wm8994->wm8994; ^ sound/soc/codecs/wm8958-dsp2.c:978:27: note: Shadow variable struct snd_kcontrol_new control[] = { ^ sound/soc/codecs/wm8958-dsp2.c:1006:27: style: Local variable 'control' shadows outer variable [shadowVariable] struct snd_kcontrol_new control[] = { ^ sound/soc/codecs/wm8958-dsp2.c:900:17: note: Shadowed declaration struct wm8994 *control = wm8994->wm8994; ^ sound/soc/codecs/wm8958-dsp2.c:1006:27: note: Shadow variable struct snd_kcontrol_new control[] = { ^ fix by adding a prefix related to each control. Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8958-dsp2.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/codecs/wm8958-dsp2.c b/sound/soc/codecs/wm8958-dsp2.c index 3bce9a14f0f3..536339e43dc7 100644 --- a/sound/soc/codecs/wm8958-dsp2.c +++ b/sound/soc/codecs/wm8958-dsp2.c @@ -923,7 +923,7 @@ void wm8958_dsp2_init(struct snd_soc_component *component) component, wm8958_enh_eq_loaded); if (pdata->num_mbc_cfgs) { - struct snd_kcontrol_new control[] = { + struct snd_kcontrol_new mbc_control[] = { SOC_ENUM_EXT("MBC Mode", wm8994->mbc_enum, wm8958_get_mbc_enum, wm8958_put_mbc_enum), }; @@ -942,14 +942,14 @@ void wm8958_dsp2_init(struct snd_soc_component *component) wm8994->mbc_enum.texts = wm8994->mbc_texts; ret = snd_soc_add_component_controls(wm8994->hubs.component, - control, 1); + mbc_control, 1); if (ret != 0) dev_err(wm8994->hubs.component->dev, "Failed to add MBC mode controls: %d\n", ret); } if (pdata->num_vss_cfgs) { - struct snd_kcontrol_new control[] = { + struct snd_kcontrol_new vss_control[] = { SOC_ENUM_EXT("VSS Mode", wm8994->vss_enum, wm8958_get_vss_enum, wm8958_put_vss_enum), }; @@ -968,14 +968,14 @@ void wm8958_dsp2_init(struct snd_soc_component *component) wm8994->vss_enum.texts = wm8994->vss_texts; ret = snd_soc_add_component_controls(wm8994->hubs.component, - control, 1); + vss_control, 1); if (ret != 0) dev_err(wm8994->hubs.component->dev, "Failed to add VSS mode controls: %d\n", ret); } if (pdata->num_vss_hpf_cfgs) { - struct snd_kcontrol_new control[] = { + struct snd_kcontrol_new hpf_control[] = { SOC_ENUM_EXT("VSS HPF Mode", wm8994->vss_hpf_enum, wm8958_get_vss_hpf_enum, wm8958_put_vss_hpf_enum), @@ -995,7 +995,7 @@ void wm8958_dsp2_init(struct snd_soc_component *component) wm8994->vss_hpf_enum.texts = wm8994->vss_hpf_texts; ret = snd_soc_add_component_controls(wm8994->hubs.component, - control, 1); + hpf_control, 1); if (ret != 0) dev_err(wm8994->hubs.component->dev, "Failed to add VSS HPFmode controls: %d\n", @@ -1003,7 +1003,7 @@ void wm8958_dsp2_init(struct snd_soc_component *component) } if (pdata->num_enh_eq_cfgs) { - struct snd_kcontrol_new control[] = { + struct snd_kcontrol_new eq_control[] = { SOC_ENUM_EXT("Enhanced EQ Mode", wm8994->enh_eq_enum, wm8958_get_enh_eq_enum, wm8958_put_enh_eq_enum), @@ -1023,7 +1023,7 @@ void wm8958_dsp2_init(struct snd_soc_component *component) wm8994->enh_eq_enum.texts = wm8994->enh_eq_texts; ret = snd_soc_add_component_controls(wm8994->hubs.component, - control, 1); + eq_control, 1); if (ret != 0) dev_err(wm8994->hubs.component->dev, "Failed to add enhanced EQ controls: %d\n", From 729d42a4ab1a7bc9f4b5c37c57a3a4270333351f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:28 -0600 Subject: [PATCH 0199/1091] ASoC: wm8978: clarify expression cppcheck warning: sound/soc/codecs/wm8978.c:727:57: style: Clarify calculation precedence for '&' and '?'. [clarifyCalculation] enum wm8978_sysclk_src current_clk_id = clking & 0x100 ? ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8978.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8978.c b/sound/soc/codecs/wm8978.c index 4b5ecd142249..7091e1a9d516 100644 --- a/sound/soc/codecs/wm8978.c +++ b/sound/soc/codecs/wm8978.c @@ -724,7 +724,7 @@ static int wm8978_hw_params(struct snd_pcm_substream *substream, /* Sampling rate mask = 0xe (for filters) */ u16 add_ctl = snd_soc_component_read(component, WM8978_ADDITIONAL_CONTROL) & ~0xe; u16 clking = snd_soc_component_read(component, WM8978_CLOCKING); - enum wm8978_sysclk_src current_clk_id = clking & 0x100 ? + enum wm8978_sysclk_src current_clk_id = (clking & 0x100) ? WM8978_PLL : WM8978_MCLK; unsigned int f_sel, diff, diff_best = INT_MAX; int i, best = 0; From b564fdb756918557fb4ca5086e67929bd2eafdd6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:29 -0600 Subject: [PATCH 0200/1091] ASoC: wm8994: align function prototype cppcheck warning: sound/soc/codecs/wm8994.c:3923:26: style:inconclusive: Function 'wm8958_mic_detect' argument 3 names different: declaration 'cb' definition 'det_cb'. [funcArgNamesDifferent] wm1811_micdet_cb det_cb, void *det_cb_data, ^ sound/soc/codecs/wm8994.h:53:26: note: Function 'wm8958_mic_detect' argument 3 names different: declaration 'cb' definition 'det_cb'. wm1811_micdet_cb cb, void *det_cb_data, ^ sound/soc/codecs/wm8994.c:3923:26: note: Function 'wm8958_mic_detect' argument 3 names different: declaration 'cb' definition 'det_cb'. wm1811_micdet_cb det_cb, void *det_cb_data, ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8994.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8994.h b/sound/soc/codecs/wm8994.h index 41c4b126114d..bc584b17bf28 100644 --- a/sound/soc/codecs/wm8994.h +++ b/sound/soc/codecs/wm8994.h @@ -50,7 +50,7 @@ typedef void (*wm1811_mic_id_cb)(void *data, u16 status); int wm8994_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack, int micbias); int wm8958_mic_detect(struct snd_soc_component *component, struct snd_soc_jack *jack, - wm1811_micdet_cb cb, void *det_cb_data, + wm1811_micdet_cb det_cb, void *det_cb_data, wm1811_mic_id_cb id_cb, void *id_cb_data); int wm8994_vmid_mode(struct snd_soc_component *component, enum wm8994_vmid_mode mode); From ea80d4991b76dc101b87228b74515d818ff03bcd Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:30 -0600 Subject: [PATCH 0201/1091] ASoC: wm8996: clarify expression cppcheck warning: sound/soc/codecs/wm8996.c:2109:23: style: Clarify calculation precedence for '/' and '?'. [clarifyCalculation] timeout = timeout/2 ? : 1; ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8996.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm8996.c b/sound/soc/codecs/wm8996.c index d303ef7571e9..197ae7d84a49 100644 --- a/sound/soc/codecs/wm8996.c +++ b/sound/soc/codecs/wm8996.c @@ -2106,7 +2106,7 @@ static int wm8996_set_fll(struct snd_soc_component *component, int fll_id, int s timeout *= 10; else /* ensure timeout of atleast 1 jiffies */ - timeout = timeout/2 ? : 1; + timeout = (timeout/2) ? : 1; for (retry = 0; retry < 10; retry++) { time_left = wait_for_completion_timeout(&wm8996->fll_lock, From 492df5b0748ada592119dc19dd713e4a60c4e69f Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:31 -0600 Subject: [PATCH 0202/1091] ASoC: wm_adsp: simplify return value cppcheck warning: sound/soc/codecs/wm_adsp.c:2092:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/codecs/wm_adsp.c:2070:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/codecs/wm_adsp.c:2092:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_adsp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_adsp.c b/sound/soc/codecs/wm_adsp.c index 070ca7d8c661..3dc119daf2f6 100644 --- a/sound/soc/codecs/wm_adsp.c +++ b/sound/soc/codecs/wm_adsp.c @@ -2079,7 +2079,7 @@ int wm_adsp_write_ctl(struct wm_adsp *dsp, const char *name, int type, snd_ctl_notify(dsp->component->card->snd_card, SNDRV_CTL_EVENT_MASK_VALUE, &kcontrol->id); - return ret; + return 0; } EXPORT_SYMBOL_GPL(wm_adsp_write_ctl); From 8ea9e29cc7fc966885018628e123f4113f1ce4b2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:43:32 -0600 Subject: [PATCH 0203/1091] ASoC: wm_hubs: align function prototype cppcheck warnings: sound/soc/codecs/wm_hubs.c:1194:11: style:inconclusive: Function 'wm_hubs_handle_analogue_pdata' argument 8 names different: declaration 'micbias1_dly' definition 'micbias1_delay'. [funcArgNamesDifferent] int micbias1_delay, int micbias2_delay, ^ sound/soc/codecs/wm_hubs.h:59:11: note: Function 'wm_hubs_handle_analogue_pdata' argument 8 names different: declaration 'micbias1_dly' definition 'micbias1_delay'. int micbias1_dly, int micbias2_dly, ^ sound/soc/codecs/wm_hubs.c:1194:11: note: Function 'wm_hubs_handle_analogue_pdata' argument 8 names different: declaration 'micbias1_dly' definition 'micbias1_delay'. int micbias1_delay, int micbias2_delay, ^ sound/soc/codecs/wm_hubs.c:1194:31: style:inconclusive: Function 'wm_hubs_handle_analogue_pdata' argument 9 names different: declaration 'micbias2_dly' definition 'micbias2_delay'. [funcArgNamesDifferent] int micbias1_delay, int micbias2_delay, ^ sound/soc/codecs/wm_hubs.h:59:29: note: Function 'wm_hubs_handle_analogue_pdata' argument 9 names different: declaration 'micbias2_dly' definition 'micbias2_delay'. int micbias1_dly, int micbias2_dly, ^ sound/soc/codecs/wm_hubs.c:1194:31: note: Function 'wm_hubs_handle_analogue_pdata' argument 9 names different: declaration 'micbias2_dly' definition 'micbias2_delay'. int micbias1_delay, int micbias2_delay, ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Charles Keepax Link: https://lore.kernel.org/r/20210311004332.120901-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm_hubs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wm_hubs.h b/sound/soc/codecs/wm_hubs.h index 988b29e63060..a4ed9bd31426 100644 --- a/sound/soc/codecs/wm_hubs.h +++ b/sound/soc/codecs/wm_hubs.h @@ -56,7 +56,7 @@ extern int wm_hubs_handle_analogue_pdata(struct snd_soc_component *, int lineout1_diff, int lineout2_diff, int lineout1fb, int lineout2fb, int jd_scthr, int jd_thr, - int micbias1_dly, int micbias2_dly, + int micbias1_delay, int micbias2_delay, int micbias1_lvl, int micbias2_lvl); extern irqreturn_t wm_hubs_dcs_done(int irq, void *data); From 5fd6b9b8b1c477fb695e3ae313ffb70b3cc88dc9 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 11 Mar 2021 11:31:50 +0800 Subject: [PATCH 0204/1091] ASoC: dt-bindings: mt8183: add compatible string for using rt1015p Machines with rt1015p should use the compatible string "mt8183-mt6358-ts3a227-rt1015p". Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210311033151.1818603-2-tzungbi@google.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt b/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt index 235eac8aea7b..ecd46ed8eb98 100644 --- a/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt +++ b/Documentation/devicetree/bindings/sound/mt8183-mt6358-ts3a227-max98357.txt @@ -4,6 +4,7 @@ Required properties: - compatible : "mediatek,mt8183_mt6358_ts3a227_max98357" for MAX98357A codec "mediatek,mt8183_mt6358_ts3a227_max98357b" for MAX98357B codec "mediatek,mt8183_mt6358_ts3a227_rt1015" for RT1015 codec + "mediatek,mt8183_mt6358_ts3a227_rt1015p" for RT1015P codec - mediatek,platform: the phandle of MT8183 ASoC platform Optional properties: From 9dc21a066bb6bff55d889f22460f1bf236a9a4a3 Mon Sep 17 00:00:00 2001 From: Tzung-Bi Shih Date: Thu, 11 Mar 2021 11:31:51 +0800 Subject: [PATCH 0205/1091] ASoC: mediatek: mt8183: support machine driver with rt1015p Supports machine driver with rt1015p ("mt8183_mt6358_ts3a227_rt1015p"). Embeds in the existing mt8183-mt6358-ts3a227-max98357.c because they share most of the code. Signed-off-by: Tzung-Bi Shih Link: https://lore.kernel.org/r/20210311033151.1818603-3-tzungbi@google.com Signed-off-by: Mark Brown --- sound/soc/mediatek/Kconfig | 1 + .../mt8183/mt8183-mt6358-ts3a227-max98357.c | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/sound/soc/mediatek/Kconfig b/sound/soc/mediatek/Kconfig index effdb76369e4..74dae4332d17 100644 --- a/sound/soc/mediatek/Kconfig +++ b/sound/soc/mediatek/Kconfig @@ -124,6 +124,7 @@ config SND_SOC_MT8183_MT6358_TS3A227E_MAX98357A select SND_SOC_MT6358 select SND_SOC_MAX98357A select SND_SOC_RT1015 + select SND_SOC_RT1015P select SND_SOC_BT_SCO select SND_SOC_TS3A227E select SND_SOC_CROS_EC_CODEC if CROS_EC diff --git a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c index 271413e719e3..94dcbd36c869 100644 --- a/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c +++ b/sound/soc/mediatek/mt8183/mt8183-mt6358-ts3a227-max98357.c @@ -284,6 +284,11 @@ SND_SOC_DAILINK_DEFS(i2s3_rt1015, COMP_CODEC(RT1015_DEV1_NAME, RT1015_CODEC_DAI)), DAILINK_COMP_ARRAY(COMP_EMPTY())); +SND_SOC_DAILINK_DEFS(i2s3_rt1015p, + DAILINK_COMP_ARRAY(COMP_CPU("I2S3")), + DAILINK_COMP_ARRAY(COMP_CODEC("rt1015p", "HiFi")), + DAILINK_COMP_ARRAY(COMP_EMPTY())); + SND_SOC_DAILINK_DEFS(i2s5, DAILINK_COMP_ARRAY(COMP_CPU("I2S5")), DAILINK_COMP_ARRAY(COMP_CODEC("bt-sco", "bt-sco-pcm")), @@ -590,6 +595,13 @@ static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015_card = { .num_configs = ARRAY_SIZE(mt8183_mt6358_ts3a227_rt1015_amp_conf), }; +static struct snd_soc_card mt8183_mt6358_ts3a227_rt1015p_card = { + .name = "mt8183_mt6358_ts3a227_rt1015p", + .owner = THIS_MODULE, + .dai_link = mt8183_mt6358_ts3a227_dai_links, + .num_links = ARRAY_SIZE(mt8183_mt6358_ts3a227_dai_links), +}; + static int mt8183_mt6358_ts3a227_max98357_headset_init(struct snd_soc_component *component) { @@ -686,6 +698,19 @@ mt8183_mt6358_ts3a227_max98357_dev_probe(struct platform_device *pdev) dai_link->platforms = i2s3_rt1015_platforms; dai_link->num_platforms = ARRAY_SIZE(i2s3_rt1015_platforms); + } else if (card == &mt8183_mt6358_ts3a227_rt1015p_card) { + dai_link->be_hw_params_fixup = + mt8183_rt1015_i2s_hw_params_fixup; + dai_link->ops = &mt8183_mt6358_i2s_ops; + dai_link->cpus = i2s3_rt1015p_cpus; + dai_link->num_cpus = + ARRAY_SIZE(i2s3_rt1015p_cpus); + dai_link->codecs = i2s3_rt1015p_codecs; + dai_link->num_codecs = + ARRAY_SIZE(i2s3_rt1015p_codecs); + dai_link->platforms = i2s3_rt1015p_platforms; + dai_link->num_platforms = + ARRAY_SIZE(i2s3_rt1015p_platforms); } } @@ -772,6 +797,10 @@ static const struct of_device_id mt8183_mt6358_ts3a227_max98357_dt_match[] = { .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015", .data = &mt8183_mt6358_ts3a227_rt1015_card, }, + { + .compatible = "mediatek,mt8183_mt6358_ts3a227_rt1015p", + .data = &mt8183_mt6358_ts3a227_rt1015p_card, + }, {} }; #endif From c68fded79a9fe1376a60049f2ab45d611969de5c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 13:39:27 -0600 Subject: [PATCH 0206/1091] ASoC: soc-core: fix DMI handling When DMI information is not present, trying to assign the card long name results in the following warning. WARNING KERN tegra-audio-graph-card sound: ASoC: no DMI vendor name! The initial solution suggested was to test if the card device is an ACPI one. This causes a regression visible to userspace on all Intel platforms, with UCM unable to load card profiles based on DMI information: the card devices are not necessarily ACPI ones, e.g. when the parent creates platform devices on Intel devices. To fix this problem, this patch exports the existing dmi_available variable and tests it in the ASoC core. Fixes: c014170408bc ("ASoC: soc-core: Prevent warning if no DMI table is present") Signed-off-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Acked-by: Jean Delvare Link: https://lore.kernel.org/r/20210310193928.108850-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- drivers/firmware/dmi_scan.c | 1 + sound/soc/soc-core.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c index d51ca0428bb8..f191a1f901ac 100644 --- a/drivers/firmware/dmi_scan.c +++ b/drivers/firmware/dmi_scan.c @@ -166,6 +166,7 @@ static int __init dmi_checksum(const u8 *buf, u8 len) static const char *dmi_ident[DMI_STRING_MAX]; static LIST_HEAD(dmi_devices); int dmi_available; +EXPORT_SYMBOL_GPL(dmi_available); /* * Save a DMI string diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 16ba54eb8164..c7e4600b2dd4 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1574,7 +1574,7 @@ int snd_soc_set_dmi_name(struct snd_soc_card *card, const char *flavour) if (card->long_name) return 0; /* long name already set by driver or from DMI */ - if (!is_acpi_device_node(card->dev->fwnode)) + if (!dmi_available) return 0; /* make up dmi long name as: vendor-product-version-board */ From 0c9fdcdba68208270ae85d39600ea97da1718344 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 14 Jan 2021 19:29:28 +0800 Subject: [PATCH 0207/1091] soc: qcom: geni: shield geni_icc_get() for ACPI boot Currently, GENI devices like i2c-qcom-geni fails to probe in ACPI boot, if interconnect support is enabled. That's because interconnect driver only supports DT right now. As interconnect is not necessarily required for basic function of GENI devices, let's shield geni_icc_get() call, and then all other ICC calls become nop due to NULL icc_path, so that GENI devices keep working for ACPI boot. Reviewed-by: Bjorn Andersson Signed-off-by: Shawn Guo Link: https://lore.kernel.org/r/20210114112928.11368-1-shawn.guo@linaro.org Signed-off-by: Bjorn Andersson --- drivers/soc/qcom/qcom-geni-se.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index f42954e2c98e..c7c03ccfe888 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -760,6 +760,9 @@ int geni_icc_get(struct geni_se *se, const char *icc_ddr) int i, err; const char *icc_names[] = {"qup-core", "qup-config", icc_ddr}; + if (has_acpi_companion(se->dev)) + return 0; + for (i = 0; i < ARRAY_SIZE(se->icc_paths); i++) { if (!icc_names[i]) continue; From f8fc9ec56f341c2a7aa263049340b11c9956962f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:07:42 +0900 Subject: [PATCH 0208/1091] ASoC: soc-pcm: check DAI activity under soc_pcm_apply_symmetry() soc_pcm_apply_symmetry() is used like below in all cases. if (snd_soc_dai_active(dai)) { err = soc_pcm_apply_symmetry(fe_substream, dai); ... } Because of this style, the code is deep nested. This patch checks it under soc_pcm_apply_symmetry(), and makes code simple. static int soc_pcm_apply_symmetry(...) { ... => if (!snd_soc_dai_active(...)) return 0; ... } => ret = soc_pcm_apply_symmetry(); if (ret < 0) ... Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0qhuobl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ba8ffbf8a5d3..9b5ab7a05f65 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -349,6 +349,9 @@ static int soc_pcm_apply_symmetry(struct snd_pcm_substream *substream, struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); int ret; + if (!snd_soc_dai_active(soc_dai)) + return 0; + #define __soc_pcm_apply_symmetry(name, NAME) \ if (soc_dai->name && (soc_dai->driver->symmetric_##name || \ rtd->dai_link->symmetric_##name)) { \ @@ -765,11 +768,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) /* Symmetry only applies if we've already got an active stream. */ for_each_rtd_dais(rtd, i, dai) { - if (snd_soc_dai_active(dai)) { - ret = soc_pcm_apply_symmetry(substream, dai); - if (ret != 0) - goto err; - } + ret = soc_pcm_apply_symmetry(substream, dai); + if (ret != 0) + goto err; } pr_debug("ASoC: %s <-> %s info:\n", @@ -1693,11 +1694,9 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, for_each_rtd_cpu_dais (fe, i, fe_cpu_dai) { /* Symmetry only applies if we've got an active stream. */ - if (snd_soc_dai_active(fe_cpu_dai)) { - err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai); - if (err < 0) - return err; - } + err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai); + if (err < 0) + return err; } /* apply symmetry for BE */ @@ -1721,11 +1720,9 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, /* Symmetry only applies if we've got an active stream. */ for_each_rtd_dais(rtd, i, dai) { - if (snd_soc_dai_active(dai)) { - err = soc_pcm_apply_symmetry(fe_substream, dai); - if (err < 0) - return err; - } + err = soc_pcm_apply_symmetry(fe_substream, dai); + if (err < 0) + return err; } } From 6fb8944cd2892e018d13955c2d51579a30744904 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:07:48 +0900 Subject: [PATCH 0209/1091] ASoC: soc-pcm: add soc_cpu/codec_dai_name() macro soc-pcm needs DAI name and it will be "multicpu/multicodec" if it has many DAIs. But current code is using very verbose for it. This patch uses macro and makes code simple. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87im61uobf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 9b5ab7a05f65..60e688b103d8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -29,6 +29,15 @@ #define DPCM_MAX_BE_USERS 8 +static inline const char *soc_cpu_dai_name(struct snd_soc_pcm_runtime *rtd) +{ + return (rtd)->num_cpus == 1 ? asoc_rtd_to_cpu(rtd, 0)->name : "multicpu"; +} +static inline const char *soc_codec_dai_name(struct snd_soc_pcm_runtime *rtd) +{ + return (rtd)->num_codecs == 1 ? asoc_rtd_to_codec(rtd, 0)->name : "multicodec"; +} + #ifdef CONFIG_DEBUG_FS static const char *dpcm_state_string(enum snd_soc_dpcm_state state) { @@ -697,8 +706,8 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_component *component; struct snd_soc_dai *dai; - const char *codec_dai_name = "multicodec"; - const char *cpu_dai_name = "multicpu"; + const char *codec_dai_name = soc_codec_dai_name(rtd); + const char *cpu_dai_name = soc_cpu_dai_name(rtd); int i, ret = 0; for_each_rtd_components(rtd, i, component) @@ -737,12 +746,6 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) /* Check that the codec and cpu DAIs are compatible */ soc_pcm_init_runtime_hw(substream); - if (rtd->num_codecs == 1) - codec_dai_name = asoc_rtd_to_codec(rtd, 0)->name; - - if (rtd->num_cpus == 1) - cpu_dai_name = asoc_rtd_to_cpu(rtd, 0)->name; - if (soc_pcm_has_symmetry(substream)) runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; @@ -2741,8 +2744,7 @@ static int soc_create_pcm(struct snd_pcm **pcm, else snprintf(new_name, sizeof(new_name), "%s %s-%d", rtd->dai_link->stream_name, - (rtd->num_codecs > 1) ? - "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, num); + soc_codec_dai_name(rtd), num); ret = snd_pcm_new(rtd->card->snd_card, new_name, num, playback, capture, pcm); @@ -2841,8 +2843,7 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) pcm->no_device_suspend = true; out: dev_dbg(rtd->card->dev, "%s <-> %s mapping ok\n", - (rtd->num_codecs > 1) ? "multicodec" : asoc_rtd_to_codec(rtd, 0)->name, - (rtd->num_cpus > 1) ? "multicpu" : asoc_rtd_to_cpu(rtd, 0)->name); + soc_codec_dai_name(rtd), soc_cpu_dai_name(rtd)); return ret; } From 56e749ba756fdc2eff332b8eadda8fca231ad782 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:07:53 +0900 Subject: [PATCH 0210/1091] ASoC: soc-pcm: direct copy at snd_soc_set_runtime_hwparams() snd_soc_set_runtime_hwparams() is called from each driver to initialize hw parameters, but coping each parameters one-by-one. Current code is not copying all parameters, but no big effect if we do it. This patch copies all parameters by simple code. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h7lluoba.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 60e688b103d8..6f2de27cf18f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -300,15 +300,8 @@ bool snd_soc_runtime_ignore_pmdown_time(struct snd_soc_pcm_runtime *rtd) int snd_soc_set_runtime_hwparams(struct snd_pcm_substream *substream, const struct snd_pcm_hardware *hw) { - struct snd_pcm_runtime *runtime = substream->runtime; - runtime->hw.info = hw->info; - runtime->hw.formats = hw->formats; - runtime->hw.period_bytes_min = hw->period_bytes_min; - runtime->hw.period_bytes_max = hw->period_bytes_max; - runtime->hw.periods_min = hw->periods_min; - runtime->hw.periods_max = hw->periods_max; - runtime->hw.buffer_bytes_max = hw->buffer_bytes_max; - runtime->hw.fifo_size = hw->fifo_size; + substream->runtime->hw = *hw; + return 0; } EXPORT_SYMBOL_GPL(snd_soc_set_runtime_hwparams); From 68cbc557375e22e921c9fd007dfcb35faeff4908 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:07:57 +0900 Subject: [PATCH 0211/1091] ASoC: soc-pcm: add soc_pcm_update_symmetry() Current soc-pcm has soc_pcm_has_symmetry() and using it as if (soc_pcm_has_symmetry(substream)) substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; We want to share same operation as same function. This patch adds soc_pcm_update_symmetry() and pack above code in one function. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ft15uob6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 6f2de27cf18f..4ea4e2af9134 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -410,7 +410,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, return 0; } -static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) +static void soc_pcm_update_symmetry(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct snd_soc_dai_link *link = rtd->dai_link; @@ -427,7 +427,8 @@ static bool soc_pcm_has_symmetry(struct snd_pcm_substream *substream) dai->driver->symmetric_channels || dai->driver->symmetric_sample_bits; - return symmetry; + if (symmetry) + substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; } static void soc_pcm_set_msb(struct snd_pcm_substream *substream, int bits) @@ -739,8 +740,7 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) /* Check that the codec and cpu DAIs are compatible */ soc_pcm_init_runtime_hw(substream); - if (soc_pcm_has_symmetry(substream)) - runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; + soc_pcm_update_symmetry(substream); ret = -EINVAL; if (!runtime->hw.rates) { @@ -1685,8 +1685,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, int i; /* apply symmetry for FE */ - if (soc_pcm_has_symmetry(fe_substream)) - fe_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; + soc_pcm_update_symmetry(fe_substream); for_each_rtd_cpu_dais (fe, i, fe_cpu_dai) { /* Symmetry only applies if we've got an active stream. */ @@ -1711,8 +1710,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, if (rtd->dai_link->be_hw_params_fixup) continue; - if (soc_pcm_has_symmetry(be_substream)) - be_substream->runtime->hw.info |= SNDRV_PCM_INFO_JOINT_DUPLEX; + soc_pcm_update_symmetry(be_substream); /* Symmetry only applies if we've got an active stream. */ for_each_rtd_dais(rtd, i, dai) { From c393281a3c1cb252735c46efbf8501a3782f9afa Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:08:02 +0900 Subject: [PATCH 0212/1091] ASoC: soc-pcm: add soc_hw_sanity_check() Current soc_pcm_open() is checking runtime->hw parameters, but having such function is very helpful for reading code. This patch adds new soc_hw_sanity_check() and checks runtime->hw parameters there. And print its debug message there, too. Debug message print out timing is exchanged after this patch, but it is not a big deal, because it is for debug. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87eegpuob1.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 67 +++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 27 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4ea4e2af9134..910a6afe9f48 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -689,6 +689,44 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) return soc_pcm_clean(substream, 0); } +static int soc_hw_sanity_check(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_pcm_hardware *hw = &substream->runtime->hw; + const char *name_cpu = soc_cpu_dai_name(rtd); + const char *name_codec = soc_codec_dai_name(rtd); + const char *err_msg; + struct device *dev = rtd->dev; + + err_msg = "rates"; + if (!hw->rates) + goto config_err; + + err_msg = "formats"; + if (!hw->formats) + goto config_err; + + err_msg = "channels"; + if (!hw->channels_min || !hw->channels_max || + hw->channels_min > hw->channels_max) + goto config_err; + + dev_dbg(dev, "ASoC: %s <-> %s info:\n", name_codec, + name_cpu); + dev_dbg(dev, "ASoC: rate mask 0x%x\n", hw->rates); + dev_dbg(dev, "ASoC: ch min %d max %d\n", hw->channels_min, + hw->channels_max); + dev_dbg(dev, "ASoC: rate min %d max %d\n", hw->rate_min, + hw->rate_max); + + return 0; + +config_err: + dev_err(dev, "ASoC: %s <-> %s No matching %s\n", + name_codec, name_cpu, err_msg); + return -EINVAL; +} + /* * Called by ALSA when a PCM substream is opened, the runtime->hw record is * then initialized and any private data can be allocated. This also calls @@ -697,11 +735,8 @@ static int soc_pcm_close(struct snd_pcm_substream *substream) static int soc_pcm_open(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_pcm_runtime *runtime = substream->runtime; struct snd_soc_component *component; struct snd_soc_dai *dai; - const char *codec_dai_name = soc_codec_dai_name(rtd); - const char *cpu_dai_name = soc_cpu_dai_name(rtd); int i, ret = 0; for_each_rtd_components(rtd, i, component) @@ -742,23 +777,9 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) soc_pcm_update_symmetry(substream); - ret = -EINVAL; - if (!runtime->hw.rates) { - printk(KERN_ERR "ASoC: %s <-> %s No matching rates\n", - codec_dai_name, cpu_dai_name); + ret = soc_hw_sanity_check(substream); + if (ret < 0) goto err; - } - if (!runtime->hw.formats) { - printk(KERN_ERR "ASoC: %s <-> %s No matching formats\n", - codec_dai_name, cpu_dai_name); - goto err; - } - if (!runtime->hw.channels_min || !runtime->hw.channels_max || - runtime->hw.channels_min > runtime->hw.channels_max) { - printk(KERN_ERR "ASoC: %s <-> %s No matching channels\n", - codec_dai_name, cpu_dai_name); - goto err; - } soc_pcm_apply_msb(substream); @@ -768,14 +789,6 @@ static int soc_pcm_open(struct snd_pcm_substream *substream) if (ret != 0) goto err; } - - pr_debug("ASoC: %s <-> %s info:\n", - codec_dai_name, cpu_dai_name); - pr_debug("ASoC: rate mask 0x%x\n", runtime->hw.rates); - pr_debug("ASoC: min ch %d max ch %d\n", runtime->hw.channels_min, - runtime->hw.channels_max); - pr_debug("ASoC: min rate %d max rate %d\n", runtime->hw.rate_min, - runtime->hw.rate_max); dynamic: snd_soc_runtime_activate(rtd, substream->stream); ret = 0; From 1db19c151819dea7a0dc4d888250d25abaf229ca Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:08:08 +0900 Subject: [PATCH 0213/1091] ASoC: soc-pcm: fixup dpcm_be_dai_startup() user count At dpcm_be_dai_startup_unwind(), it indicates error message at (1) if this function was called with no users. But, it doesn't use "continue" here. Thus, users will be a negative number at (2) void dpcm_be_dai_startup_unwind(...) { ... for_each_dpcm_be(...) { ... (1) if (be->dpcm[stream].users == 0) dev_err(...); (2) if (--be->dpcm[stream].users != 0) continue; At dpcm_be_dai_startup(), it indicates error message if user reached to MAX USERS at (A). But, it doesn't use "continue" here. Thus, it will be over MAX USERS at (B). int dpcm_be_dai_startup(...) { ... for_each_dpcm_be(...) { ... (A) if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) dev_err(...); (B) if (be->dpcm[stream].users++ != 0) continue; These are just bug. This patch fixup these. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87czw9uoav.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 910a6afe9f48..626d6e0a3a15 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1432,10 +1432,12 @@ static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, struct snd_pcm_substream *be_substream = snd_soc_dpcm_get_substream(be, stream); - if (be->dpcm[stream].users == 0) + if (be->dpcm[stream].users == 0) { dev_err(be->dev, "ASoC: no users %s at close - state %d\n", stream ? "capture" : "playback", be->dpcm[stream].state); + continue; + } if (--be->dpcm[stream].users != 0) continue; @@ -1472,10 +1474,12 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) continue; /* first time the dpcm is open ? */ - if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) + if (be->dpcm[stream].users == DPCM_MAX_BE_USERS) { dev_err(be->dev, "ASoC: too many users %s at open %d\n", stream ? "capture" : "playback", be->dpcm[stream].state); + continue; + } if (be->dpcm[stream].users++ != 0) continue; @@ -1517,10 +1521,12 @@ unwind: if (!snd_soc_dpcm_be_can_update(fe, be, stream)) continue; - if (be->dpcm[stream].users == 0) + if (be->dpcm[stream].users == 0) { dev_err(be->dev, "ASoC: no users %s at close %d\n", stream ? "capture" : "playback", be->dpcm[stream].state); + continue; + } if (--be->dpcm[stream].users != 0) continue; From 20048a9a4070d046a868c3be3b4f7bdc139cc203 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:08:12 +0900 Subject: [PATCH 0214/1091] ASoC: soc-pcm: remove unneeded !rtd->dai_link check rtd->dai_link is setuped at soc_new_pcm_runtime(), thus "rtd->dai_link == NULL" is never happen. This patch removes unneeded !rtd->dai_link check Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87blbtuoar.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 626d6e0a3a15..0ae386f0790e 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -165,9 +165,6 @@ static const struct file_operations dpcm_state_fops = { void soc_dpcm_debugfs_add(struct snd_soc_pcm_runtime *rtd) { - if (!rtd->dai_link) - return; - if (!rtd->dai_link->dynamic) return; From 531590bb40f827fb3c4398148af0797f95bbaee2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 9 Mar 2021 10:08:17 +0900 Subject: [PATCH 0215/1091] ASoC: soc-pcm: share DPCM BE DAI stop operation soc-pcm has very similar but different DPCM BE DAI stop operation at 1) dpcm_be_dai_startup() error case rollback 2) dpcm_be_dai_startup_unwind() 3) dpcm_be_dai_shutdown() The differences are 1) for rollback 2) Doesn't check by snd_soc_dpcm_be_can_update() (Is this bug ?) 3) Do soc_pcm_hw_free() if it was not !OPENed and !HW_FREEed, and call soc_pcm_close(). We can share same code by 1) hw_free is not needed. Needs last dpcm as rollback. 2) hw_free is not needed. 3) hw_free is needed. This patch adds new dpcm_be_dai_stop() and share these 3. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a6rduoam.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 8 +++- sound/soc/soc-compress.c | 2 +- sound/soc/soc-pcm.c | 94 +++++++++------------------------------- 3 files changed, 28 insertions(+), 76 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index 0f6c50b17bba..d76cb1eeeaca 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -149,7 +149,8 @@ void dpcm_path_put(struct snd_soc_dapm_widget_list **list); int dpcm_process_paths(struct snd_soc_pcm_runtime *fe, int stream, struct snd_soc_dapm_widget_list **list, int new); int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream); -int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream); +void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, + int do_hw_free, struct snd_soc_dpcm *last); void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream); void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); @@ -159,4 +160,9 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_dapm_stream_event(struct snd_soc_pcm_runtime *fe, int dir, int event); +#define dpcm_be_dai_startup_rollback(fe, stream, last) \ + dpcm_be_dai_stop(fe, stream, 0, last) +#define dpcm_be_dai_startup_unwind(fe, stream) dpcm_be_dai_stop(fe, stream, 0, NULL) +#define dpcm_be_dai_shutdown(fe, stream) dpcm_be_dai_stop(fe, stream, 1, NULL) + #endif diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 246a5e32e22a..89445ba0e86b 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -189,7 +189,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) if (ret < 0) dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret); - ret = dpcm_be_dai_shutdown(fe, stream); + dpcm_be_dai_shutdown(fe, stream); /* mark FE's links ready to prune */ for_each_dpcm_be(fe, stream, dpcm) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 0ae386f0790e..a27385ab7b55 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1417,18 +1417,24 @@ void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream) spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); } -static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, - int stream) +void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, + int do_hw_free, struct snd_soc_dpcm *last) { struct snd_soc_dpcm *dpcm; /* disable any enabled and non active backends */ for_each_dpcm_be(fe, stream, dpcm) { - struct snd_soc_pcm_runtime *be = dpcm->be; struct snd_pcm_substream *be_substream = snd_soc_dpcm_get_substream(be, stream); + if (dpcm == last) + return; + + /* is this op for this BE ? */ + if (!snd_soc_dpcm_be_can_update(fe, be, stream)) + continue; + if (be->dpcm[stream].users == 0) { dev_err(be->dev, "ASoC: no users %s at close - state %d\n", stream ? "capture" : "playback", @@ -1439,8 +1445,15 @@ static void dpcm_be_dai_startup_unwind(struct snd_soc_pcm_runtime *fe, if (--be->dpcm[stream].users != 0) continue; - if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) - continue; + if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) { + if (!do_hw_free) + continue; + + if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) { + soc_pcm_hw_free(be_substream); + be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; + } + } soc_pcm_close(be_substream); be_substream->runtime = NULL; @@ -1509,32 +1522,7 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) return count; unwind: - /* disable any enabled and non active backends */ - for_each_dpcm_be_rollback(fe, stream, dpcm) { - struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_pcm_substream *be_substream = - snd_soc_dpcm_get_substream(be, stream); - - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) - continue; - - if (be->dpcm[stream].users == 0) { - dev_err(be->dev, "ASoC: no users %s at close %d\n", - stream ? "capture" : "playback", - be->dpcm[stream].state); - continue; - } - - if (--be->dpcm[stream].users != 0) - continue; - - if (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN) - continue; - - soc_pcm_close(be_substream); - be_substream->runtime = NULL; - be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; - } + dpcm_be_dai_startup_rollback(fe, stream, dpcm); return err; } @@ -1782,46 +1770,6 @@ be_err: return ret; } -int dpcm_be_dai_shutdown(struct snd_soc_pcm_runtime *fe, int stream) -{ - struct snd_soc_dpcm *dpcm; - - /* only shutdown BEs that are either sinks or sources to this FE DAI */ - for_each_dpcm_be(fe, stream, dpcm) { - - struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_pcm_substream *be_substream = - snd_soc_dpcm_get_substream(be, stream); - - /* is this op for this BE ? */ - if (!snd_soc_dpcm_be_can_update(fe, be, stream)) - continue; - - if (be->dpcm[stream].users == 0) - dev_err(be->dev, "ASoC: no users %s at close - state %d\n", - stream ? "capture" : "playback", - be->dpcm[stream].state); - - if (--be->dpcm[stream].users != 0) - continue; - - if ((be->dpcm[stream].state != SND_SOC_DPCM_STATE_HW_FREE) && - (be->dpcm[stream].state != SND_SOC_DPCM_STATE_OPEN)) { - soc_pcm_hw_free(be_substream); - be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; - } - - dev_dbg(be->dev, "ASoC: close BE %s\n", - be->dai_link->name); - - soc_pcm_close(be_substream); - be_substream->runtime = NULL; - - be->dpcm[stream].state = SND_SOC_DPCM_STATE_CLOSE; - } - return 0; -} - static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); @@ -2371,9 +2319,7 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) if (err < 0) dev_err(fe->dev,"ASoC: hw_free FE failed %d\n", err); - err = dpcm_be_dai_shutdown(fe, stream); - if (err < 0) - dev_err(fe->dev,"ASoC: shutdown FE failed %d\n", err); + dpcm_be_dai_shutdown(fe, stream); /* run the stream event for each BE */ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP); From 2e5e57f085a3243aae7e4af88dc2c40e5ff4d3be Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:49:01 -0600 Subject: [PATCH 0216/1091] ASoC: mediatek: mtk-btcvsd: remove useless assignment cppcheck warning: sound/soc/mediatek/common/mtk-btcvsd.c:783:34: style: Variable 'avail' is assigned a value that is never used. [unreadVariable] int written_size = count, avail = 0, cur_write_idx, write_size, cont; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210311004904.121205-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/mediatek/common/mtk-btcvsd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/mediatek/common/mtk-btcvsd.c b/sound/soc/mediatek/common/mtk-btcvsd.c index a554c57b6460..f85b5ea180ec 100644 --- a/sound/soc/mediatek/common/mtk-btcvsd.c +++ b/sound/soc/mediatek/common/mtk-btcvsd.c @@ -780,7 +780,7 @@ static ssize_t mtk_btcvsd_snd_write(struct mtk_btcvsd_snd *bt, char __user *buf, size_t count) { - int written_size = count, avail = 0, cur_write_idx, write_size, cont; + int written_size = count, avail, cur_write_idx, write_size, cont; unsigned int cur_buf_ofs = 0; unsigned long flags; unsigned int packet_size = bt->tx->packet_size; From 57f1379e77a7432759e2f35b720c71863e2d83bc Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:49:02 -0600 Subject: [PATCH 0217/1091] ASoC: mediatek: mt2701: align function prototype cppcheck warnings: sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c:102:30: style:inconclusive: Function 'mt2701_afe_enable_i2s' argument 2 names different: declaration 'path' definition 'i2s_path'. [funcArgNamesDifferent] struct mt2701_i2s_path *i2s_path, ^ sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h:21:30: note: Function 'mt2701_afe_enable_i2s' argument 2 names different: declaration 'path' definition 'i2s_path'. struct mt2701_i2s_path *path, ^ sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c:102:30: note: Function 'mt2701_afe_enable_i2s' argument 2 names different: declaration 'path' definition 'i2s_path'. struct mt2701_i2s_path *i2s_path, ^ sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c:128:32: style:inconclusive: Function 'mt2701_afe_disable_i2s' argument 2 names different: declaration 'path' definition 'i2s_path'. [funcArgNamesDifferent] struct mt2701_i2s_path *i2s_path, ^ sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h:24:32: note: Function 'mt2701_afe_disable_i2s' argument 2 names different: declaration 'path' definition 'i2s_path'. struct mt2701_i2s_path *path, ^ sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.c:128:32: note: Function 'mt2701_afe_disable_i2s' argument 2 names different: declaration 'path' definition 'i2s_path'. struct mt2701_i2s_path *i2s_path, ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210311004904.121205-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h index 580fead2ab05..0bd82fbda176 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h +++ b/sound/soc/mediatek/mt2701/mt2701-afe-clock-ctrl.h @@ -18,10 +18,10 @@ int mt2701_afe_enable_clock(struct mtk_base_afe *afe); int mt2701_afe_disable_clock(struct mtk_base_afe *afe); int mt2701_afe_enable_i2s(struct mtk_base_afe *afe, - struct mt2701_i2s_path *path, + struct mt2701_i2s_path *i2s_path, int dir); void mt2701_afe_disable_i2s(struct mtk_base_afe *afe, - struct mt2701_i2s_path *path, + struct mt2701_i2s_path *i2s_path, int dir); int mt2701_afe_enable_mclk(struct mtk_base_afe *afe, int id); void mt2701_afe_disable_mclk(struct mtk_base_afe *afe, int id); From d9cdc1335622866c52a463325b3aaea9844cff1b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:49:03 -0600 Subject: [PATCH 0218/1091] ASoC: mediatek: mt2701: rename shadowed array cppcheck warning: sound/soc/mediatek/mt2701/mt2701-afe-pcm.c:406:36: style: Local variable 'memif_data' shadows outer variable [shadowVariable] const struct mtk_base_memif_data *memif_data; ^ sound/soc/mediatek/mt2701/mt2701-afe-pcm.c:977:41: note: Shadowed declaration static const struct mtk_base_memif_data memif_data[MT2701_MEMIF_NUM] = { ^ sound/soc/mediatek/mt2701/mt2701-afe-pcm.c:406:36: note: Shadow variable const struct mtk_base_memif_data *memif_data; ^ sound/soc/mediatek/mt2701/mt2701-afe-pcm.c:431:36: style: Local variable 'memif_data' shadows outer variable [shadowVariable] const struct mtk_base_memif_data *memif_data; ^ sound/soc/mediatek/mt2701/mt2701-afe-pcm.c:977:41: note: Shadowed declaration static const struct mtk_base_memif_data memif_data[MT2701_MEMIF_NUM] = { ^ sound/soc/mediatek/mt2701/mt2701-afe-pcm.c:431:36: note: Shadow variable const struct mtk_base_memif_data *memif_data; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210311004904.121205-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt2701/mt2701-afe-pcm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c index d5cffe7a7e15..bc3d0466472b 100644 --- a/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c +++ b/sound/soc/mediatek/mt2701/mt2701-afe-pcm.c @@ -974,7 +974,7 @@ static const struct snd_soc_component_driver mt2701_afe_pcm_dai_component = { .resume = mtk_afe_resume, }; -static const struct mtk_base_memif_data memif_data[MT2701_MEMIF_NUM] = { +static const struct mtk_base_memif_data memif_data_array[MT2701_MEMIF_NUM] = { { .name = "DL1", .id = MT2701_MEMIF_DL1, @@ -1366,7 +1366,7 @@ static int mt2701_afe_pcm_dev_probe(struct platform_device *pdev) return -ENOMEM; for (i = 0; i < afe->memif_size; i++) { - afe->memif[i].data = &memif_data[i]; + afe->memif[i].data = &memif_data_array[i]; afe->memif[i].irq_usage = -1; } From 14667403a5631ce2fd2935d90c6d36f7975f61f3 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Wed, 10 Mar 2021 18:49:04 -0600 Subject: [PATCH 0219/1091] ASoC: mediatek: mt8173: rename local irq variable cppcheck warning: sound/soc/mediatek/mt8173/mt8173-afe-pcm.c:929:28: style: Local variable 'irq' shadows outer argument [shadowArgument] struct mtk_base_afe_irq *irq; ^ sound/soc/mediatek/mt8173/mt8173-afe-pcm.c:914:47: note: Shadowed declaration static irqreturn_t mt8173_afe_irq_handler(int irq, void *dev_id) ^ sound/soc/mediatek/mt8173/mt8173-afe-pcm.c:929:28: note: Shadow variable struct mtk_base_afe_irq *irq; ^ Not a great idea to have two 'irq' variables in the same function... Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210311004904.121205-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/mediatek/mt8173/mt8173-afe-pcm.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c index 685f4074b4e0..6350390414d4 100644 --- a/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c +++ b/sound/soc/mediatek/mt8173/mt8173-afe-pcm.c @@ -926,14 +926,14 @@ static irqreturn_t mt8173_afe_irq_handler(int irq, void *dev_id) for (i = 0; i < MT8173_AFE_MEMIF_NUM; i++) { struct mtk_base_afe_memif *memif = &afe->memif[i]; - struct mtk_base_afe_irq *irq; + struct mtk_base_afe_irq *irq_p; if (memif->irq_usage < 0) continue; - irq = &afe->irqs[memif->irq_usage]; + irq_p = &afe->irqs[memif->irq_usage]; - if (!(reg_value & (1 << irq->irq_data->irq_clr_shift))) + if (!(reg_value & (1 << irq_p->irq_data->irq_clr_shift))) continue; snd_pcm_period_elapsed(memif->substream); From fac245216b68cdfccf3e2a8d20d6710b750bf20f Mon Sep 17 00:00:00 2001 From: Vineet Gupta Date: Thu, 11 Feb 2021 16:43:53 -0800 Subject: [PATCH 0220/1091] ARC: haps: bump memory to 1 GB Signed-off-by: Vineet Gupta --- arch/arc/boot/dts/haps_hs.dts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arc/boot/dts/haps_hs.dts b/arch/arc/boot/dts/haps_hs.dts index 60d578e2781f..76ad527a0847 100644 --- a/arch/arc/boot/dts/haps_hs.dts +++ b/arch/arc/boot/dts/haps_hs.dts @@ -16,7 +16,7 @@ memory { device_type = "memory"; /* CONFIG_LINUX_RAM_BASE needs to match low mem start */ - reg = <0x0 0x80000000 0x0 0x20000000 /* 512 MB low mem */ + reg = <0x0 0x80000000 0x0 0x40000000 /* 1 GB low mem */ 0x1 0x00000000 0x0 0x40000000>; /* 1 GB highmem */ }; From b7c7203a1f751348f35fc4bcb157572d303f7573 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 12 Mar 2021 12:48:50 +0100 Subject: [PATCH 0221/1091] ASoC: Intel: bytcr_rt5640: Enable jack-detect support on Asus T100TAF The Asus T100TAF uses the same jack-detect settings as the T100TA, this has been confirmed on actual hardware. Add these settings to the T100TAF quirks to enable jack-detect support on the T100TAF. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312114850.13832-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 5d48cc359c3d..19faababb78d 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -482,6 +482,9 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { DMI_EXACT_MATCH(DMI_PRODUCT_NAME, "T100TAF"), }, .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | BYT_RT5640_MONO_SPEAKER | BYT_RT5640_DIFF_MIC | BYT_RT5640_SSP0_AIF2 | From 464b489a7885d6a89b0dfa7b7f1f56e2db80700d Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Fri, 12 Mar 2021 02:45:15 +0000 Subject: [PATCH 0222/1091] ASoC: rt1015p: add acpi device id for rt1015p Add acpi device id for rt1015p. Signed-off-by: Jack Yu Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/949671bd00c14b6d9aa5e85cc14be5d4@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015p.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/sound/soc/codecs/rt1015p.c b/sound/soc/codecs/rt1015p.c index 671f2a2130fe..39f4c4ed2ab8 100644 --- a/sound/soc/codecs/rt1015p.c +++ b/sound/soc/codecs/rt1015p.c @@ -4,6 +4,7 @@ // // Copyright 2020 The Linux Foundation. All rights reserved. +#include #include #include #include @@ -130,10 +131,19 @@ static const struct of_device_id rt1015p_device_id[] = { MODULE_DEVICE_TABLE(of, rt1015p_device_id); #endif +#ifdef CONFIG_ACPI +static const struct acpi_device_id rt1015p_acpi_match[] = { + { "RTL1015", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, rt1015p_acpi_match); +#endif + static struct platform_driver rt1015p_platform_driver = { .driver = { .name = "rt1015p", .of_match_table = of_match_ptr(rt1015p_device_id), + .acpi_match_table = ACPI_PTR(rt1015p_acpi_match), }, .probe = rt1015p_platform_probe, }; From d58970da324732686529655c21791cef0ee547c4 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:02:30 -0600 Subject: [PATCH 0223/1091] ASoC: samsung: tm2_wm5110: check of of_parse return value cppcheck warning: sound/soc/samsung/tm2_wm5110.c:605:6: style: Variable 'ret' is reassigned a value before the old one has been used. [redundantAssignment] ret = devm_snd_soc_register_component(dev, &tm2_component, ^ sound/soc/samsung/tm2_wm5110.c:554:7: note: ret is assigned ret = of_parse_phandle_with_args(dev->of_node, "i2s-controller", ^ sound/soc/samsung/tm2_wm5110.c:605:6: note: ret is overwritten ret = devm_snd_soc_register_component(dev, &tm2_component, ^ The args is a stack variable, so it could have junk (uninitialized) therefore args.np could have a non-NULL and random value even though property was missing. Later could trigger invalid pointer dereference. There's no need to check for args.np because args.np won't be initialized on errors. Fixes: 8d1513cef51a ("ASoC: samsung: Add support for HDMI audio on TM2 board") Cc: Suggested-by: Krzysztof Kozlowski Reviewed-by: Krzysztof Kozlowski Reviewed-by: Sylwester Nawrocki Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312180231.2741-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 9300fef9bf26..125e07f65d2b 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -553,7 +553,7 @@ static int tm2_probe(struct platform_device *pdev) ret = of_parse_phandle_with_args(dev->of_node, "i2s-controller", cells_name, i, &args); - if (!args.np) { + if (ret) { dev_err(dev, "i2s-controller property parse error: %d\n", i); ret = -EINVAL; goto dai_node_put; From f7b61287cf17486dd09438115a993d699db2ab3b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:02:31 -0600 Subject: [PATCH 0224/1091] ASoC: samsung: tm2_wm5110: remove shadowed variable cppcheck warning: sound/soc/samsung/tm2_wm5110.c:552:26: style: Local variable 'args' shadows outer variable [shadowVariable] struct of_phandle_args args; ^ sound/soc/samsung/tm2_wm5110.c:504:25: note: Shadowed declaration struct of_phandle_args args; ^ sound/soc/samsung/tm2_wm5110.c:552:26: note: Shadow variable struct of_phandle_args args; ^ Move the top-level variable to the lower scope where it's needed. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Krzysztof Kozlowski Link: https://lore.kernel.org/r/20210312180231.2741-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/samsung/tm2_wm5110.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/samsung/tm2_wm5110.c b/sound/soc/samsung/tm2_wm5110.c index 125e07f65d2b..84c2c63d5a87 100644 --- a/sound/soc/samsung/tm2_wm5110.c +++ b/sound/soc/samsung/tm2_wm5110.c @@ -501,7 +501,6 @@ static int tm2_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct snd_soc_card *card = &tm2_card; struct tm2_machine_priv *priv; - struct of_phandle_args args; struct snd_soc_dai_link *dai_link; int num_codecs, ret, i; @@ -585,6 +584,8 @@ static int tm2_probe(struct platform_device *pdev) } if (num_codecs > 1) { + struct of_phandle_args args; + /* HDMI DAI link (I2S1) */ i = card->num_links - 1; From 40e4046913a34dd187c94f66c0f43facbff0f430 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:05:02 +0100 Subject: [PATCH 0225/1091] ASoC: rt5640: Rename 'Mono DAC Playback Volume' to 'DAC2 Playback Volume' Rename 'Mono DAC Playback Volume' to 'DAC2 Playback Volume' and move it from rt5640_specific_snd_controls[] to rt5640_snd_controls[]. The RT5640_DAC2_DIG_VOL register controlled by this mixer-element has nothing to do with the Mono (Amplified) output which is only available on the ALC5640 chip and not on the ALC5642 chip. The RT5640_DAC2_DIG_VOL volume-control is the main volume control for audio coming from the I2S2 / AIF2 input of the chip and as such is also available on the ALC5642. This commit results in the following userspace visible changes: 1. On devices with an ACL5640 codec, the 'Mono DAC Playback Volume' control is renamed to 'DAC2 Playback Volume' allowing the alsa-lib mixer code to properly group it with the 'DAC2 Playback Switch' which is controlling the mute bits in the RT5640_DAC2_DIG_VOL register. Note the removal of the 'Mono DAC Playback Volume' is not an issue for userspace because the UCM profiles do not use it (the UCM profiles are shared betweent the 5640 and 5642 and only the 5640 had this control). 2. On devices with an ACL5642 codec, there now will be a new 'DAC2 Playback Volume', grouped with the 'DAC2 Playback Switch' Having a complete 'DAC2 Playback Volume' / 'DAC2 Playback Switch' pair on both variants will allow enabling hardware-volume control by setting the UCM PlaybackMasterElem to "DAC2" on devices where the I2S2/AIF2 interface of the codec is used. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307150503.34906-2-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5640.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5640.c b/sound/soc/codecs/rt5640.c index 8c1766954b92..9523f4b5c800 100644 --- a/sound/soc/codecs/rt5640.c +++ b/sound/soc/codecs/rt5640.c @@ -400,6 +400,9 @@ static const struct snd_kcontrol_new rt5640_snd_controls[] = { /* DAC Digital Volume */ SOC_DOUBLE("DAC2 Playback Switch", RT5640_DAC2_CTRL, RT5640_M_DAC_L2_VOL_SFT, RT5640_M_DAC_R2_VOL_SFT, 1, 1), + SOC_DOUBLE_TLV("DAC2 Playback Volume", RT5640_DAC2_DIG_VOL, + RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, + 175, 0, dac_vol_tlv), SOC_DOUBLE_TLV("DAC1 Playback Volume", RT5640_DAC1_DIG_VOL, RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 175, 0, dac_vol_tlv), @@ -443,9 +446,6 @@ static const struct snd_kcontrol_new rt5640_specific_snd_controls[] = { /* MONO Output Control */ SOC_SINGLE("Mono Playback Switch", RT5640_MONO_OUT, RT5640_L_MUTE_SFT, 1, 1), - - SOC_DOUBLE_TLV("Mono DAC Playback Volume", RT5640_DAC2_DIG_VOL, - RT5640_L_VOL_SFT, RT5640_R_VOL_SFT, 175, 0, dac_vol_tlv), }; /** From 9f47c9c8bddc79e770ed19366840b9c2ab280ac1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:05:03 +0100 Subject: [PATCH 0226/1091] ASoC: Intel: bytcr_rt5640: Add used AIF to the components string Depending on which AIF is used the UCM profile needs to setup a different path through the rt5640's "Digital Mixer Path" graph. ATM the UCM profiles solve this by just enabling paths to the outputs / from the input from both AIF1 and AIF2 and then relying on the DAPM framework to power-down the parts of the graph connected to the unused AIF. But in order to be able to use hardware-volumecontrol and to use the hardware mute controls, which are necessary for mute LED control, the UCM profiles need to know which AIF is actually being used. Add a new "aif:1" or "aif:2" part to the component string to provide info about the used AIF to userspace / to the UCM profiles. Note the size of byt_rt5640_components is not increased because the size of 32 chars already is big enough. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307150503.34906-3-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 19faababb78d..59d6d47c8d82 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -1255,6 +1255,7 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) int ret_val = 0; int dai_index = 0; int i, cfg_spk; + int aif; is_bytcr = false; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); @@ -1366,8 +1367,12 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) log_quirks(&pdev->dev); if ((byt_rt5640_quirk & BYT_RT5640_SSP2_AIF2) || - (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) + (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) { byt_rt5640_dais[dai_index].codecs->dai_name = "rt5640-aif2"; + aif = 2; + } else { + aif = 1; + } if ((byt_rt5640_quirk & BYT_RT5640_SSP0_AIF1) || (byt_rt5640_quirk & BYT_RT5640_SSP0_AIF2)) @@ -1405,8 +1410,8 @@ static int snd_byt_rt5640_mc_probe(struct platform_device *pdev) } snprintf(byt_rt5640_components, sizeof(byt_rt5640_components), - "cfg-spk:%d cfg-mic:%s", cfg_spk, - map_name[BYT_RT5640_MAP(byt_rt5640_quirk)]); + "cfg-spk:%d cfg-mic:%s aif:%d", cfg_spk, + map_name[BYT_RT5640_MAP(byt_rt5640_quirk)], aif); byt_rt5640_card.components = byt_rt5640_components; #if !IS_ENABLED(CONFIG_SND_SOC_INTEL_USER_FRIENDLY_LONG_NAMES) snprintf(byt_rt5640_long_name, sizeof(byt_rt5640_long_name), From ee427ea4f12672e5d7874abaa634ddee0ff2bb97 Mon Sep 17 00:00:00 2001 From: Robin Gong Date: Fri, 5 Mar 2021 17:19:37 +0800 Subject: [PATCH 0227/1091] ASoC: fsl_asrc_dma: request dma channel from specific controller Request dma channel from specific dma controller instead of generic dma controller list, otherwise, may get the wrong dma controller if there are multi dma controllers such as i.MX8MP. Signed-off-by: Robin Gong Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1614935977-21638-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc_dma.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_asrc_dma.c b/sound/soc/fsl/fsl_asrc_dma.c index 29f91cdecbc3..c313a26c8f95 100644 --- a/sound/soc/fsl/fsl_asrc_dma.c +++ b/sound/soc/fsl/fsl_asrc_dma.c @@ -141,6 +141,7 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, struct dma_slave_config config_fe, config_be; enum asrc_pair_index index = pair->index; struct device *dev = component->dev; + struct device_node *of_dma_node; int stream = substream->stream; struct imx_dma_data *tmp_data; struct snd_soc_dpcm *dpcm; @@ -231,8 +232,10 @@ static int fsl_asrc_dma_hw_params(struct snd_soc_component *component, pair->dma_data.priority = tmp_data->priority; dma_release_channel(tmp_chan); + of_dma_node = pair->dma_chan[!dir]->device->dev->of_node; pair->dma_chan[dir] = - dma_request_channel(mask, filter, &pair->dma_data); + __dma_request_channel(&mask, filter, &pair->dma_data, + of_dma_node); pair->req_dma_chan = true; } else { pair->dma_chan[dir] = tmp_chan; From c9570d4a5efd04479b3cd09c39b571eb031d94f4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Thu, 31 Dec 2020 09:52:52 +0100 Subject: [PATCH 0228/1091] extcon: Add stubs for extcon_register_notifier_all() functions Add stubs for extcon_register_notifier_all() function for !CONFIG_EXTCON case. This is useful for compile testing and for drivers which use EXTCON but do not require it (therefore do not depend on CONFIG_EXTCON). Fixes: 815429b39d94 ("extcon: Add new extcon_register_notifier_all() to monitor all external connectors") Reported-by: kernel test robot Signed-off-by: Krzysztof Kozlowski Signed-off-by: Chanwoo Choi --- include/linux/extcon.h | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/include/linux/extcon.h b/include/linux/extcon.h index fd183fb9c20f..0c19010da77f 100644 --- a/include/linux/extcon.h +++ b/include/linux/extcon.h @@ -271,6 +271,29 @@ static inline void devm_extcon_unregister_notifier(struct device *dev, struct extcon_dev *edev, unsigned int id, struct notifier_block *nb) { } +static inline int extcon_register_notifier_all(struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline int extcon_unregister_notifier_all(struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline int devm_extcon_register_notifier_all(struct device *dev, + struct extcon_dev *edev, + struct notifier_block *nb) +{ + return 0; +} + +static inline void devm_extcon_unregister_notifier_all(struct device *dev, + struct extcon_dev *edev, + struct notifier_block *nb) { } + static inline struct extcon_dev *extcon_get_extcon_dev(const char *extcon_name) { return ERR_PTR(-ENODEV); From d3bdd1c3140724967ca4136755538fa7c05c2b4e Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Tue, 19 Jan 2021 16:10:55 +0800 Subject: [PATCH 0229/1091] extcon: Fix error handling in extcon_dev_register When devm_kcalloc() fails, we should execute device_unregister() to unregister edev->dev from system. Fixes: 046050f6e623e ("extcon: Update the prototype of extcon_register_notifier() with enum extcon") Signed-off-by: Dinghao Liu Signed-off-by: Chanwoo Choi --- drivers/extcon/extcon.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/extcon/extcon.c b/drivers/extcon/extcon.c index 0a6438cbb3f3..e7a9561a826d 100644 --- a/drivers/extcon/extcon.c +++ b/drivers/extcon/extcon.c @@ -1241,6 +1241,7 @@ int extcon_dev_register(struct extcon_dev *edev) sizeof(*edev->nh), GFP_KERNEL); if (!edev->nh) { ret = -ENOMEM; + device_unregister(&edev->dev); goto err_dev; } From 62dd0f98a0e5668424270b47a0c2e973795faba7 Mon Sep 17 00:00:00 2001 From: Andrew Price Date: Mon, 15 Mar 2021 12:24:00 +0000 Subject: [PATCH 0230/1091] gfs2: Flag a withdraw if init_threads() fails Interrupting mount with ^C quickly enough can cause the kthread_run() calls in gfs2's init_threads() to fail and the error path leads to a deadlock on the s_umount rwsem. The abridged chain of events is: [mount path] get_tree_bdev() sget_fc() alloc_super() down_write_nested(&s->s_umount, SINGLE_DEPTH_NESTING); [acquired] gfs2_fill_super() gfs2_make_fs_rw() init_threads() kthread_run() ( Interrupted ) [Error path] gfs2_gl_hash_clear() flush_workqueue(glock_workqueue) wait_for_completion() [workqueue context] glock_work_func() run_queue() do_xmote() freeze_go_sync() freeze_super() down_write(&sb->s_umount) [deadlock] In freeze_go_sync() there is a gfs2_withdrawn() check that we can use to make sure freeze_super() is not called in the error path, so add a gfs2_withdraw_delayed() call when init_threads() fails. Ref: https://bugzilla.kernel.org/show_bug.cgi?id=212231 Reported-by: Alexander Aring Signed-off-by: Andrew Price Signed-off-by: Andreas Gruenbacher --- fs/gfs2/super.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 97076d3f562f..9e91c9d92bd6 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -162,8 +162,10 @@ int gfs2_make_fs_rw(struct gfs2_sbd *sdp) int error; error = init_threads(sdp); - if (error) + if (error) { + gfs2_withdraw_delayed(sdp); return error; + } j_gl->gl_ops->go_inval(j_gl, DIO_METADATA); if (gfs2_withdrawn(sdp)) { From 3b6e7088afc919f5b52e4d2de8501ad34d35b09b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 12 Mar 2021 14:02:40 +0100 Subject: [PATCH 0231/1091] regulator: bd9571mwv: Fix AVS and DVFS voltage range According to Table 30 ("DVFS_MoniVDAC [6:0] Setting Table") in the BD9571MWV-M Datasheet Rev. 002, the valid voltage range is 600..1100 mV (settings 0x3c..0x6e). While the lower limit is taken into account (by setting regulator_desc.linear_min_sel to 0x3c), the upper limit is not. Fix this by reducing regulator_desc.n_voltages from 0x80 to 0x6f. Fixes: e85c5a153fe237f2 ("regulator: Add ROHM BD9571MWV-M PMIC regulator driver") Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210312130242.3390038-2-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/regulator/bd9571mwv-regulator.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index 7b0cd08db446..13393cdc6be1 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -125,7 +125,7 @@ static const struct regulator_ops vid_ops = { static const struct regulator_desc regulators[] = { BD9571MWV_REG("VD09", "vd09", VD09, avs_ops, 0, 0x7f, - 0x80, 600000, 10000, 0x3c), + 0x6f, 600000, 10000, 0x3c), BD9571MWV_REG("VD18", "vd18", VD18, vid_ops, BD9571MWV_VD18_VID, 0xf, 16, 1625000, 25000, 0), BD9571MWV_REG("VD25", "vd25", VD25, vid_ops, BD9571MWV_VD25_VID, 0xf, @@ -134,7 +134,7 @@ static const struct regulator_desc regulators[] = { 11, 2800000, 100000, 0), BD9571MWV_REG("DVFS", "dvfs", DVFS, reg_ops, BD9571MWV_DVFS_MONIVDAC, 0x7f, - 0x80, 600000, 10000, 0x3c), + 0x6f, 600000, 10000, 0x3c), }; #ifdef CONFIG_PM_SLEEP From 9cbc23f7d51fb0b1363bdfdd0b770aa7b5982f2f Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 12 Mar 2021 14:02:41 +0100 Subject: [PATCH 0232/1091] regulator: bd9571mwv: Fix regulator name printed on registration failure If a regulator fails to register, the driver prints an error message like: bd9571mwv-regulator bd9571mwv-regulator.6.auto: failed to register bd9571mwv-regulator regulator However, the platform device's name is already printed as part of dev_err(), and does not allow the user to distinguish among the various regulators that are part of the PMIC. Fix this by printing regulator_desc.name instead, to change the message like: bd9571mwv-regulator bd9571mwv-regulator.6.auto: failed to register DVFS regulator Signed-off-by: Geert Uytterhoeven Reviewed-by: Matti Vaittinen Link: https://lore.kernel.org/r/20210312130242.3390038-3-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/regulator/bd9571mwv-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index 13393cdc6be1..a4d406022587 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -301,7 +301,7 @@ static int bd9571mwv_regulator_probe(struct platform_device *pdev) &config); if (IS_ERR(rdev)) { dev_err(&pdev->dev, "failed to register %s regulator\n", - pdev->name); + regulators[i].name); return PTR_ERR(rdev); } } From 1deceabbdc0dd3162def1e26acb2e57a93275909 Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 12 Mar 2021 14:02:42 +0100 Subject: [PATCH 0233/1091] regulator: bd9571mwv: Convert device attribute to sysfs_emit() Convert the "backup_mode" device attribute from sprintf() to sysfs_emit(), as the latter is aware of the PAGE_SIZE buffer. Signed-off-by: Geert Uytterhoeven Link: https://lore.kernel.org/r/20210312130242.3390038-4-geert+renesas@glider.be Signed-off-by: Mark Brown --- drivers/regulator/bd9571mwv-regulator.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/regulator/bd9571mwv-regulator.c b/drivers/regulator/bd9571mwv-regulator.c index a4d406022587..ba020a45f238 100644 --- a/drivers/regulator/bd9571mwv-regulator.c +++ b/drivers/regulator/bd9571mwv-regulator.c @@ -174,7 +174,7 @@ static ssize_t backup_mode_show(struct device *dev, { struct bd9571mwv_reg *bdreg = dev_get_drvdata(dev); - return sprintf(buf, "%s\n", bdreg->bkup_mode_enabled ? "on" : "off"); + return sysfs_emit(buf, "%s\n", bdreg->bkup_mode_enabled ? "on" : "off"); } static ssize_t backup_mode_store(struct device *dev, From 1cbd44666216278bbb6a55bcb6b9283702171c77 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 7 Mar 2021 06:06:28 +0200 Subject: [PATCH 0234/1091] dmaengine: xilinx: dpdma: Fix descriptor issuing on video group When multiple channels are part of a video group, the transfer is triggered only when all channels in the group are ready. The logic to do so is incorrect, as it causes the descriptors for all channels but the last one in a group to not being pushed to the hardware. Fix it. Signed-off-by: Laurent Pinchart Link: https://lore.kernel.org/r/20210307040629.29308-2-laurent.pinchart@ideasonboard.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dpdma.c | 28 +++++++++++++++++----------- 1 file changed, 17 insertions(+), 11 deletions(-) diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index 55df63dead8d..d504112c609e 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -839,6 +839,7 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan) struct xilinx_dpdma_tx_desc *desc; struct virt_dma_desc *vdesc; u32 reg, channels; + bool first_frame; lockdep_assert_held(&chan->lock); @@ -852,14 +853,6 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan) chan->running = true; } - if (chan->video_group) - channels = xilinx_dpdma_chan_video_group_ready(chan); - else - channels = BIT(chan->id); - - if (!channels) - return; - vdesc = vchan_next_desc(&chan->vchan); if (!vdesc) return; @@ -884,13 +877,26 @@ static void xilinx_dpdma_chan_queue_transfer(struct xilinx_dpdma_chan *chan) FIELD_PREP(XILINX_DPDMA_CH_DESC_START_ADDRE_MASK, upper_32_bits(sw_desc->dma_addr))); - if (chan->first_frame) + first_frame = chan->first_frame; + chan->first_frame = false; + + if (chan->video_group) { + channels = xilinx_dpdma_chan_video_group_ready(chan); + /* + * Trigger the transfer only when all channels in the group are + * ready. + */ + if (!channels) + return; + } else { + channels = BIT(chan->id); + } + + if (first_frame) reg = XILINX_DPDMA_GBL_TRIG_MASK(channels); else reg = XILINX_DPDMA_GBL_RETRIG_MASK(channels); - chan->first_frame = false; - dpdma_write(xdev->reg, XILINX_DPDMA_GBL, reg); } From 868833fbffbe51c487df4f95d4de9194264a4b30 Mon Sep 17 00:00:00 2001 From: Laurent Pinchart Date: Sun, 7 Mar 2021 06:06:29 +0200 Subject: [PATCH 0235/1091] dmaengine: xilinx: dpdma: Fix race condition in done IRQ The active descriptor pointer is accessed from different contexts, including different interrupt handlers, and its access must be protected by the channel's lock. This wasn't done in the done IRQ handler. Fix it. Signed-off-by: Laurent Pinchart Link: https://lore.kernel.org/r/20210307040629.29308-3-laurent.pinchart@ideasonboard.com Signed-off-by: Vinod Koul --- drivers/dma/xilinx/xilinx_dpdma.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/dma/xilinx/xilinx_dpdma.c b/drivers/dma/xilinx/xilinx_dpdma.c index d504112c609e..70b29bd079c9 100644 --- a/drivers/dma/xilinx/xilinx_dpdma.c +++ b/drivers/dma/xilinx/xilinx_dpdma.c @@ -1048,13 +1048,14 @@ static int xilinx_dpdma_chan_stop(struct xilinx_dpdma_chan *chan) */ static void xilinx_dpdma_chan_done_irq(struct xilinx_dpdma_chan *chan) { - struct xilinx_dpdma_tx_desc *active = chan->desc.active; + struct xilinx_dpdma_tx_desc *active; unsigned long flags; spin_lock_irqsave(&chan->lock, flags); xilinx_dpdma_debugfs_desc_done_irq(chan); + active = chan->desc.active; if (active) vchan_cyclic_callback(&active->vdesc); else From 11fd6d8e097b5b179ea445e0206aaefc47e62845 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 15 Mar 2021 11:39:30 -0500 Subject: [PATCH 0236/1091] ASoC: SOF: fix debugfs initialisation error handling If debugfs initialisation fails partially in sof_probe_continue() some debugfs files and the root directory might have been created successfully. They have to be cleaned up if some of them failed too. Reviewed-by: Ranjani Sridharan Reviewed-by: Xiuli Pan Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210315163932.18663-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 6d8f7d9fd192..495295a34c3a 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -154,7 +154,7 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) if (ret < 0) { dev_err(sdev->dev, "error: failed to get machine info %d\n", ret); - goto dbg_err; + goto dsp_err; } /* set up platform component driver */ @@ -257,8 +257,9 @@ fw_run_err: fw_load_err: snd_sof_ipc_free(sdev); ipc_err: - snd_sof_free_debug(sdev); dbg_err: + snd_sof_free_debug(sdev); +dsp_err: snd_sof_remove(sdev); /* all resources freed, update state to match */ From 72c35856b5edc3f734be5699e9f6737190a1d897 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 15 Mar 2021 11:39:31 -0500 Subject: [PATCH 0237/1091] ASoC: SOF: only allocate debugfs cache buffers for IPC flood entries snd_sof_debugfs_buf_item() is an exported function and is called from different locations to initialise different debugfs entries. However .cache_buf is only needed for IPC flood entries. Limit allocations respectively. Reviewed-by: Ranjani Sridharan Reviewed-by: Xiuli Pan Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210315163932.18663-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 715a374b33cf..778c7d028493 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -609,14 +609,16 @@ int snd_sof_debugfs_buf_item(struct snd_sof_dev *sdev, dfse->sdev = sdev; #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_IPC_FLOOD_TEST) - /* - * cache_buf is unused for SOF_DFSENTRY_TYPE_BUF debugfs entries. - * So, use it to save the results of the last IPC flood test. - */ - dfse->cache_buf = devm_kzalloc(sdev->dev, IPC_FLOOD_TEST_RESULT_LEN, - GFP_KERNEL); - if (!dfse->cache_buf) - return -ENOMEM; + if (!strncmp(name, "ipc_flood", strlen("ipc_flood"))) { + /* + * cache_buf is unused for SOF_DFSENTRY_TYPE_BUF debugfs entries. + * So, use it to save the results of the last IPC flood test. + */ + dfse->cache_buf = devm_kzalloc(sdev->dev, IPC_FLOOD_TEST_RESULT_LEN, + GFP_KERNEL); + if (!dfse->cache_buf) + return -ENOMEM; + } #endif debugfs_create_file(name, mode, sdev->debugfs_root, dfse, From 97f53046d746bef513d5fbaac53eedb011968407 Mon Sep 17 00:00:00 2001 From: Guennadi Liakhovetski Date: Mon, 15 Mar 2021 11:39:32 -0500 Subject: [PATCH 0238/1091] ASoC: SOF: remove superfluous NULL check in debugfs read MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When reading from IPC flood debugfs entries no need to check whether .cache_buf is NULL - it's impossible since otherwise the initialisation would have failed. This also fixes a klocwork reported issue: passed to function and may be dereferenced there by passing argument 2 to function 'memcpy' at line 510. sound/soc/sof/debug.c:510 | sof_dfsentry_read() Reported-by: Keqiao Zhang Reviewed-by: Ranjani Sridharan Reviewed-by: Xiuli Pan Signed-off-by: Guennadi Liakhovetski Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210315163932.18663-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/debug.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/sof/debug.c b/sound/soc/sof/debug.c index 778c7d028493..a51a928ea40a 100644 --- a/sound/soc/sof/debug.c +++ b/sound/soc/sof/debug.c @@ -451,8 +451,7 @@ static ssize_t sof_dfsentry_read(struct file *file, char __user *buffer, dentry = file->f_path.dentry; if ((!strcmp(dentry->d_name.name, "ipc_flood_count") || - !strcmp(dentry->d_name.name, "ipc_flood_duration_ms")) && - dfse->cache_buf) { + !strcmp(dentry->d_name.name, "ipc_flood_duration_ms"))) { if (*ppos) return 0; From 6ad864ed6ac50f11a6d8575fda79991cca8f245c Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Tue, 16 Mar 2021 17:42:16 +0800 Subject: [PATCH 0239/1091] ASoC: fsl_spdif: use snd_ctl_boolean_mono_info Remove redundant code and use snd_ctl_boolean_mono_info instead. Signed-off-by: Viorel Suman Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615887736-31217-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_spdif.c | 30 +++--------------------------- 1 file changed, 3 insertions(+), 27 deletions(-) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 174e558224d8..1cd3441d1c03 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -801,18 +801,6 @@ static int fsl_spdif_qget(struct snd_kcontrol *kcontrol, return ret; } -/* Valid bit information */ -static int fsl_spdif_vbit_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - - return 0; -} - /* Get valid good bit from interrupt status register */ static int fsl_spdif_rx_vbit_get(struct snd_kcontrol *kcontrol, struct snd_ctl_elem_value *ucontrol) @@ -925,18 +913,6 @@ static int fsl_spdif_rxrate_get(struct snd_kcontrol *kcontrol, return 0; } -/* User bit sync mode info */ -static int fsl_spdif_usync_info(struct snd_kcontrol *kcontrol, - struct snd_ctl_elem_info *uinfo) -{ - uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; - uinfo->count = 1; - uinfo->value.integer.min = 0; - uinfo->value.integer.max = 1; - - return 0; -} - /* * User bit sync mode: * 1 CD User channel subcode @@ -1018,7 +994,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = { .name = "IEC958 RX V-Bit Errors", .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = fsl_spdif_vbit_info, + .info = snd_ctl_boolean_mono_info, .get = fsl_spdif_rx_vbit_get, }, { @@ -1027,7 +1003,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = fsl_spdif_vbit_info, + .info = snd_ctl_boolean_mono_info, .get = fsl_spdif_tx_vbit_get, .put = fsl_spdif_tx_vbit_put, }, @@ -1047,7 +1023,7 @@ static struct snd_kcontrol_new fsl_spdif_ctrls[] = { .access = SNDRV_CTL_ELEM_ACCESS_READ | SNDRV_CTL_ELEM_ACCESS_WRITE | SNDRV_CTL_ELEM_ACCESS_VOLATILE, - .info = fsl_spdif_usync_info, + .info = snd_ctl_boolean_mono_info, .get = fsl_spdif_usync_get, .put = fsl_spdif_usync_put, }, From 1d49439c04792a4a3d8299a32b7673ab7ba13b77 Mon Sep 17 00:00:00 2001 From: Fabio Estevam Date: Mon, 15 Mar 2021 16:38:42 -0300 Subject: [PATCH 0240/1091] ASoC: mx27vis: Remove unused file i.MX has been converted to a devicetree-only platform and asoc-mx27vis.h is no longer used. Get rid of this unused file. Signed-off-by: Fabio Estevam Link: https://lore.kernel.org/r/20210315193842.183042-1-festevam@gmail.com Signed-off-by: Mark Brown --- include/linux/platform_data/asoc-mx27vis.h | 12 ------------ 1 file changed, 12 deletions(-) delete mode 100644 include/linux/platform_data/asoc-mx27vis.h diff --git a/include/linux/platform_data/asoc-mx27vis.h b/include/linux/platform_data/asoc-mx27vis.h deleted file mode 100644 index 2107d0d992dd..000000000000 --- a/include/linux/platform_data/asoc-mx27vis.h +++ /dev/null @@ -1,12 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -#ifndef __PLATFORM_DATA_ASOC_MX27VIS_H -#define __PLATFORM_DATA_ASOC_MX27VIS_H - -struct snd_mx27vis_platform_data { - int amp_gain0_gpio; - int amp_gain1_gpio; - int amp_mutel_gpio; - int amp_muter_gpio; -}; - -#endif /* __PLATFORM_DATA_ASOC_MX27VIS_H */ From 19c6a63ced5e07e40f3a5255cb1f0fe0d3be7b14 Mon Sep 17 00:00:00 2001 From: Mikhail Durnev Date: Tue, 16 Mar 2021 14:47:35 +1000 Subject: [PATCH 0241/1091] ASoC: rsnd: core: Check convert rate in rsnd_hw_params snd_pcm_hw_params_set_rate_near can return incorrect sample rate in some cases, e.g. when the backend output rate is set to some value higher than 48000 Hz and the input rate is 8000 Hz. So passing the value returned by snd_pcm_hw_params_set_rate_near to snd_pcm_hw_params will result in "FSO/FSI ratio error" and playing no audio at all while the userland is not properly notified about the issue. If SRC is unable to convert the requested sample rate to the sample rate the backend is using, then the requested sample rate should be adjusted in rsnd_hw_params. The userland will be notified about that change in the returned hw_params structure. Signed-off-by: Mikhail Durnev Link: https://lore.kernel.org/r/1615870055-13954-1-git-send-email-mikhail_durnev@mentor.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/core.c | 69 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 68 insertions(+), 1 deletion(-) diff --git a/sound/soc/sh/rcar/core.c b/sound/soc/sh/rcar/core.c index d1612d35f0ee..8696a993c478 100644 --- a/sound/soc/sh/rcar/core.c +++ b/sound/soc/sh/rcar/core.c @@ -1424,8 +1424,75 @@ static int rsnd_hw_params(struct snd_soc_component *component, } if (io->converted_chan) dev_dbg(dev, "convert channels = %d\n", io->converted_chan); - if (io->converted_rate) + if (io->converted_rate) { + /* + * SRC supports convert rates from params_rate(hw_params)/k_down + * to params_rate(hw_params)*k_up, where k_up is always 6, and + * k_down depends on number of channels and SRC unit. + * So all SRC units can upsample audio up to 6 times regardless + * its number of channels. And all SRC units can downsample + * 2 channel audio up to 6 times too. + */ + int k_up = 6; + int k_down = 6; + int channel; + struct rsnd_mod *src_mod = rsnd_io_to_mod_src(io); + dev_dbg(dev, "convert rate = %d\n", io->converted_rate); + + channel = io->converted_chan ? io->converted_chan : + params_channels(hw_params); + + switch (rsnd_mod_id(src_mod)) { + /* + * SRC0 can downsample 4, 6 and 8 channel audio up to 4 times. + * SRC1, SRC3 and SRC4 can downsample 4 channel audio + * up to 4 times. + * SRC1, SRC3 and SRC4 can downsample 6 and 8 channel audio + * no more than twice. + */ + case 1: + case 3: + case 4: + if (channel > 4) { + k_down = 2; + break; + } + fallthrough; + case 0: + if (channel > 2) + k_down = 4; + break; + + /* Other SRC units do not support more than 2 channels */ + default: + if (channel > 2) + return -EINVAL; + } + + if (params_rate(hw_params) > io->converted_rate * k_down) { + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = + io->converted_rate * k_down; + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = + io->converted_rate * k_down; + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; + } else if (params_rate(hw_params) * k_up < io->converted_rate) { + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->min = + (io->converted_rate + k_up - 1) / k_up; + hw_param_interval(hw_params, SNDRV_PCM_HW_PARAM_RATE)->max = + (io->converted_rate + k_up - 1) / k_up; + hw_params->cmask |= SNDRV_PCM_HW_PARAM_RATE; + } + + /* + * TBD: Max SRC input and output rates also depend on number + * of channels and SRC unit: + * SRC1, SRC3 and SRC4 do not support more than 128kHz + * for 6 channel and 96kHz for 8 channel audio. + * Perhaps this function should return EINVAL if the input or + * the output rate exceeds the limitation. + */ + } } return rsnd_dai_call(hw_params, io, substream, hw_params); From 2e2bf6d479616a15c54c4e668558f61caffa4db4 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Thu, 4 Mar 2021 17:08:01 +0800 Subject: [PATCH 0242/1091] ASoC: imx-hdmi: fix platform_no_drv_owner.cocci warnings ./sound/soc/fsl/imx-hdmi.c:226:3-8: No need to set .owner here. The core will do it. Remove .owner field if calls are used which set it automatically Reported-by: Abaci Robot Signed-off-by: Yang Li Reviewed-by: Fabio Estevam Link: https://lore.kernel.org/r/1614848881-29637-1-git-send-email-yang.lee@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/fsl/imx-hdmi.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/fsl/imx-hdmi.c b/sound/soc/fsl/imx-hdmi.c index 1ebcb9a2336b..34a0dceae621 100644 --- a/sound/soc/fsl/imx-hdmi.c +++ b/sound/soc/fsl/imx-hdmi.c @@ -219,7 +219,6 @@ MODULE_DEVICE_TABLE(of, imx_hdmi_dt_ids); static struct platform_driver imx_hdmi_driver = { .driver = { .name = "imx-hdmi", - .owner = THIS_MODULE, .pm = &snd_soc_pm_ops, .of_match_table = imx_hdmi_dt_ids, }, From 276559d8d02c2709281578976ca2f53bc62063d4 Mon Sep 17 00:00:00 2001 From: Ping Cheng Date: Thu, 11 Mar 2021 11:30:09 -0800 Subject: [PATCH 0243/1091] HID: wacom: set EV_KEY and EV_ABS only for non-HID_GENERIC type of devices Valid HID_GENERIC type of devices set EV_KEY and EV_ABS by wacom_map_usage. When *_input_capabilities are reached, those devices should already have their proper EV_* set. EV_KEY and EV_ABS only need to be set for non-HID_GENERIC type of devices in *_input_capabilities. Devices that don't support HID descitoprs will pass back to hid-input for registration without being accidentally rejected by the introduction of patch: "Input: refuse to register absolute devices without absinfo" Fixes: 6ecfe51b4082 ("Input: refuse to register absolute devices without absinfo") Signed-off-by: Ping Cheng Reviewed-by: Jason Gerecke Tested-by: Juan Garrido CC: stable@vger.kernel.org Signed-off-by: Jiri Kosina --- drivers/hid/wacom_wac.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/hid/wacom_wac.c b/drivers/hid/wacom_wac.c index bdd9ba577150..2d70dc4bea65 100644 --- a/drivers/hid/wacom_wac.c +++ b/drivers/hid/wacom_wac.c @@ -3574,8 +3574,6 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, { struct wacom_features *features = &wacom_wac->features; - input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - if (!(features->device_type & WACOM_DEVICETYPE_PEN)) return -ENODEV; @@ -3590,6 +3588,7 @@ int wacom_setup_pen_input_capabilities(struct input_dev *input_dev, return 0; } + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); __set_bit(BTN_TOUCH, input_dev->keybit); __set_bit(ABS_MISC, input_dev->absbit); @@ -3742,8 +3741,6 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, { struct wacom_features *features = &wacom_wac->features; - input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); - if (!(features->device_type & WACOM_DEVICETYPE_TOUCH)) return -ENODEV; @@ -3756,6 +3753,7 @@ int wacom_setup_touch_input_capabilities(struct input_dev *input_dev, /* setup has already been done */ return 0; + input_dev->evbit[0] |= BIT_MASK(EV_KEY) | BIT_MASK(EV_ABS); __set_bit(BTN_TOUCH, input_dev->keybit); if (features->touch_max == 1) { From c00f4f2598d334470b49385f811ca8f5c966a63e Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Wed, 17 Mar 2021 13:50:42 +0530 Subject: [PATCH 0244/1091] ASoC: ti: Fix a typo in the file ams-delta.c s/functonality/functionality/ Signed-off-by: Bhaskar Chowdhury Link: https://lore.kernel.org/r/20210317082042.3670745-1-unixbhaskar@gmail.com Signed-off-by: Mark Brown --- sound/soc/ti/ams-delta.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/ams-delta.c b/sound/soc/ti/ams-delta.c index 57feb473a579..31462587f922 100644 --- a/sound/soc/ti/ams-delta.c +++ b/sound/soc/ti/ams-delta.c @@ -408,7 +408,7 @@ static struct tty_ldisc_ops cx81801_ops = { /* * Even if not very useful, the sound card can still work without any of the - * above functonality activated. You can still control its audio input/output + * above functionality activated. You can still control its audio input/output * constellation and speakerphone gain from userspace by issuing AT commands * over the modem port. */ From 30916faa1a6009122e10d0c42338b8db44a36fde Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Sun, 14 Mar 2021 18:41:01 +0200 Subject: [PATCH 0245/1091] ARM: OMAP4: Fix PMIC voltage domains for bionic We are now registering the mpu domain three times instead of registering mpu, core and iva domains like we should. Fixes: d44fa156dcb2 ("ARM: OMAP2+: Configure voltage controller for cpcap") Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/pmic-cpcap.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-omap2/pmic-cpcap.c b/arch/arm/mach-omap2/pmic-cpcap.c index 09076ad0576d..668dc84fd31e 100644 --- a/arch/arm/mach-omap2/pmic-cpcap.c +++ b/arch/arm/mach-omap2/pmic-cpcap.c @@ -246,10 +246,10 @@ int __init omap4_cpcap_init(void) omap_voltage_register_pmic(voltdm, &omap443x_max8952_mpu); if (of_machine_is_compatible("motorola,droid-bionic")) { - voltdm = voltdm_lookup("mpu"); + voltdm = voltdm_lookup("core"); omap_voltage_register_pmic(voltdm, &omap_cpcap_core); - voltdm = voltdm_lookup("mpu"); + voltdm = voltdm_lookup("iva"); omap_voltage_register_pmic(voltdm, &omap_cpcap_iva); } else { voltdm = voltdm_lookup("core"); From b3d09a06d89f474cb52664e016849315a97e09d9 Mon Sep 17 00:00:00 2001 From: Carlos Leija Date: Sun, 14 Mar 2021 18:35:44 +0200 Subject: [PATCH 0246/1091] ARM: OMAP4: PM: update ROM return address for OSWR and OFF We need to add a dummy smc call to the cpuidle wakeup path to force the ROM code to save the return address after MMU is enabled again. This is needed to prevent random hangs on secure devices like droid4. Otherwise the system will eventually hang when entering deeper SoC idle states with the core and mpu domains in open-switch retention (OSWR). The hang happens as the ROM code tries to use the earlier physical return address set by omap-headsmp.S with MMU off while waking up CPU1 again. The hangs started happening in theory already with commit caf8c87d7ff2 ("ARM: OMAP2+: Allow core oswr for omap4"), but in practise the issue went unnoticed as various drivers were often blocking any deeper idle states with hardware autoidle features. This patch is based on an earlier TI Linux kernel tree commit 92f0b3028d9e ("OMAP4: PM: update ROM return address for OSWR and OFF") written by Carlos Leija , Praneeth Bajjuri , and Bryan Buckley . A later version of the patch was updated to use CPU_PM notifiers by Tero Kristo . Signed-off-by: Carlos Leija Signed-off-by: Praneeth Bajjuri Signed-off-by: Bryan Buckley Signed-off-by: Tero Kristo Fixes: caf8c87d7ff2 ("ARM: OMAP2+: Allow core oswr for omap4") Reported-by: Carl Philipp Klemm Reported-by: Merlijn Wajer Cc: Ivan Jelincic Cc: Pavel Machek Cc: Sebastian Reichel Cc: Tero Kristo [tony@atomide.com: updated to apply, updated description] Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/omap-secure.c | 39 +++++++++++++++++++++++++++++++ arch/arm/mach-omap2/omap-secure.h | 1 + 2 files changed, 40 insertions(+) diff --git a/arch/arm/mach-omap2/omap-secure.c b/arch/arm/mach-omap2/omap-secure.c index f70d561f37f7..0659ab4cb0af 100644 --- a/arch/arm/mach-omap2/omap-secure.c +++ b/arch/arm/mach-omap2/omap-secure.c @@ -9,6 +9,7 @@ */ #include +#include #include #include #include @@ -20,6 +21,7 @@ #include "common.h" #include "omap-secure.h" +#include "soc.h" static phys_addr_t omap_secure_memblock_base; @@ -213,3 +215,40 @@ void __init omap_secure_init(void) { omap_optee_init_check(); } + +/* + * Dummy dispatcher call after core OSWR and MPU off. Updates the ROM return + * address after MMU has been re-enabled after CPU1 has been woken up again. + * Otherwise the ROM code will attempt to use the earlier physical return + * address that got set with MMU off when waking up CPU1. Only used on secure + * devices. + */ +static int cpu_notifier(struct notifier_block *nb, unsigned long cmd, void *v) +{ + switch (cmd) { + case CPU_CLUSTER_PM_EXIT: + omap_secure_dispatcher(OMAP4_PPA_SERVICE_0, + FLAG_START_CRITICAL, + 0, 0, 0, 0, 0); + break; + default: + break; + } + + return NOTIFY_OK; +} + +static struct notifier_block secure_notifier_block = { + .notifier_call = cpu_notifier, +}; + +static int __init secure_pm_init(void) +{ + if (omap_type() == OMAP2_DEVICE_TYPE_GP || !soc_is_omap44xx()) + return 0; + + cpu_pm_register_notifier(&secure_notifier_block); + + return 0; +} +omap_arch_initcall(secure_pm_init); diff --git a/arch/arm/mach-omap2/omap-secure.h b/arch/arm/mach-omap2/omap-secure.h index 4aaa95706d39..172069f31616 100644 --- a/arch/arm/mach-omap2/omap-secure.h +++ b/arch/arm/mach-omap2/omap-secure.h @@ -50,6 +50,7 @@ #define OMAP5_DRA7_MON_SET_ACR_INDEX 0x107 /* Secure PPA(Primary Protected Application) APIs */ +#define OMAP4_PPA_SERVICE_0 0x21 #define OMAP4_PPA_L2_POR_INDEX 0x23 #define OMAP4_PPA_CPU_ACTRL_SMP_INDEX 0x25 From 9afeefcf06fc7b4bdab06a6e2cb06745bded34dd Mon Sep 17 00:00:00 2001 From: Suman Anna Date: Mon, 15 Mar 2021 15:58:59 -0500 Subject: [PATCH 0247/1091] remoteproc: pru: Fix firmware loading crashes on K3 SoCs The K3 PRUs are 32-bit processors and in general have some limitations in using the standard ARMv8 memcpy function for loading firmware segments, so the driver already uses a custom memcpy implementation. This added logic however is limited to only IRAMs at the moment, but the loading into Data RAMs is not completely ok either and does generate a kernel crash for unaligned accesses. Fix these crashes by removing the existing IRAM logic limitation and extending the custom memcpy usage to Data RAMs as well for all K3 SoCs. Fixes: 1d39f4d19921 ("remoteproc: pru: Add support for various PRU cores on K3 AM65x SoCs") Signed-off-by: Suman Anna Link: https://lore.kernel.org/r/20210315205859.19590-1-s-anna@ti.com Signed-off-by: Bjorn Andersson --- drivers/remoteproc/pru_rproc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/remoteproc/pru_rproc.c b/drivers/remoteproc/pru_rproc.c index 5fad787ba012..dcb380e868df 100644 --- a/drivers/remoteproc/pru_rproc.c +++ b/drivers/remoteproc/pru_rproc.c @@ -603,7 +603,7 @@ pru_rproc_load_elf_segments(struct rproc *rproc, const struct firmware *fw) break; } - if (pru->data->is_k3 && is_iram) { + if (pru->data->is_k3) { ret = pru_rproc_memcpy(ptr, elf_data + phdr->p_offset, filesz); if (ret) { From e409a6a3e0690efdef9b8a96197bc61ff117cfaf Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 15 Mar 2021 12:50:08 +0100 Subject: [PATCH 0248/1091] i2c: turn recovery error on init to debug In some configurations, recovery is optional. So, don't throw an error when it is not used because e.g. pinctrl settings for recovery are not provided. Reword the message and make it debug output. Reported-by: Klaus Kudielka Tested-by: Klaus Kudielka Signed-off-by: Wolfram Sang Signed-off-by: Wolfram Sang Cc: stable@kernel.org --- drivers/i2c/i2c-core-base.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/i2c-core-base.c b/drivers/i2c/i2c-core-base.c index 63ebf722a424..f21362355973 100644 --- a/drivers/i2c/i2c-core-base.c +++ b/drivers/i2c/i2c-core-base.c @@ -378,7 +378,7 @@ static int i2c_gpio_init_recovery(struct i2c_adapter *adap) static int i2c_init_recovery(struct i2c_adapter *adap) { struct i2c_bus_recovery_info *bri = adap->bus_recovery_info; - char *err_str; + char *err_str, *err_level = KERN_ERR; if (!bri) return 0; @@ -387,7 +387,8 @@ static int i2c_init_recovery(struct i2c_adapter *adap) return -EPROBE_DEFER; if (!bri->recover_bus) { - err_str = "no recover_bus() found"; + err_str = "no suitable method provided"; + err_level = KERN_DEBUG; goto err; } @@ -414,7 +415,7 @@ static int i2c_init_recovery(struct i2c_adapter *adap) return 0; err: - dev_err(&adap->dev, "Not using recovery: %s\n", err_str); + dev_printk(err_level, &adap->dev, "Not using recovery: %s\n", err_str); adap->bus_recovery_info = NULL; return -EINVAL; From 4e0b9ea85e6fb7654a3d28c23bbde736ce1592ae Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:17:55 +0100 Subject: [PATCH 0249/1091] mfd: arizona: Drop arizona-extcon cells The arizona jack-dection handling is being reworked so that the codec-child-device drivers directly handle jack-detect themselves, so it is no longer necessary to instantiate "arizona-extcon" child-devices. Signed-off-by: Hans de Goede Acked-by: Charles Keepax Tested-by: Charles Keepax Signed-off-by: Lee Jones --- drivers/mfd/arizona-core.c | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/drivers/mfd/arizona-core.c b/drivers/mfd/arizona-core.c index 75f1bc671d59..ce6fe6de34f8 100644 --- a/drivers/mfd/arizona-core.c +++ b/drivers/mfd/arizona-core.c @@ -881,11 +881,6 @@ static const char * const wm5102_supplies[] = { static const struct mfd_cell wm5102_devs[] = { { .name = "arizona-micsupp" }, { .name = "arizona-gpio" }, - { - .name = "arizona-extcon", - .parent_supplies = wm5102_supplies, - .num_parent_supplies = 1, /* We only need MICVDD */ - }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { @@ -898,11 +893,6 @@ static const struct mfd_cell wm5102_devs[] = { static const struct mfd_cell wm5110_devs[] = { { .name = "arizona-micsupp" }, { .name = "arizona-gpio" }, - { - .name = "arizona-extcon", - .parent_supplies = wm5102_supplies, - .num_parent_supplies = 1, /* We only need MICVDD */ - }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { @@ -939,11 +929,6 @@ static const char * const wm8997_supplies[] = { static const struct mfd_cell wm8997_devs[] = { { .name = "arizona-micsupp" }, { .name = "arizona-gpio" }, - { - .name = "arizona-extcon", - .parent_supplies = wm8997_supplies, - .num_parent_supplies = 1, /* We only need MICVDD */ - }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { @@ -956,11 +941,6 @@ static const struct mfd_cell wm8997_devs[] = { static const struct mfd_cell wm8998_devs[] = { { .name = "arizona-micsupp" }, { .name = "arizona-gpio" }, - { - .name = "arizona-extcon", - .parent_supplies = wm5102_supplies, - .num_parent_supplies = 1, /* We only need MICVDD */ - }, { .name = "arizona-haptics" }, { .name = "arizona-pwm" }, { From c309a3e8793f7e01c4a4ec7960658380572cb576 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:17:56 +0100 Subject: [PATCH 0250/1091] extcon: arizona: Fix some issues when HPDET IRQ fires after the jack has been unplugged When the jack is partially inserted and then removed again it may be removed while the hpdet code is running. In this case the following may happen: 1. The "JACKDET rise" or ""JACKDET fall" IRQ triggers 2. arizona_jackdet runs and takes info->lock 3. The "HPDET" IRQ triggers 4. arizona_hpdet_irq runs, blocks on info->lock 5. arizona_jackdet calls arizona_stop_mic() and clears info->hpdet_done 6. arizona_jackdet releases info->lock 7. arizona_hpdet_irq now can continue running and: 7.1 Calls arizona_start_mic() (if a mic was detected) 7.2 sets info->hpdet_done Step 7 is undesirable / a bug: 7.1 causes the device to stay in a high power-state (with MICVDD enabled) 7.2 causes hpdet to not run on the next jack insertion, which in turn causes the EXTCON_JACK_HEADPHONE state to never get set This fixes both issues by skipping these 2 steps when arizona_hpdet_irq runs after the jack has been unplugged. Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Acked-by: Chanwoo Choi Signed-off-by: Lee Jones --- drivers/extcon/extcon-arizona.c | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index aae82db542a5..f7ef247de46a 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -601,7 +601,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) struct arizona *arizona = info->arizona; int id_gpio = arizona->pdata.hpdet_id_gpio; unsigned int report = EXTCON_JACK_HEADPHONE; - int ret, reading; + int ret, reading, state; bool mic = false; mutex_lock(&info->lock); @@ -614,12 +614,11 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) } /* If the cable was removed while measuring ignore the result */ - ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); - if (ret < 0) { - dev_err(arizona->dev, "Failed to check cable state: %d\n", - ret); + state = extcon_get_state(info->edev, EXTCON_MECHANICAL); + if (state < 0) { + dev_err(arizona->dev, "Failed to check cable state: %d\n", state); goto out; - } else if (!ret) { + } else if (!state) { dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n"); goto done; } @@ -667,7 +666,7 @@ done: gpio_set_value_cansleep(id_gpio, 0); /* If we have a mic then reenable MICDET */ - if (mic || info->mic) + if (state && (mic || info->mic)) arizona_start_mic(info); if (info->hpdet_active) { @@ -675,7 +674,9 @@ done: info->hpdet_active = false; } - info->hpdet_done = true; + /* Do not set hp_det done when the cable has been unplugged */ + if (state) + info->hpdet_done = true; out: mutex_unlock(&info->lock); From e5b499f6fb17bc95a813e85d0796522280203806 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:17:57 +0100 Subject: [PATCH 0251/1091] extcon: arizona: Fix various races on driver unbind We must free/disable all interrupts and cancel all pending works before doing further cleanup. Before this commit arizona_extcon_remove() was doing several register writes to shut things down before disabling the IRQs and it was cancelling only 1 of the 3 different works used. Move all the register-writes shutting things down to after the disabling of the IRQs and add the 2 missing cancel_delayed_work_sync() calls. This fixes various possible races on driver unbind. One of which would always trigger on devices using the mic-clamp feature for jack detection. The ARIZONA_MICD_CLAMP_MODE_MASK update was done before disabling the IRQs, causing: 1. arizona_jackdet() to run 2. detect a jack being inserted (clamp disabled means jack inserted) 3. call arizona_start_mic() which: 3.1 Enables the MICVDD regulator 3.2 takes a pm_runtime_reference And this was all happening after the ARIZONA_MICD_ENA bit clearing, which would undo 3.1 and 3.2 because the ARIZONA_MICD_CLAMP_MODE_MASK update was being done after the ARIZONA_MICD_ENA bit clearing. So this means that arizona_extcon_remove() would exit with 1. MICVDD enabled and 2. The pm_runtime_reference being unbalanced. MICVDD still being enabled caused the following oops when the regulator is released by the devm framework: [ 2850.745757] ------------[ cut here ]------------ [ 2850.745827] WARNING: CPU: 2 PID: 2098 at drivers/regulator/core.c:2123 _regulator_put.part.0+0x19f/0x1b0 [ 2850.745835] Modules linked in: extcon_arizona ... ... [ 2850.746909] Call Trace: [ 2850.746932] regulator_put+0x2d/0x40 [ 2850.746946] release_nodes+0x22a/0x260 [ 2850.746984] __device_release_driver+0x190/0x240 [ 2850.747002] driver_detach+0xd4/0x120 ... [ 2850.747337] ---[ end trace f455dfd7abd9781f ]--- Note this oops is just one of various theoretically possible races caused by the wrong ordering inside arizona_extcon_remove(), this fixes the ordering fixing all possible races, including the reported oops. Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Acked-by: Chanwoo Choi Signed-off-by: Lee Jones --- drivers/extcon/extcon-arizona.c | 40 +++++++++++++++++---------------- 1 file changed, 21 insertions(+), 19 deletions(-) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index f7ef247de46a..76aacbac5869 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -1760,25 +1760,6 @@ static int arizona_extcon_remove(struct platform_device *pdev) bool change; int ret; - ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, - ARIZONA_MICD_ENA, 0, - &change); - if (ret < 0) { - dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", - ret); - } else if (change) { - regulator_disable(info->micvdd); - pm_runtime_put(info->dev); - } - - gpiod_put(info->micd_pol_gpio); - - pm_runtime_disable(&pdev->dev); - - regmap_update_bits(arizona->regmap, - ARIZONA_MICD_CLAMP_CONTROL, - ARIZONA_MICD_CLAMP_MODE_MASK, 0); - if (info->micd_clamp) { jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; @@ -1794,10 +1775,31 @@ static int arizona_extcon_remove(struct platform_device *pdev) arizona_free_irq(arizona, jack_irq_rise, info); arizona_free_irq(arizona, jack_irq_fall, info); cancel_delayed_work_sync(&info->hpdet_work); + cancel_delayed_work_sync(&info->micd_detect_work); + cancel_delayed_work_sync(&info->micd_timeout_work); + + ret = regmap_update_bits_check(arizona->regmap, ARIZONA_MIC_DETECT_1, + ARIZONA_MICD_ENA, 0, + &change); + if (ret < 0) { + dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", + ret); + } else if (change) { + regulator_disable(info->micvdd); + pm_runtime_put(info->dev); + } + + regmap_update_bits(arizona->regmap, + ARIZONA_MICD_CLAMP_CONTROL, + ARIZONA_MICD_CLAMP_MODE_MASK, 0); regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, ARIZONA_JD1_ENA, 0); arizona_clk32k_disable(arizona); + gpiod_put(info->micd_pol_gpio); + + pm_runtime_disable(&pdev->dev); + return 0; } From ece2619fe8edc703b872136057090627e8a19ab4 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:17:58 +0100 Subject: [PATCH 0252/1091] extcon: arizona: Fix flags parameter to the gpiod_get("wlf,micd-pol") call The initial value of the GPIO should match the info->micd_modes[0].gpio value. arizona_extcon_probe() already stores the necessary flag in a mode variable, but instead of passing mode as flags to the gpiod_get() it was using a hardcoded GPIOD_OUT_LOW. Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Acked-by: Chanwoo Choi Signed-off-by: Lee Jones --- drivers/extcon/extcon-arizona.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 76aacbac5869..72d23b15108c 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -1510,7 +1510,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) */ info->micd_pol_gpio = gpiod_get_optional(arizona->dev, "wlf,micd-pol", - GPIOD_OUT_LOW); + mode); if (IS_ERR(info->micd_pol_gpio)) { ret = PTR_ERR(info->micd_pol_gpio); dev_err(arizona->dev, From 505eb8df97d9a6c51f5168f69984d116e9c27470 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:17:59 +0100 Subject: [PATCH 0253/1091] extcon: arizona: Always use pm_runtime_get_sync() when we need the device to be awake Before this commit the extcon-arizona code was mixing pm_runtime_get() and pm_runtime_get_sync() in different places. In all places where pm_runtime_get[_sync]() is called, the code makes use of the device immediately after the call. This means that we should always use pm_runtime_get_sync(). Signed-off-by: Hans de Goede Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Acked-by: Chanwoo Choi Signed-off-by: Lee Jones --- drivers/extcon/extcon-arizona.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/extcon/extcon-arizona.c b/drivers/extcon/extcon-arizona.c index 72d23b15108c..56d2ce05de50 100644 --- a/drivers/extcon/extcon-arizona.c +++ b/drivers/extcon/extcon-arizona.c @@ -290,7 +290,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info) unsigned int mode; /* Microphone detection can't use idle mode */ - pm_runtime_get(info->dev); + pm_runtime_get_sync(info->dev); if (info->detecting) { ret = regulator_allow_bypass(info->micvdd, false); @@ -695,7 +695,7 @@ static void arizona_identify_headphone(struct arizona_extcon_info *info) dev_dbg(arizona->dev, "Starting HPDET\n"); /* Make sure we keep the device enabled during the measurement */ - pm_runtime_get(info->dev); + pm_runtime_get_sync(info->dev); info->hpdet_active = true; From a908a716696eee75bf85199cde2b0989290536d1 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:00 +0100 Subject: [PATCH 0254/1091] ASoC/extcon: arizona: Move arizona jack code to sound/soc/codecs/arizona-jack.c The jack handling for arizona codecs is being refactored so that it is done directly by the codec drivers, instead of having an extcon-driver bind to a separate "arizona-extcon" child-device for this. drivers/mfd/arizona-core.c has already been updated to no longer instantiate an "arizona-extcon" child-device for the arizona codecs. This means that the "arizona-extcon" driver is no longer useful (there are no longer any devices for it to bind to). This commit drops the extcon Kconfig / Makefile bits and moves drivers/extcon/extcon-arizona.c to sound/soc/codecs/arizona-jack.c . This is a preparation patch for converting the arizona extcon-driver into a helper library for letting the arizona codec-drivers directly report jack state through the standard sound/soc/soc-jack.c functions. Signed-off-by: Hans de Goede Acked-by: Charles Keepax Tested-by: Charles Keepax Acked-by: Chanwoo Choi Signed-off-by: Lee Jones --- MAINTAINERS | 3 +-- drivers/extcon/Kconfig | 8 -------- drivers/extcon/Makefile | 1 - .../extcon-arizona.c => sound/soc/codecs/arizona-jack.c | 0 4 files changed, 1 insertion(+), 11 deletions(-) rename drivers/extcon/extcon-arizona.c => sound/soc/codecs/arizona-jack.c (100%) diff --git a/MAINTAINERS b/MAINTAINERS index d92f85ca831d..dd40d5e551b0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -19378,7 +19378,6 @@ F: Documentation/devicetree/bindings/sound/wlf,arizona.yaml F: Documentation/hwmon/wm83??.rst F: arch/arm/mach-s3c/mach-crag6410* F: drivers/clk/clk-wm83*.c -F: drivers/extcon/extcon-arizona.c F: drivers/gpio/gpio-*wm*.c F: drivers/gpio/gpio-arizona.c F: drivers/hwmon/wm83??-hwmon.c @@ -19402,7 +19401,7 @@ F: include/linux/mfd/wm8400* F: include/linux/regulator/arizona* F: include/linux/wm97xx.h F: include/sound/wm????.h -F: sound/soc/codecs/arizona.? +F: sound/soc/codecs/arizona* F: sound/soc/codecs/cs47l24* F: sound/soc/codecs/wm* diff --git a/drivers/extcon/Kconfig b/drivers/extcon/Kconfig index af58ebca2bf6..e3db936becfd 100644 --- a/drivers/extcon/Kconfig +++ b/drivers/extcon/Kconfig @@ -21,14 +21,6 @@ config EXTCON_ADC_JACK help Say Y here to enable extcon device driver based on ADC values. -config EXTCON_ARIZONA - tristate "Wolfson Arizona EXTCON support" - depends on MFD_ARIZONA && INPUT && SND_SOC - help - Say Y here to enable support for external accessory detection - with Wolfson Arizona devices. These are audio CODECs with - advanced audio accessory detection support. - config EXTCON_AXP288 tristate "X-Power AXP288 EXTCON support" depends on MFD_AXP20X && USB_SUPPORT && X86 && ACPI diff --git a/drivers/extcon/Makefile b/drivers/extcon/Makefile index fe10a1b7d18b..1b390d934ca9 100644 --- a/drivers/extcon/Makefile +++ b/drivers/extcon/Makefile @@ -6,7 +6,6 @@ obj-$(CONFIG_EXTCON) += extcon-core.o extcon-core-objs += extcon.o devres.o obj-$(CONFIG_EXTCON_ADC_JACK) += extcon-adc-jack.o -obj-$(CONFIG_EXTCON_ARIZONA) += extcon-arizona.o obj-$(CONFIG_EXTCON_AXP288) += extcon-axp288.o obj-$(CONFIG_EXTCON_FSA9480) += extcon-fsa9480.o obj-$(CONFIG_EXTCON_GPIO) += extcon-gpio.o diff --git a/drivers/extcon/extcon-arizona.c b/sound/soc/codecs/arizona-jack.c similarity index 100% rename from drivers/extcon/extcon-arizona.c rename to sound/soc/codecs/arizona-jack.c From a46b78247b852345ae4458711a4aec6744a7838c Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:43 +0300 Subject: [PATCH 0255/1091] ASoC: tegra20: ac97: Add reset control Tegra20 AC97 driver doesn't manage the AC97 controller reset, relying on implicit deassertion of the reset by tegra-clk driver, which needs to be fixed since this behaviour is unacceptable by other Tegra drivers. Add explicit reset control to the Tegra20 AC97 driver. Note that AC97 reset was always specified in Tegra20 device-tree, hence DTB ABI changes aren't required. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-2-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_ac97.c | 21 +++++++++++++++++++++ sound/soc/tegra/tegra20_ac97.h | 1 + 2 files changed, 22 insertions(+) diff --git a/sound/soc/tegra/tegra20_ac97.c b/sound/soc/tegra/tegra20_ac97.c index 06c728ae17ed..c454a34c15c4 100644 --- a/sound/soc/tegra/tegra20_ac97.c +++ b/sound/soc/tegra/tegra20_ac97.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -313,6 +314,12 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, ac97); + ac97->reset = devm_reset_control_get_exclusive(&pdev->dev, "ac97"); + if (IS_ERR(ac97->reset)) { + dev_err(&pdev->dev, "Can't retrieve ac97 reset\n"); + return PTR_ERR(ac97->reset); + } + ac97->clk_ac97 = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(ac97->clk_ac97)) { dev_err(&pdev->dev, "Can't retrieve ac97 clock\n"); @@ -364,12 +371,26 @@ static int tegra20_ac97_platform_probe(struct platform_device *pdev) ac97->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; ac97->playback_dma_data.maxburst = 4; + ret = reset_control_assert(ac97->reset); + if (ret) { + dev_err(&pdev->dev, "Failed to assert AC'97 reset: %d\n", ret); + goto err_clk_put; + } + ret = clk_prepare_enable(ac97->clk_ac97); if (ret) { dev_err(&pdev->dev, "clk_enable failed: %d\n", ret); goto err_clk_put; } + usleep_range(10, 100); + + ret = reset_control_deassert(ac97->reset); + if (ret) { + dev_err(&pdev->dev, "Failed to deassert AC'97 reset: %d\n", ret); + goto err_clk_disable_unprepare; + } + ret = snd_soc_set_ac97_ops(&tegra20_ac97_ops); if (ret) { dev_err(&pdev->dev, "Failed to set AC'97 ops: %d\n", ret); diff --git a/sound/soc/tegra/tegra20_ac97.h b/sound/soc/tegra/tegra20_ac97.h index e467cd1ff2ca..870ea09ff301 100644 --- a/sound/soc/tegra/tegra20_ac97.h +++ b/sound/soc/tegra/tegra20_ac97.h @@ -78,6 +78,7 @@ struct tegra20_ac97 { struct clk *clk_ac97; struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; + struct reset_control *reset; struct regmap *regmap; int reset_gpio; int sync_gpio; From 9c648ef82d7d4696e80b286d37dae07b67a9a32d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:44 +0300 Subject: [PATCH 0256/1091] ASoC: tegra20: i2s: Add reset control The I2S reset may be asserted at a boot time, in particular this is the case on Tegra20 AC100 netbook. Tegra20 I2S driver doesn't manage the reset control and currently it happens to work because reset is implicitly deasserted by the tegra-clk driver when I2S clock is enabled. The I2S permanently stays in a reset once tegra-clk is fixed to not touch the resets, which it shouldn't be doing. Add reset control to the Tegra20 I2S driver. Note that I2S reset was always specified in Tegra20 device-tree, hence DTB ABI changes aren't required. Tested-by: Paul Fertser # T20 AC100 Reported-by: Paul Fertser Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-3-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 31 +++++++++++++++++++++++++++++++ sound/soc/tegra/tegra20_i2s.h | 1 + 2 files changed, 32 insertions(+) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index d7a3d046c8f8..c0af5352b483 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include #include @@ -37,6 +38,8 @@ static int tegra20_i2s_runtime_suspend(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev); + regcache_cache_only(i2s->regmap, true); + clk_disable_unprepare(i2s->clk_i2s); return 0; @@ -47,13 +50,35 @@ static int tegra20_i2s_runtime_resume(struct device *dev) struct tegra20_i2s *i2s = dev_get_drvdata(dev); int ret; + ret = reset_control_assert(i2s->reset); + if (ret) + return ret; + ret = clk_prepare_enable(i2s->clk_i2s); if (ret) { dev_err(dev, "clk_enable failed: %d\n", ret); return ret; } + usleep_range(10, 100); + + ret = reset_control_deassert(i2s->reset); + if (ret) + goto disable_clocks; + + regcache_cache_only(i2s->regmap, false); + regcache_mark_dirty(i2s->regmap); + + ret = regcache_sync(i2s->regmap); + if (ret) + goto disable_clocks; + return 0; + +disable_clocks: + clk_disable_unprepare(i2s->clk_i2s); + + return ret; } static int tegra20_i2s_set_fmt(struct snd_soc_dai *dai, @@ -339,6 +364,12 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) i2s->dai = tegra20_i2s_dai_template; i2s->dai.name = dev_name(&pdev->dev); + i2s->reset = devm_reset_control_get_exclusive(&pdev->dev, "i2s"); + if (IS_ERR(i2s->reset)) { + dev_err(&pdev->dev, "Can't retrieve i2s reset\n"); + return PTR_ERR(i2s->reset); + } + i2s->clk_i2s = clk_get(&pdev->dev, NULL); if (IS_ERR(i2s->clk_i2s)) { dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); diff --git a/sound/soc/tegra/tegra20_i2s.h b/sound/soc/tegra/tegra20_i2s.h index 628d3ca09f42..8233e5fa2eff 100644 --- a/sound/soc/tegra/tegra20_i2s.h +++ b/sound/soc/tegra/tegra20_i2s.h @@ -144,6 +144,7 @@ struct tegra20_i2s { struct snd_dmaengine_dai_dma_data capture_dma_data; struct snd_dmaengine_dai_dma_data playback_dma_data; struct regmap *regmap; + struct reset_control *reset; }; #endif From 0bbcecaaab15a74ba69f93df46c753f2a64eadca Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:45 +0300 Subject: [PATCH 0257/1091] ASoC: tegra30: i2s: Restore hardware state on runtime PM resume Tegra30 I2S driver syncs regmap cache only on resume from system suspend, but hardware is reset across the runtime suspend because RPM of the parent AHUB driver resets the I2S hardware, hence h/w state is lost after each RPM resume. The problem isn't visible because hardware happens to be fully reprogrammed after each RPM resume. Move hardware syncing to RPM resume in order to restore h/w state properly. Fixes: ed9ce1ed2239 ("ASoC: tegra: ahub: Reset hardware properly") Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-4-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_i2s.c | 40 +++++++++++------------------------ 1 file changed, 12 insertions(+), 28 deletions(-) diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 6740df541508..3d22c1be6f3d 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -58,8 +58,18 @@ static int tegra30_i2s_runtime_resume(struct device *dev) } regcache_cache_only(i2s->regmap, false); + regcache_mark_dirty(i2s->regmap); + + ret = regcache_sync(i2s->regmap); + if (ret) + goto disable_clocks; return 0; + +disable_clocks: + clk_disable_unprepare(i2s->clk_i2s); + + return ret; } static int tegra30_i2s_set_fmt(struct snd_soc_dai *dai, @@ -551,37 +561,11 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int tegra30_i2s_suspend(struct device *dev) -{ - struct tegra30_i2s *i2s = dev_get_drvdata(dev); - - regcache_mark_dirty(i2s->regmap); - - return 0; -} - -static int tegra30_i2s_resume(struct device *dev) -{ - struct tegra30_i2s *i2s = dev_get_drvdata(dev); - int ret; - - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put(dev); - return ret; - } - ret = regcache_sync(i2s->regmap); - pm_runtime_put(dev); - - return ret; -} -#endif - static const struct dev_pm_ops tegra30_i2s_pm_ops = { SET_RUNTIME_PM_OPS(tegra30_i2s_runtime_suspend, tegra30_i2s_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(tegra30_i2s_suspend, tegra30_i2s_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver tegra30_i2s_driver = { From 48d71395896d54eec989179dd265e569fcecb15a Mon Sep 17 00:00:00 2001 From: Philipp Zabel Date: Sun, 14 Mar 2021 18:44:46 +0300 Subject: [PATCH 0258/1091] reset: Add reset_control_bulk API Follow the clock and regulator subsystems' lead and add a bulk API for reset controls. Signed-off-by: Philipp Zabel Tested-by: Dmitry Osipenko Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-5-digetx@gmail.com Signed-off-by: Mark Brown --- drivers/reset/core.c | 215 ++++++++++++++++++++++++++++ include/linux/reset.h | 315 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 530 insertions(+) diff --git a/drivers/reset/core.c b/drivers/reset/core.c index dbf881b586d9..71c1c8264b2d 100644 --- a/drivers/reset/core.c +++ b/drivers/reset/core.c @@ -358,6 +358,30 @@ int reset_control_reset(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_reset); +/** + * reset_control_bulk_reset - reset the controlled devices in order + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Issue a reset on all provided reset controls, in order. + * + * See also: reset_control_reset() + */ +int reset_control_bulk_reset(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + ret = reset_control_reset(rstcs[i].rstc); + if (ret) + return ret; + } + + return 0; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_reset); + /** * reset_control_rearm - allow shared reset line to be re-triggered" * @rstc: reset controller @@ -461,6 +485,36 @@ int reset_control_assert(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_assert); +/** + * reset_control_bulk_assert - asserts the reset lines in order + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Assert the reset lines for all provided reset controls, in order. + * If an assertion fails, already asserted resets are deasserted again. + * + * See also: reset_control_assert() + */ +int reset_control_bulk_assert(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + ret = reset_control_assert(rstcs[i].rstc); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + reset_control_deassert(rstcs[i].rstc); + return ret; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_assert); + /** * reset_control_deassert - deasserts the reset line * @rstc: reset controller @@ -511,6 +565,36 @@ int reset_control_deassert(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_deassert); +/** + * reset_control_bulk_deassert - deasserts the reset lines in reverse order + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Deassert the reset lines for all provided reset controls, in reverse order. + * If a deassertion fails, already deasserted resets are asserted again. + * + * See also: reset_control_deassert() + */ +int reset_control_bulk_deassert(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = num_rstcs - 1; i >= 0; i--) { + ret = reset_control_deassert(rstcs[i].rstc); + if (ret) + goto err; + } + + return 0; + +err: + while (i < num_rstcs) + reset_control_assert(rstcs[i++].rstc); + return ret; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_deassert); + /** * reset_control_status - returns a negative errno if not supported, a * positive value if the reset line is asserted, or zero if the reset @@ -588,6 +672,36 @@ int reset_control_acquire(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_acquire); +/** + * reset_control_bulk_acquire - acquires reset controls for exclusive use + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * This is used to explicitly acquire reset controls requested with + * reset_control_bulk_get_exclusive_release() for temporary exclusive use. + * + * See also: reset_control_acquire(), reset_control_bulk_release() + */ +int reset_control_bulk_acquire(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + ret = reset_control_acquire(rstcs[i].rstc); + if (ret) + goto err; + } + + return 0; + +err: + while (i--) + reset_control_release(rstcs[i].rstc); + return ret; +} +EXPORT_SYMBOL_GPL(reset_control_bulk_acquire); + /** * reset_control_release() - releases exclusive access to a reset control * @rstc: reset control @@ -610,6 +724,26 @@ void reset_control_release(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_release); +/** + * reset_control_bulk_release() - releases exclusive access to reset controls + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + * + * Releases exclusive access right to reset controls previously obtained by a + * call to reset_control_bulk_acquire(). + * + * See also: reset_control_release(), reset_control_bulk_acquire() + */ +void reset_control_bulk_release(int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + int i; + + for (i = 0; i < num_rstcs; i++) + reset_control_release(rstcs[i].rstc); +} +EXPORT_SYMBOL_GPL(reset_control_bulk_release); + static struct reset_control *__reset_control_get_internal( struct reset_controller_dev *rcdev, unsigned int index, bool shared, bool acquired) @@ -814,6 +948,32 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, } EXPORT_SYMBOL_GPL(__reset_control_get); +int __reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + int ret, i; + + for (i = 0; i < num_rstcs; i++) { + rstcs[i].rstc = __reset_control_get(dev, rstcs[i].id, 0, + shared, optional, acquired); + if (IS_ERR(rstcs[i].rstc)) { + ret = PTR_ERR(rstcs[i].rstc); + goto err; + } + } + + return 0; + +err: + mutex_lock(&reset_list_mutex); + while (i--) + __reset_control_put_internal(rstcs[i].rstc); + mutex_unlock(&reset_list_mutex); + return ret; +} +EXPORT_SYMBOL_GPL(__reset_control_bulk_get); + static void reset_control_array_put(struct reset_control_array *resets) { int i; @@ -845,6 +1005,23 @@ void reset_control_put(struct reset_control *rstc) } EXPORT_SYMBOL_GPL(reset_control_put); +/** + * reset_control_bulk_put - free the reset controllers + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset controls set + */ +void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ + mutex_lock(&reset_list_mutex); + while (num_rstcs--) { + if (IS_ERR_OR_NULL(rstcs[num_rstcs].rstc)) + continue; + __reset_control_put_internal(rstcs[num_rstcs].rstc); + } + mutex_unlock(&reset_list_mutex); +} +EXPORT_SYMBOL_GPL(reset_control_bulk_put); + static void devm_reset_control_release(struct device *dev, void *res) { reset_control_put(*(struct reset_control **)res); @@ -874,6 +1051,44 @@ struct reset_control *__devm_reset_control_get(struct device *dev, } EXPORT_SYMBOL_GPL(__devm_reset_control_get); +struct reset_control_bulk_devres { + int num_rstcs; + struct reset_control_bulk_data *rstcs; +}; + +static void devm_reset_control_bulk_release(struct device *dev, void *res) +{ + struct reset_control_bulk_devres *devres = res; + + reset_control_bulk_put(devres->num_rstcs, devres->rstcs); +} + +int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + struct reset_control_bulk_devres *ptr; + int ret; + + ptr = devres_alloc(devm_reset_control_bulk_release, sizeof(*ptr), + GFP_KERNEL); + if (!ptr) + return -ENOMEM; + + ret = __reset_control_bulk_get(dev, num_rstcs, rstcs, shared, optional, acquired); + if (ret < 0) { + devres_free(ptr); + return ret; + } + + ptr->num_rstcs = num_rstcs; + ptr->rstcs = rstcs; + devres_add(dev, ptr); + + return 0; +} +EXPORT_SYMBOL_GPL(__devm_reset_control_bulk_get); + /** * __device_reset - find reset controller associated with the device * and perform reset diff --git a/include/linux/reset.h b/include/linux/reset.h index b9109efa2a5c..46e6372cb431 100644 --- a/include/linux/reset.h +++ b/include/linux/reset.h @@ -10,6 +10,21 @@ struct device; struct device_node; struct reset_control; +/** + * struct reset_control_bulk_data - Data used for bulk reset control operations. + * + * @id: reset control consumer ID + * @rstc: struct reset_control * to store the associated reset control + * + * The reset APIs provide a series of reset_control_bulk_*() API calls as + * a convenience to consumers which require multiple reset controls. + * This structure is used to manage data for these calls. + */ +struct reset_control_bulk_data { + const char *id; + struct reset_control *rstc; +}; + #ifdef CONFIG_RESET_CONTROLLER int reset_control_reset(struct reset_control *rstc); @@ -20,6 +35,12 @@ int reset_control_status(struct reset_control *rstc); int reset_control_acquire(struct reset_control *rstc); void reset_control_release(struct reset_control *rstc); +int reset_control_bulk_reset(int num_rstcs, struct reset_control_bulk_data *rstcs); +int reset_control_bulk_assert(int num_rstcs, struct reset_control_bulk_data *rstcs); +int reset_control_bulk_deassert(int num_rstcs, struct reset_control_bulk_data *rstcs); +int reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rstcs); +void reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs); + struct reset_control *__of_reset_control_get(struct device_node *node, const char *id, int index, bool shared, bool optional, bool acquired); @@ -27,10 +48,18 @@ struct reset_control *__reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional, bool acquired); void reset_control_put(struct reset_control *rstc); +int __reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired); +void reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs); + int __device_reset(struct device *dev, bool optional); struct reset_control *__devm_reset_control_get(struct device *dev, const char *id, int index, bool shared, bool optional, bool acquired); +int __devm_reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired); struct reset_control *devm_reset_control_array_get(struct device *dev, bool shared, bool optional); @@ -96,6 +125,48 @@ static inline struct reset_control *__reset_control_get( return optional ? NULL : ERR_PTR(-ENOTSUPP); } +static inline int +reset_control_bulk_reset(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ + return 0; +} + +static inline int +reset_control_bulk_assert(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ + return 0; +} + +static inline int +reset_control_bulk_deassert(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ + return 0; +} + +static inline int +reset_control_bulk_acquire(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ + return 0; +} + +static inline void +reset_control_bulk_release(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ +} + +static inline int +__reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + return optional ? 0 : -EOPNOTSUPP; +} + +static inline void +reset_control_bulk_put(int num_rstcs, struct reset_control_bulk_data *rstcs) +{ +} + static inline struct reset_control *__devm_reset_control_get( struct device *dev, const char *id, int index, bool shared, bool optional, @@ -104,6 +175,14 @@ static inline struct reset_control *__devm_reset_control_get( return optional ? NULL : ERR_PTR(-ENOTSUPP); } +static inline int +__devm_reset_control_bulk_get(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs, + bool shared, bool optional, bool acquired) +{ + return optional ? 0 : -EOPNOTSUPP; +} + static inline struct reset_control * devm_reset_control_array_get(struct device *dev, bool shared, bool optional) { @@ -155,6 +234,23 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id) return __reset_control_get(dev, id, 0, false, false, true); } +/** + * reset_control_bulk_get_exclusive - Lookup and obtain exclusive references to + * multiple reset controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Fills the rstcs array with pointers to exclusive reset controls and + * returns 0, or an IS_ERR() condition containing errno. + */ +static inline int __must_check +reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); +} + /** * reset_control_get_exclusive_released - Lookup and obtain a temoprarily * exclusive reference to a reset @@ -176,6 +272,48 @@ __must_check reset_control_get_exclusive_released(struct device *dev, return __reset_control_get(dev, id, 0, false, false, false); } +/** + * reset_control_bulk_get_exclusive_released - Lookup and obtain temporarily + * exclusive references to multiple reset + * controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Fills the rstcs array with pointers to exclusive reset controls and + * returns 0, or an IS_ERR() condition containing errno. + * reset-controls returned by this function must be acquired via + * reset_control_bulk_acquire() before they can be used and should be released + * via reset_control_bulk_release() afterwards. + */ +static inline int __must_check +reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); +} + +/** + * reset_control_bulk_get_optional_exclusive_released - Lookup and obtain optional + * temporarily exclusive references to multiple + * reset controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Optional variant of reset_control_bulk_get_exclusive_released(). If the + * requested reset is not specified in the device tree, this function returns 0 + * instead of an error and missing rtsc is set to NULL. + * + * See reset_control_bulk_get_exclusive_released() for more information. + */ +static inline int __must_check +reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); +} + /** * reset_control_get_shared - Lookup and obtain a shared reference to a * reset controller. @@ -204,6 +342,23 @@ static inline struct reset_control *reset_control_get_shared( return __reset_control_get(dev, id, 0, true, false, false); } +/** + * reset_control_bulk_get_shared - Lookup and obtain shared references to + * multiple reset controllers. + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Fills the rstcs array with pointers to shared reset controls and + * returns 0, or an IS_ERR() condition containing errno. + */ +static inline int __must_check +reset_control_bulk_get_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); +} + /** * reset_control_get_optional_exclusive - optional reset_control_get_exclusive() * @dev: device to be reset by the controller @@ -221,6 +376,26 @@ static inline struct reset_control *reset_control_get_optional_exclusive( return __reset_control_get(dev, id, 0, false, true, true); } +/** + * reset_control_bulk_get_optional_exclusive - optional + * reset_control_bulk_get_exclusive() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Optional variant of reset_control_bulk_get_exclusive(). If any of the + * requested resets are not specified in the device tree, this function sets + * them to NULL instead of returning an error. + * + * See reset_control_bulk_get_exclusive() for more information. + */ +static inline int __must_check +reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, true); +} + /** * reset_control_get_optional_shared - optional reset_control_get_shared() * @dev: device to be reset by the controller @@ -238,6 +413,26 @@ static inline struct reset_control *reset_control_get_optional_shared( return __reset_control_get(dev, id, 0, true, true, false); } +/** + * reset_control_bulk_get_optional_shared - optional + * reset_control_bulk_get_shared() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Optional variant of reset_control_bulk_get_shared(). If the requested resets + * are not specified in the device tree, this function sets them to NULL + * instead of returning an error. + * + * See reset_control_bulk_get_shared() for more information. + */ +static inline int __must_check +reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); +} + /** * of_reset_control_get_exclusive - Lookup and obtain an exclusive reference * to a reset controller. @@ -343,6 +538,26 @@ __must_check devm_reset_control_get_exclusive(struct device *dev, return __devm_reset_control_get(dev, id, 0, false, false, true); } +/** + * devm_reset_control_bulk_get_exclusive - resource managed + * reset_control_bulk_get_exclusive() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_exclusive(). For reset controllers returned + * from this function, reset_control_put() is called automatically on driver + * detach. + * + * See reset_control_bulk_get_exclusive() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, true); +} + /** * devm_reset_control_get_exclusive_released - resource managed * reset_control_get_exclusive_released() @@ -362,6 +577,26 @@ __must_check devm_reset_control_get_exclusive_released(struct device *dev, return __devm_reset_control_get(dev, id, 0, false, false, false); } +/** + * devm_reset_control_bulk_get_exclusive_released - resource managed + * reset_control_bulk_get_exclusive_released() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_exclusive_released(). For reset controllers + * returned from this function, reset_control_put() is called automatically on + * driver detach. + * + * See reset_control_bulk_get_exclusive_released() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, false, false); +} + /** * devm_reset_control_get_optional_exclusive_released - resource managed * reset_control_get_optional_exclusive_released() @@ -381,6 +616,26 @@ __must_check devm_reset_control_get_optional_exclusive_released(struct device *d return __devm_reset_control_get(dev, id, 0, false, true, false); } +/** + * devm_reset_control_bulk_get_optional_exclusive_released - resource managed + * reset_control_bulk_optional_get_exclusive_released() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_optional_get_exclusive_released(). For reset + * controllers returned from this function, reset_control_put() is called + * automatically on driver detach. + * + * See reset_control_bulk_optional_get_exclusive_released() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_optional_exclusive_released(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, false, true, false); +} + /** * devm_reset_control_get_shared - resource managed reset_control_get_shared() * @dev: device to be reset by the controller @@ -396,6 +651,26 @@ static inline struct reset_control *devm_reset_control_get_shared( return __devm_reset_control_get(dev, id, 0, true, false, false); } +/** + * devm_reset_control_bulk_get_shared - resource managed + * reset_control_bulk_get_shared() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_shared(). For reset controllers returned + * from this function, reset_control_put() is called automatically on driver + * detach. + * + * See reset_control_bulk_get_shared() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, false); +} + /** * devm_reset_control_get_optional_exclusive - resource managed * reset_control_get_optional_exclusive() @@ -414,6 +689,26 @@ static inline struct reset_control *devm_reset_control_get_optional_exclusive( return __devm_reset_control_get(dev, id, 0, false, true, true); } +/** + * devm_reset_control_bulk_get_optional_exclusive - resource managed + * reset_control_bulk_get_optional_exclusive() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_optional_exclusive(). For reset controllers + * returned from this function, reset_control_put() is called automatically on + * driver detach. + * + * See reset_control_bulk_get_optional_exclusive() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_optional_exclusive(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, false, true); +} + /** * devm_reset_control_get_optional_shared - resource managed * reset_control_get_optional_shared() @@ -432,6 +727,26 @@ static inline struct reset_control *devm_reset_control_get_optional_shared( return __devm_reset_control_get(dev, id, 0, true, true, false); } +/** + * devm_reset_control_bulk_get_optional_shared - resource managed + * reset_control_bulk_get_optional_shared() + * @dev: device to be reset by the controller + * @num_rstcs: number of entries in rstcs array + * @rstcs: array of struct reset_control_bulk_data with reset line names set + * + * Managed reset_control_bulk_get_optional_shared(). For reset controllers + * returned from this function, reset_control_put() is called automatically on + * driver detach. + * + * See reset_control_bulk_get_optional_shared() for more information. + */ +static inline int __must_check +devm_reset_control_bulk_get_optional_shared(struct device *dev, int num_rstcs, + struct reset_control_bulk_data *rstcs) +{ + return __devm_reset_control_bulk_get(dev, num_rstcs, rstcs, true, true, false); +} + /** * devm_reset_control_get_exclusive_by_index - resource managed * reset_control_get_exclusive() From 050086eb6dc945207b1db1d15cd81e9366dfd2f1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:47 +0300 Subject: [PATCH 0259/1091] ASoC: tegra30: ahub: Switch to use reset-bulk API Switch to use reset-bulk API in order to make code cleaner. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-6-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 104 ++++++++++++--------------------- sound/soc/tegra/tegra30_ahub.h | 5 +- sound/soc/tegra/tegra30_i2s.c | 1 + 3 files changed, 40 insertions(+), 70 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 9ef05ca4f6c4..d24c26f4960d 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -65,7 +65,7 @@ static int tegra30_ahub_runtime_resume(struct device *dev) { int ret; - ret = reset_control_assert(ahub->reset); + ret = reset_control_bulk_assert(ahub->nresets, ahub->resets); if (ret) return ret; @@ -75,7 +75,7 @@ static int tegra30_ahub_runtime_resume(struct device *dev) usleep_range(10, 100); - ret = reset_control_deassert(ahub->reset); + ret = reset_control_bulk_deassert(ahub->nresets, ahub->resets); if (ret) goto disable_clocks; @@ -339,41 +339,28 @@ int tegra30_ahub_unset_rx_cif_source(enum tegra30_ahub_rxcif rxcif) } EXPORT_SYMBOL_GPL(tegra30_ahub_unset_rx_cif_source); -#define MOD_LIST_MASK_TEGRA30 BIT(0) -#define MOD_LIST_MASK_TEGRA114 BIT(1) -#define MOD_LIST_MASK_TEGRA124 BIT(2) - -#define MOD_LIST_MASK_TEGRA30_OR_LATER \ - (MOD_LIST_MASK_TEGRA30 | MOD_LIST_MASK_TEGRA114 | \ - MOD_LIST_MASK_TEGRA124) -#define MOD_LIST_MASK_TEGRA114_OR_LATER \ - (MOD_LIST_MASK_TEGRA114 | MOD_LIST_MASK_TEGRA124) - -static const struct { - const char *rst_name; - u32 mod_list_mask; -} configlink_mods[] = { - { "d_audio", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "apbif", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s0", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s1", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s2", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s3", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "i2s4", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "dam0", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "dam1", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "dam2", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "spdif", MOD_LIST_MASK_TEGRA30_OR_LATER }, - { "amx", MOD_LIST_MASK_TEGRA114_OR_LATER }, - { "adx", MOD_LIST_MASK_TEGRA114_OR_LATER }, - { "amx1", MOD_LIST_MASK_TEGRA124 }, - { "adx1", MOD_LIST_MASK_TEGRA124 }, - { "afc0", MOD_LIST_MASK_TEGRA124 }, - { "afc1", MOD_LIST_MASK_TEGRA124 }, - { "afc2", MOD_LIST_MASK_TEGRA124 }, - { "afc3", MOD_LIST_MASK_TEGRA124 }, - { "afc4", MOD_LIST_MASK_TEGRA124 }, - { "afc5", MOD_LIST_MASK_TEGRA124 }, +static const struct reset_control_bulk_data tegra30_ahub_resets_data[] = { + { "d_audio" }, + { "apbif" }, + { "i2s0" }, + { "i2s1" }, + { "i2s2" }, + { "i2s3" }, + { "i2s4" }, + { "dam0" }, + { "dam1" }, + { "dam2" }, + { "spdif" }, + { "amx" }, /* Tegra114+ */ + { "adx" }, /* Tegra114+ */ + { "amx1" }, /* Tegra124 */ + { "adx1" }, /* Tegra124 */ + { "afc0" }, /* Tegra124 */ + { "afc1" }, /* Tegra124 */ + { "afc2" }, /* Tegra124 */ + { "afc3" }, /* Tegra124 */ + { "afc4" }, /* Tegra124 */ + { "afc5" }, /* Tegra124 */ }; #define LAST_REG(name) \ @@ -502,17 +489,17 @@ static const struct regmap_config tegra30_ahub_ahub_regmap_config = { }; static struct tegra30_ahub_soc_data soc_data_tegra30 = { - .mod_list_mask = MOD_LIST_MASK_TEGRA30, + .num_resets = 11, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra114 = { - .mod_list_mask = MOD_LIST_MASK_TEGRA114, + .num_resets = 13, .set_audio_cif = tegra30_ahub_set_cif, }; static struct tegra30_ahub_soc_data soc_data_tegra124 = { - .mod_list_mask = MOD_LIST_MASK_TEGRA124, + .num_resets = 21, .set_audio_cif = tegra124_ahub_set_cif, }; @@ -527,8 +514,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev) { const struct of_device_id *match; const struct tegra30_ahub_soc_data *soc_data; - struct reset_control *rst; - int i; struct resource *res0; void __iomem *regs_apbif, *regs_ahub; int ret = 0; @@ -541,34 +526,16 @@ static int tegra30_ahub_probe(struct platform_device *pdev) return -EINVAL; soc_data = match->data; - /* - * The AHUB hosts a register bus: the "configlink". For this to - * operate correctly, all devices on this bus must be out of reset. - */ - for (i = 0; i < ARRAY_SIZE(configlink_mods); i++) { - if (!(configlink_mods[i].mod_list_mask & - soc_data->mod_list_mask)) - continue; - - rst = reset_control_get_exclusive(&pdev->dev, - configlink_mods[i].rst_name); - if (IS_ERR(rst)) { - dev_err(&pdev->dev, "Can't get reset %s\n", - configlink_mods[i].rst_name); - ret = PTR_ERR(rst); - return ret; - } - - /* just check presence of the reset control in DT */ - reset_control_put(rst); - } - ahub = devm_kzalloc(&pdev->dev, sizeof(struct tegra30_ahub), GFP_KERNEL); if (!ahub) return -ENOMEM; dev_set_drvdata(&pdev->dev, ahub); + BUILD_BUG_ON(sizeof(ahub->resets) != sizeof(tegra30_ahub_resets_data)); + memcpy(ahub->resets, tegra30_ahub_resets_data, sizeof(ahub->resets)); + + ahub->nresets = soc_data->num_resets; ahub->soc_data = soc_data; ahub->dev = &pdev->dev; @@ -579,10 +546,11 @@ static int tegra30_ahub_probe(struct platform_device *pdev) if (ret) return ret; - ahub->reset = devm_reset_control_array_get_exclusive(&pdev->dev); - if (IS_ERR(ahub->reset)) { - dev_err(&pdev->dev, "Can't get resets: %pe\n", ahub->reset); - return PTR_ERR(ahub->reset); + ret = devm_reset_control_bulk_get_exclusive(&pdev->dev, ahub->nresets, + ahub->resets); + if (ret) { + dev_err(&pdev->dev, "Can't get resets: %d\n", ret); + return ret; } res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); diff --git a/sound/soc/tegra/tegra30_ahub.h b/sound/soc/tegra/tegra30_ahub.h index 3b85244f87f1..c9eaf4ec8f6e 100644 --- a/sound/soc/tegra/tegra30_ahub.h +++ b/sound/soc/tegra/tegra30_ahub.h @@ -491,7 +491,7 @@ void tegra124_ahub_set_cif(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); struct tegra30_ahub_soc_data { - u32 mod_list_mask; + unsigned int num_resets; void (*set_audio_cif)(struct regmap *regmap, unsigned int reg, struct tegra30_ahub_cif_conf *conf); @@ -511,7 +511,8 @@ struct tegra30_ahub_soc_data { struct tegra30_ahub { const struct tegra30_ahub_soc_data *soc_data; struct device *dev; - struct reset_control *reset; + struct reset_control_bulk_data resets[21]; + unsigned int nresets; struct clk_bulk_data clocks[2]; unsigned int nclocks; resource_size_t apbif_addr; diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 3d22c1be6f3d..614b67be1dd9 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -23,6 +23,7 @@ #include #include #include +#include #include #include #include From 0911f154a2ae264ee2a7c868c1267a102396d016 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:48 +0300 Subject: [PATCH 0260/1091] ASoC: tegra20: spdif: Correct driver removal order Tegra20 SPDIF driver has a wrong driver removal order, which should be opposite to the registration order, but it's not. In particular the runtime PM is disabled in a wrong order. Fix the order. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-7-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_spdif.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 5839833e23a0..e48d332506a0 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -329,13 +329,13 @@ err_pm_disable: static int tegra20_spdif_platform_remove(struct platform_device *pdev) { + tegra_pcm_platform_unregister(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); + pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra20_spdif_runtime_suspend(&pdev->dev); - tegra_pcm_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - return 0; } From c53b396f0dd49a626ea2b1fc0a8b9e0a0bf95d4d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:49 +0300 Subject: [PATCH 0261/1091] ASoC: tegra20: spdif: Remove handing of disabled runtime PM Runtime PM is always available on Tegra since commit 40b2bb1b132a ("ARM: tegra: enforce PM requirement"), hence there is no need to handle the case of a disabled RPM by Tegra drivers. Remove handing of a disabled runtime PM from Tegra20 SPDIF driver. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-8-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_spdif.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index e48d332506a0..7b597ee63cb5 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -294,18 +294,13 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) spdif->playback_dma_data.slave_id = dmareq->start; pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - ret = tegra20_spdif_runtime_resume(&pdev->dev); - if (ret) - goto err_pm_disable; - } ret = snd_soc_register_component(&pdev->dev, &tegra20_spdif_component, &tegra20_spdif_dai, 1); if (ret) { dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); ret = -ENOMEM; - goto err_suspend; + goto err_pm_disable; } ret = tegra_pcm_platform_register(&pdev->dev); @@ -318,9 +313,6 @@ static int tegra20_spdif_platform_probe(struct platform_device *pdev) err_unregister_component: snd_soc_unregister_component(&pdev->dev); -err_suspend: - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra20_spdif_runtime_suspend(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); @@ -333,8 +325,6 @@ static int tegra20_spdif_platform_remove(struct platform_device *pdev) snd_soc_unregister_component(&pdev->dev); pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra20_spdif_runtime_suspend(&pdev->dev); return 0; } From e33fdd9bee12be35d080bfd4acc9d1e3a0d04001 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:50 +0300 Subject: [PATCH 0262/1091] ASoC: tegra20: i2s: Add system level suspend-resume callbacks Add system level suspend-resume callbacks in order to ensure that I2S is gated before system is suspended. This puts Tegra20 I2S driver on par with the Tegra30 I2S driver. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-9-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index c0af5352b483..267517446d27 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -460,6 +460,8 @@ static const struct of_device_id tegra20_i2s_of_match[] = { static const struct dev_pm_ops tegra20_i2s_pm_ops = { SET_RUNTIME_PM_OPS(tegra20_i2s_runtime_suspend, tegra20_i2s_runtime_resume, NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver tegra20_i2s_driver = { From ca6e960ed6b10ba9236da8b3614574bb4524c65e Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:51 +0300 Subject: [PATCH 0263/1091] ASoC: tegra20: i2s: Correct driver removal order Tegra20 I2S driver has a wrong driver removal order, which should be opposite to the registration order, but it's not. In particular the runtime PM is disabled in a wrong order. Fix the order. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-10-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 267517446d27..0f2bdc2e8598 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -440,13 +440,13 @@ static int tegra20_i2s_platform_remove(struct platform_device *pdev) { struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev); + tegra_pcm_platform_unregister(&pdev->dev); + snd_soc_unregister_component(&pdev->dev); + pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra20_i2s_runtime_suspend(&pdev->dev); - tegra_pcm_platform_unregister(&pdev->dev); - snd_soc_unregister_component(&pdev->dev); - clk_put(i2s->clk_i2s); return 0; From d3c6ef98dadd1e500445e4c5a9d684cbf3182c7d Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:52 +0300 Subject: [PATCH 0264/1091] ASoC: tegra20: i2s: Use devm_clk_get() Use resource-managed variant of clk_get() to simplify code. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-11-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 0f2bdc2e8598..fe569198b17a 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -370,7 +370,7 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) return PTR_ERR(i2s->reset); } - i2s->clk_i2s = clk_get(&pdev->dev, NULL); + i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2s->clk_i2s)) { dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); ret = PTR_ERR(i2s->clk_i2s); @@ -381,7 +381,7 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) regs = devm_ioremap_resource(&pdev->dev, mem); if (IS_ERR(regs)) { ret = PTR_ERR(regs); - goto err_clk_put; + goto err; } i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, @@ -389,7 +389,7 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) if (IS_ERR(i2s->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); ret = PTR_ERR(i2s->regmap); - goto err_clk_put; + goto err; } i2s->capture_dma_data.addr = mem->start + TEGRA20_I2S_FIFO2; @@ -430,16 +430,12 @@ err_suspend: tegra20_i2s_runtime_suspend(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); -err_clk_put: - clk_put(i2s->clk_i2s); err: return ret; } static int tegra20_i2s_platform_remove(struct platform_device *pdev) { - struct tegra20_i2s *i2s = dev_get_drvdata(&pdev->dev); - tegra_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); @@ -447,8 +443,6 @@ static int tegra20_i2s_platform_remove(struct platform_device *pdev) if (!pm_runtime_status_suspended(&pdev->dev)) tegra20_i2s_runtime_suspend(&pdev->dev); - clk_put(i2s->clk_i2s); - return 0; } From 80ec4a4cb36d3f8bb56b5aa89faceb1145ef7aea Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:53 +0300 Subject: [PATCH 0265/1091] ASoC: tegra20: i2s: Remove handing of disabled runtime PM Runtime PM is always available on Tegra since commit 40b2bb1b132a ("ARM: tegra: enforce PM requirement"), hence there is no need to handle the case of a disabled RPM by Tegra drivers. Remove handing of a disabled runtime PM from Tegra20 I2S driver. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-12-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index fe569198b17a..1b27f81c10fe 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -401,18 +401,13 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) i2s->playback_dma_data.maxburst = 4; pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - ret = tegra20_i2s_runtime_resume(&pdev->dev); - if (ret) - goto err_pm_disable; - } ret = snd_soc_register_component(&pdev->dev, &tegra20_i2s_component, &i2s->dai, 1); if (ret) { dev_err(&pdev->dev, "Could not register DAI: %d\n", ret); ret = -ENOMEM; - goto err_suspend; + goto err_pm_disable; } ret = tegra_pcm_platform_register(&pdev->dev); @@ -425,9 +420,6 @@ static int tegra20_i2s_platform_probe(struct platform_device *pdev) err_unregister_component: snd_soc_unregister_component(&pdev->dev); -err_suspend: - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra20_i2s_runtime_suspend(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); err: @@ -438,10 +430,7 @@ static int tegra20_i2s_platform_remove(struct platform_device *pdev) { tegra_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); - pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra20_i2s_runtime_suspend(&pdev->dev); return 0; } From f852e1e4acf4ebde4c960bab6f89407fa18ca489 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:54 +0300 Subject: [PATCH 0266/1091] ASoC: tegra30: i2s: Correct driver removal order Tegra30 I2S driver has a wrong driver removal order, which should be opposite to the registration order, but it's not. In particular the runtime PM is disabled in a wrong order. Fix the order. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-13-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_i2s.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 614b67be1dd9..31e08c5c1405 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -544,10 +544,6 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) { struct tegra30_i2s *i2s = dev_get_drvdata(&pdev->dev); - pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra30_i2s_runtime_suspend(&pdev->dev); - tegra_pcm_platform_unregister(&pdev->dev); snd_soc_unregister_component(&pdev->dev); @@ -557,6 +553,10 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif); tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif); + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + tegra30_i2s_runtime_suspend(&pdev->dev); + clk_put(i2s->clk_i2s); return 0; From 52674aef9eb678f30d99f77fd53f6c564d5e2d92 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:55 +0300 Subject: [PATCH 0267/1091] ASoC: tegra30: i2s: Use devm_clk_get() Use resource-managed variant of clk_get() to simplify code. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-14-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_i2s.c | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 31e08c5c1405..0ed982548ce4 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -438,7 +438,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) i2s->playback_i2s_cif = cif_ids[0]; i2s->capture_i2s_cif = cif_ids[1]; - i2s->clk_i2s = clk_get(&pdev->dev, NULL); + i2s->clk_i2s = devm_clk_get(&pdev->dev, NULL); if (IS_ERR(i2s->clk_i2s)) { dev_err(&pdev->dev, "Can't retrieve i2s clock\n"); ret = PTR_ERR(i2s->clk_i2s); @@ -448,7 +448,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) regs = devm_platform_ioremap_resource(pdev, 0); if (IS_ERR(regs)) { ret = PTR_ERR(regs); - goto err_clk_put; + goto err; } i2s->regmap = devm_regmap_init_mmio(&pdev->dev, regs, @@ -456,7 +456,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) if (IS_ERR(i2s->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); ret = PTR_ERR(i2s->regmap); - goto err_clk_put; + goto err; } regcache_cache_only(i2s->regmap, true); @@ -534,8 +534,6 @@ err_suspend: tegra30_i2s_runtime_suspend(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); -err_clk_put: - clk_put(i2s->clk_i2s); err: return ret; } @@ -557,8 +555,6 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) if (!pm_runtime_status_suspended(&pdev->dev)) tegra30_i2s_runtime_suspend(&pdev->dev); - clk_put(i2s->clk_i2s); - return 0; } From b5f6f781fcb27b3ae5a2f04312a190115b5cbbd1 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:56 +0300 Subject: [PATCH 0268/1091] ASoC: tegra30: i2s: Remove handing of disabled runtime PM Runtime PM is always available on Tegra since commit 40b2bb1b132a ("ARM: tegra: enforce PM requirement"), hence there is no need to handle the case of a disabled RPM by Tegra drivers. Remove handing of a disabled runtime PM from Tegra30 I2S driver. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-15-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_i2s.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 0ed982548ce4..8730ffa0f691 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -461,11 +461,6 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) regcache_cache_only(i2s->regmap, true); pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - ret = tegra30_i2s_runtime_resume(&pdev->dev); - if (ret) - goto err_pm_disable; - } i2s->playback_dma_data.addr_width = DMA_SLAVE_BUSWIDTH_4_BYTES; i2s->playback_dma_data.maxburst = 4; @@ -475,7 +470,7 @@ static int tegra30_i2s_platform_probe(struct platform_device *pdev) &i2s->playback_dma_data.addr); if (ret) { dev_err(&pdev->dev, "Could not alloc TX FIFO: %d\n", ret); - goto err_suspend; + goto err_pm_disable; } ret = tegra30_ahub_set_rx_cif_source(i2s->playback_i2s_cif, i2s->playback_fifo_cif); @@ -529,9 +524,6 @@ err_unroute_tx_fifo: tegra30_ahub_unset_rx_cif_source(i2s->playback_i2s_cif); err_free_tx_fifo: tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif); -err_suspend: - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra30_i2s_runtime_suspend(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); err: @@ -552,8 +544,6 @@ static int tegra30_i2s_platform_remove(struct platform_device *pdev) tegra30_ahub_free_tx_fifo(i2s->playback_fifo_cif); pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra30_i2s_runtime_suspend(&pdev->dev); return 0; } From 5d956e3cb806870012c443bc265e6ac6188d3c36 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:57 +0300 Subject: [PATCH 0269/1091] ASoC: tegra30: ahub: Reset global variable Tegra30 AHUB uses global variable that is never reset by the driver on a probe failure and on driver removal, meaning that driver will never try to re-probe and can't be unbound. Make driver to reset the variable. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-16-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index d24c26f4960d..409a259e6343 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -518,9 +518,6 @@ static int tegra30_ahub_probe(struct platform_device *pdev) void __iomem *regs_apbif, *regs_ahub; int ret = 0; - if (ahub) - return -ENODEV; - match = of_match_device(tegra30_ahub_of_match, &pdev->dev); if (!match) return -EINVAL; @@ -544,19 +541,21 @@ static int tegra30_ahub_probe(struct platform_device *pdev) ret = devm_clk_bulk_get(&pdev->dev, ahub->nclocks, ahub->clocks); if (ret) - return ret; + goto err_unset_ahub; ret = devm_reset_control_bulk_get_exclusive(&pdev->dev, ahub->nresets, ahub->resets); if (ret) { dev_err(&pdev->dev, "Can't get resets: %d\n", ret); - return ret; + goto err_unset_ahub; } res0 = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs_apbif = devm_ioremap_resource(&pdev->dev, res0); - if (IS_ERR(regs_apbif)) - return PTR_ERR(regs_apbif); + if (IS_ERR(regs_apbif)) { + ret = PTR_ERR(regs_apbif); + goto err_unset_ahub; + } ahub->apbif_addr = res0->start; @@ -565,20 +564,22 @@ static int tegra30_ahub_probe(struct platform_device *pdev) if (IS_ERR(ahub->regmap_apbif)) { dev_err(&pdev->dev, "apbif regmap init failed\n"); ret = PTR_ERR(ahub->regmap_apbif); - return ret; + goto err_unset_ahub; } regcache_cache_only(ahub->regmap_apbif, true); regs_ahub = devm_platform_ioremap_resource(pdev, 1); - if (IS_ERR(regs_ahub)) - return PTR_ERR(regs_ahub); + if (IS_ERR(regs_ahub)) { + ret = PTR_ERR(regs_ahub); + goto err_unset_ahub; + } ahub->regmap_ahub = devm_regmap_init_mmio(&pdev->dev, regs_ahub, &tegra30_ahub_ahub_regmap_config); if (IS_ERR(ahub->regmap_ahub)) { dev_err(&pdev->dev, "ahub regmap init failed\n"); ret = PTR_ERR(ahub->regmap_ahub); - return ret; + goto err_unset_ahub; } regcache_cache_only(ahub->regmap_ahub, true); @@ -595,19 +596,20 @@ static int tegra30_ahub_probe(struct platform_device *pdev) err_pm_disable: pm_runtime_disable(&pdev->dev); +err_unset_ahub: + ahub = NULL; return ret; } static int tegra30_ahub_remove(struct platform_device *pdev) { - if (!ahub) - return -ENODEV; - pm_runtime_disable(&pdev->dev); if (!pm_runtime_status_suspended(&pdev->dev)) tegra30_ahub_runtime_suspend(&pdev->dev); + ahub = NULL; + return 0; } From e2965c2ca139e780dc353cef1474103bb037136e Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:58 +0300 Subject: [PATCH 0270/1091] ASoC: tegra30: ahub: Correct suspend-resume callbacks Tegra30 AHUB driver always syncs hardware state on a runtime PM resume, hence there is no needed to re-sync the state on system resume. Replace the suspend-resume callbacks with a generic helpers which ensure that AHUB is suspended using RPM callbacks across system suspend-resume. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-17-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 29 ++--------------------------- 1 file changed, 2 insertions(+), 27 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index 409a259e6343..e64b41bc5fdf 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -613,36 +613,11 @@ static int tegra30_ahub_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM_SLEEP -static int tegra30_ahub_suspend(struct device *dev) -{ - regcache_mark_dirty(ahub->regmap_ahub); - regcache_mark_dirty(ahub->regmap_apbif); - - return 0; -} - -static int tegra30_ahub_resume(struct device *dev) -{ - int ret; - - ret = pm_runtime_get_sync(dev); - if (ret < 0) { - pm_runtime_put(dev); - return ret; - } - ret = regcache_sync(ahub->regmap_ahub); - ret |= regcache_sync(ahub->regmap_apbif); - pm_runtime_put(dev); - - return ret; -} -#endif - static const struct dev_pm_ops tegra30_ahub_pm_ops = { SET_RUNTIME_PM_OPS(tegra30_ahub_runtime_suspend, tegra30_ahub_runtime_resume, NULL) - SET_SYSTEM_SLEEP_PM_OPS(tegra30_ahub_suspend, tegra30_ahub_resume) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) }; static struct platform_driver tegra30_ahub_driver = { From b5571449e6186bd37e8da16e7bce53f621c05e72 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 14 Mar 2021 18:44:59 +0300 Subject: [PATCH 0271/1091] ASoC: tegra30: ahub: Remove handing of disabled runtime PM Runtime PM is always available on Tegra since commit 40b2bb1b132a ("ARM: tegra: enforce PM requirement"), hence there is no need to handle the case of a disabled RPM by Tegra drivers. Remove handing of a disabled runtime PM from Tegra30 AHUB driver. Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210314154459.15375-18-digetx@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra30_ahub.c | 9 --------- 1 file changed, 9 deletions(-) diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index e64b41bc5fdf..d1718f3af3cd 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -584,18 +584,11 @@ static int tegra30_ahub_probe(struct platform_device *pdev) regcache_cache_only(ahub->regmap_ahub, true); pm_runtime_enable(&pdev->dev); - if (!pm_runtime_enabled(&pdev->dev)) { - ret = tegra30_ahub_runtime_resume(&pdev->dev); - if (ret) - goto err_pm_disable; - } of_platform_populate(pdev->dev.of_node, NULL, NULL, &pdev->dev); return 0; -err_pm_disable: - pm_runtime_disable(&pdev->dev); err_unset_ahub: ahub = NULL; @@ -605,8 +598,6 @@ err_unset_ahub: static int tegra30_ahub_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); - if (!pm_runtime_status_suspended(&pdev->dev)) - tegra30_ahub_runtime_suspend(&pdev->dev); ahub = NULL; From 73b4fe4a03db519977a22cdf34303bd0ac21c69d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:24 -0600 Subject: [PATCH 0272/1091] ASoC: ab8500-codec: remove useless structure Cppcheck warnings: sound/soc/codecs/ab8500-codec.c:117:20: style: struct member 'ab8500_codec_drvdata_dbg::vaud' is never used. [unusedStructMember] struct regulator *vaud; ^ sound/soc/codecs/ab8500-codec.c:118:20: style: struct member 'ab8500_codec_drvdata_dbg::vamic1' is never used. [unusedStructMember] struct regulator *vamic1; ^ sound/soc/codecs/ab8500-codec.c:119:20: style: struct member 'ab8500_codec_drvdata_dbg::vamic2' is never used. [unusedStructMember] struct regulator *vamic2; ^ sound/soc/codecs/ab8500-codec.c:120:20: style: struct member 'ab8500_codec_drvdata_dbg::vdmic' is never used. [unusedStructMember] struct regulator *vdmic; ^ The structure is never used, remove. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/ab8500-codec.c | 7 ------- 1 file changed, 7 deletions(-) diff --git a/sound/soc/codecs/ab8500-codec.c b/sound/soc/codecs/ab8500-codec.c index c95f007cede1..5525e1ccab76 100644 --- a/sound/soc/codecs/ab8500-codec.c +++ b/sound/soc/codecs/ab8500-codec.c @@ -113,13 +113,6 @@ enum amic_idx { AMIC_IDX_2 }; -struct ab8500_codec_drvdata_dbg { - struct regulator *vaud; - struct regulator *vamic1; - struct regulator *vamic2; - struct regulator *vdmic; -}; - /* Private data for AB8500 device-driver */ struct ab8500_codec_drvdata { struct regmap *regmap; From ca6b3a6ca047d23b9b2a54af9f7f4d6f41200719 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:25 -0600 Subject: [PATCH 0273/1091] ASoC: ad1836: remove useless return Cppcheck warning: sound/soc/codecs/ad1836.c:311:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/codecs/ad1836.c:308:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/codecs/ad1836.c:311:9: note: Returning identical expression 'ret' return ret; ^ Likely copy/paste between adc and dac cases. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/ad1836.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/ad1836.c b/sound/soc/codecs/ad1836.c index a46152560294..08a5651bed9f 100644 --- a/sound/soc/codecs/ad1836.c +++ b/sound/soc/codecs/ad1836.c @@ -305,8 +305,6 @@ static int ad1836_probe(struct snd_soc_component *component) return ret; ret = snd_soc_dapm_add_routes(dapm, ad183x_adc_routes, num_adcs); - if (ret) - return ret; return ret; } From 5b349c8f355ae4bd1de462f1f1b6164d14796b0e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:26 -0600 Subject: [PATCH 0274/1091] ASoC: adau1977: remove useless return Cppcheck warning: sound/soc/codecs/adau1977.c:242:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/codecs/adau1977.c:239:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/codecs/adau1977.c:242:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/adau1977.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/adau1977.c b/sound/soc/codecs/adau1977.c index 8260f49caa24..e347a48131d1 100644 --- a/sound/soc/codecs/adau1977.c +++ b/sound/soc/codecs/adau1977.c @@ -236,8 +236,6 @@ static int adau1977_reset(struct adau1977 *adau1977) ret = regmap_write(adau1977->regmap, ADAU1977_REG_POWER, ADAU1977_POWER_RESET); regcache_cache_bypass(adau1977->regmap, false); - if (ret) - return ret; return ret; } From 157c4df677569daad6f204c63cfaf226c941bf03 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:27 -0600 Subject: [PATCH 0275/1091] ASoC: cros_ec_codec: remove null pointer dereference warning Cppcheck complains of a possible issue: sound/soc/codecs/cros_ec_codec.c:98:10: warning: Possible null pointer dereference: in [nullPointer] memcpy(in, msg->data, insize); ^ sound/soc/codecs/cros_ec_codec.c:162:34: note: Calling function 'send_ec_host_command', 5th argument 'NULL' value is 0 (uint8_t *)&p, sizeof(p), NULL, 0); ^ sound/soc/codecs/cros_ec_codec.c:98:10: note: Null pointer dereference memcpy(in, msg->data, insize); ^ In practice the access to the pointer is protected by another argument, but this is likely to fool other static analysis tools. Add a test to avoid doing the memcpy if the pointer is NULL or the size is zero. Signed-off-by: Pierre-Louis Bossart Acked-by: Enric Balletbo i Serra Link: https://lore.kernel.org/r/20210312182246.5153-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cros_ec_codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cros_ec_codec.c b/sound/soc/codecs/cros_ec_codec.c index c4772f82485a..a201d652aca2 100644 --- a/sound/soc/codecs/cros_ec_codec.c +++ b/sound/soc/codecs/cros_ec_codec.c @@ -94,7 +94,7 @@ static int send_ec_host_command(struct cros_ec_device *ec_dev, uint32_t cmd, if (ret < 0) goto error; - if (insize) + if (in && insize) memcpy(in, msg->data, insize); ret = 0; From 4d753b6642ee7304fc56f9fc463bb69ec641a037 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:28 -0600 Subject: [PATCH 0276/1091] ASoC: cx2070x: remove useless assignment Cppcheck warning: sound/soc/codecs/cx2072x.c:830:26: style: Variable 'reg1.r.rx_data_one_line' is reassigned a value before the old one has been used. [redundantAssignment] reg1.r.rx_data_one_line = 1; ^ sound/soc/codecs/cx2072x.c:782:26: note: reg1.r.rx_data_one_line is assigned reg1.r.rx_data_one_line = 1; ^ sound/soc/codecs/cx2072x.c:830:26: note: reg1.r.rx_data_one_line is overwritten reg1.r.rx_data_one_line = 1; ^ sound/soc/codecs/cx2072x.c:831:26: style: Variable 'reg1.r.tx_data_one_line' is reassigned a value before the old one has been used. [redundantAssignment] reg1.r.tx_data_one_line = 1; ^ sound/soc/codecs/cx2072x.c:783:26: note: reg1.r.tx_data_one_line is assigned reg1.r.tx_data_one_line = 1; ^ sound/soc/codecs/cx2072x.c:831:26: note: reg1.r.tx_data_one_line is overwritten reg1.r.tx_data_one_line = 1; ^ Likely copy/paste. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20210312182246.5153-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index 8ab22815c2c9..d2d004654c9b 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -827,9 +827,6 @@ static int cx2072x_config_i2spcm(struct cx2072x_priv *cx2072x) } regdbt2.r.i2s_bclk_invert = is_bclk_inv; - reg1.r.rx_data_one_line = 1; - reg1.r.tx_data_one_line = 1; - /* Configures the BCLK output */ bclk_rate = cx2072x->sample_rate * frame_len; reg5.r.i2s_pcm_clk_div_chan_en = 0; From 8d41c1ab248fa6e6bfd4728a31eec6d3b9e0f924 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:29 -0600 Subject: [PATCH 0277/1091] ASoC: cx2070x: remove duplicate else branch cppcheck warning: sound/soc/codecs/cx2072x.c:1436:10: style:inconclusive: Found duplicate branches for 'if' and 'else'. [duplicateBranch] } else if (type & 0x4) { ^ sound/soc/codecs/cx2072x.c:1439:5: note: Found duplicate branches for 'if' and 'else'. } else { ^ sound/soc/codecs/cx2072x.c:1436:10: note: Found duplicate branches for 'if' and 'else'. } else if (type & 0x4) { ^ The last two branches do the same thing and can be collapsed together. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Takashi Iwai Link: https://lore.kernel.org/r/20210312182246.5153-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index d2d004654c9b..d924e3528029 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1430,11 +1430,11 @@ static int cx2072x_jack_status_check(void *data) state |= SND_JACK_HEADSET; if (type & 0x2) state |= SND_JACK_BTN_0; - } else if (type & 0x4) { - /* Nokia headset */ - state |= SND_JACK_HEADPHONE; } else { - /* Headphone */ + /* + * Nokia headset (type & 0x4) and + * regular Headphone + */ state |= SND_JACK_HEADPHONE; } } From f8a684a4c2c9a6f922453f0e5dc6d20b1bdb082b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:30 -0600 Subject: [PATCH 0278/1091] ASoC: da7219-aad: remove useless initialization cppcheck warning: sound/soc/codecs/da7219-aad.c:118:22: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int report = 0, ret = 0; ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Adam Thomson Link: https://lore.kernel.org/r/20210312182246.5153-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7219-aad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/da7219-aad.c b/sound/soc/codecs/da7219-aad.c index 48081d71c22c..7998fdd3b378 100644 --- a/sound/soc/codecs/da7219-aad.c +++ b/sound/soc/codecs/da7219-aad.c @@ -115,7 +115,7 @@ static void da7219_aad_hptest_work(struct work_struct *work) __le16 tonegen_freq_hptest; u8 pll_srm_sts, pll_ctrl, gain_ramp_ctrl, accdet_cfg8; - int report = 0, ret = 0; + int report = 0, ret; /* Lock DAPM, Kcontrols affected by this test and the PLL */ snd_soc_dapm_mutex_lock(dapm); From 426b3bbcee199e1e96ec62b1c1d9cb7019a84efb Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:31 -0600 Subject: [PATCH 0279/1091] ASoC: hdac_hdmi: remove useless initializations Cppcheck complains a lot about possible null pointer dereferences but it's again a case of useless initializations to NULL. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/hdac_hdmi.c b/sound/soc/codecs/hdac_hdmi.c index 2c1305bf0572..66408a98298b 100644 --- a/sound/soc/codecs/hdac_hdmi.c +++ b/sound/soc/codecs/hdac_hdmi.c @@ -523,7 +523,7 @@ static struct hdac_hdmi_port *hdac_hdmi_get_port_from_cvt( struct hdac_hdmi_cvt *cvt) { struct hdac_hdmi_pcm *pcm; - struct hdac_hdmi_port *port = NULL; + struct hdac_hdmi_port *port; int ret, i; list_for_each_entry(pcm, &hdmi->pcm_list, head) { @@ -713,7 +713,7 @@ static struct hdac_hdmi_pcm *hdac_hdmi_get_pcm(struct hdac_device *hdev, struct hdac_hdmi_port *port) { struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); - struct hdac_hdmi_pcm *pcm = NULL; + struct hdac_hdmi_pcm *pcm; struct hdac_hdmi_port *p; list_for_each_entry(pcm, &hdmi->pcm_list, head) { @@ -900,7 +900,7 @@ static int hdac_hdmi_set_pin_port_mux(struct snd_kcontrol *kcontrol, struct hdac_hdmi_port *port = w->priv; struct hdac_device *hdev = dev_to_hdac_dev(dapm->dev); struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); - struct hdac_hdmi_pcm *pcm = NULL; + struct hdac_hdmi_pcm *pcm; const char *cvt_name = e->texts[ucontrol->value.enumerated.item[0]]; ret = snd_soc_dapm_put_enum_double(kcontrol, ucontrol); @@ -1693,7 +1693,7 @@ static void hdac_hdmi_eld_notify_cb(void *aptr, int port, int pipe) { struct hdac_device *hdev = aptr; struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev); - struct hdac_hdmi_pin *pin = NULL; + struct hdac_hdmi_pin *pin; struct hdac_hdmi_port *hport = NULL; struct snd_soc_component *component = hdmi->component; int i; @@ -1958,7 +1958,7 @@ static int hdmi_codec_probe(struct snd_soc_component *component) struct hdac_device *hdev = hdmi->hdev; struct snd_soc_dapm_context *dapm = snd_soc_component_get_dapm(component); - struct hdac_ext_link *hlink = NULL; + struct hdac_ext_link *hlink; int ret; hdmi->component = component; @@ -2227,7 +2227,7 @@ static int hdac_hdmi_runtime_suspend(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; - struct hdac_ext_link *hlink = NULL; + struct hdac_ext_link *hlink; dev_dbg(dev, "Enter: %s\n", __func__); @@ -2263,7 +2263,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev) { struct hdac_device *hdev = dev_to_hdac_dev(dev); struct hdac_bus *bus = hdev->bus; - struct hdac_ext_link *hlink = NULL; + struct hdac_ext_link *hlink; dev_dbg(dev, "Enter: %s\n", __func__); From 997994d7e6fab713d1c03843c9698919e64cc135 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:32 -0600 Subject: [PATCH 0280/1091] ASoC: hdac_hdmi: align function arguments cppcheck warning: sound/soc/codecs/hdac_hdmi.c:1882:54: style:inconclusive: Function 'hdac_hdmi_jack_init' argument 2 names different: declaration 'pcm' definition 'device'. [funcArgNamesDifferent] int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, ^ sound/soc/codecs/hdac_hdmi.h:5:54: note: Function 'hdac_hdmi_jack_init' argument 2 names different: declaration 'pcm' definition 'device'. int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm, ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdac_hdmi.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/hdac_hdmi.h b/sound/soc/codecs/hdac_hdmi.h index 4fa2fc9ee893..493fa3b4ef75 100644 --- a/sound/soc/codecs/hdac_hdmi.h +++ b/sound/soc/codecs/hdac_hdmi.h @@ -2,7 +2,7 @@ #ifndef __HDAC_HDMI_H__ #define __HDAC_HDMI_H__ -int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int pcm, +int hdac_hdmi_jack_init(struct snd_soc_dai *dai, int device, struct snd_soc_jack *jack); int hdac_hdmi_jack_port_init(struct snd_soc_component *component, From 3c011ef344cddd15be0a9b2256f7886f6b5eeec5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:33 -0600 Subject: [PATCH 0281/1091] ASoC: hdmi-codec: remove useless initialization Fix cppcheck warning: sound/soc/codecs/hdmi-codec.c:745:5: style: Redundant initialization for 'cf'. The initialized value is overwritten before it is read. [redundantInitialization] cf = dai->playback_dma_data; ^ sound/soc/codecs/hdmi-codec.c:738:31: note: cf is initialized struct hdmi_codec_daifmt *cf = dai->playback_dma_data; ^ sound/soc/codecs/hdmi-codec.c:745:5: note: cf is overwritten cf = dai->playback_dma_data; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 422539f933de..83e74ddccf59 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -735,7 +735,7 @@ static int hdmi_codec_set_jack(struct snd_soc_component *component, static int hdmi_dai_spdif_probe(struct snd_soc_dai *dai) { - struct hdmi_codec_daifmt *cf = dai->playback_dma_data; + struct hdmi_codec_daifmt *cf; int ret; ret = hdmi_dai_probe(dai); From 9ad869fee5c598d914fa5cf8fb26f5e106e90956 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:34 -0600 Subject: [PATCH 0282/1091] ASoC: hdmi-codec: remove unused spk_mask member fix cppcheck warning: sound/soc/codecs/hdmi-codec.c:25:16: style: struct member 'hdmi_codec_channel_map_table::spk_mask' is never used. [unusedStructMember] unsigned long spk_mask; /* speaker position bit mask */ ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/hdmi-codec.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/hdmi-codec.c b/sound/soc/codecs/hdmi-codec.c index 83e74ddccf59..1567ba196ab9 100644 --- a/sound/soc/codecs/hdmi-codec.c +++ b/sound/soc/codecs/hdmi-codec.c @@ -22,7 +22,6 @@ struct hdmi_codec_channel_map_table { unsigned char map; /* ALSA API channel map position */ - unsigned long spk_mask; /* speaker position bit mask */ }; /* From 226a783f3dcf7f565c173627d565135424ee0be9 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:35 -0600 Subject: [PATCH 0283/1091] ASoC: max98090: remove useless assignment cppcheck warning: sound/soc/codecs/max98090.c:1835:16: style: Variable 'test_diff' is assigned a value that is never used. [unreadVariable] int test_diff = INT_MAX; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98090.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/max98090.c b/sound/soc/codecs/max98090.c index 06276ff5f8a3..bc30a1dc7530 100644 --- a/sound/soc/codecs/max98090.c +++ b/sound/soc/codecs/max98090.c @@ -1832,7 +1832,7 @@ static const struct dmic_table dmic_table[] = { /* One for each pclk freq. */ static int max98090_find_divisor(int target_freq, int pclk) { int current_diff = INT_MAX; - int test_diff = INT_MAX; + int test_diff; int divisor_index = 0; int i; From 2b5e8cd53ffad8c586d8a9d47087fdb058a21287 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:36 -0600 Subject: [PATCH 0284/1091] ASoC: mt6358: remove useless initializations cppcheck warnings: sound/soc/codecs/mt6358.c:334:19: style: Variable 'stage' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ sound/soc/codecs/mt6358.c:350:19: style: Variable 'stage' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ 185/930 files checked 25% done Checking sound/soc/codecs/mt6359.c ... sound/soc/codecs/mt6359.c:274:8: style: Variable 'i' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ sound/soc/codecs/mt6359.c:274:19: style: Variable 'stage' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6358.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/mt6358.c b/sound/soc/codecs/mt6358.c index 1f39d5998cf6..9b263a9a669d 100644 --- a/sound/soc/codecs/mt6358.c +++ b/sound/soc/codecs/mt6358.c @@ -331,7 +331,7 @@ static void hp_zcd_disable(struct mt6358_priv *priv) static void hp_main_output_ramp(struct mt6358_priv *priv, bool up) { - int i = 0, stage = 0; + int i, stage; int target = 7; /* Enable/Reduce HPL/R main output stage step by step */ @@ -347,7 +347,7 @@ static void hp_main_output_ramp(struct mt6358_priv *priv, bool up) static void hp_aux_feedback_loop_gain_ramp(struct mt6358_priv *priv, bool up) { - int i = 0, stage = 0; + int i, stage; /* Reduce HP aux feedback loop gain step by step */ for (i = 0; i <= 0xf; i++) { From d068ab4eab0de3224b32ac37234d4d33452d5b01 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:37 -0600 Subject: [PATCH 0285/1091] ASoC: mt6359: remove useless assignment cppcheck warning: sound/soc/codecs/mt6359.c:242:19: style: Variable 'stage' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ sound/soc/codecs/mt6359.c:260:19: style: Variable 'stage' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ sound/soc/codecs/mt6359.c:274:8: style: Variable 'i' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ sound/soc/codecs/mt6359.c:274:19: style: Variable 'stage' is assigned a value that is never used. [unreadVariable] int i = 0, stage = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/mt6359.c b/sound/soc/codecs/mt6359.c index 6f4b1da52082..b909b36582b7 100644 --- a/sound/soc/codecs/mt6359.c +++ b/sound/soc/codecs/mt6359.c @@ -239,7 +239,7 @@ static void zcd_disable(struct mt6359_priv *priv) static void hp_main_output_ramp(struct mt6359_priv *priv, bool up) { - int i = 0, stage = 0; + int i, stage; int target = 7; /* Enable/Reduce HPL/R main output stage step by step */ @@ -257,7 +257,7 @@ static void hp_main_output_ramp(struct mt6359_priv *priv, bool up) static void hp_aux_feedback_loop_gain_ramp(struct mt6359_priv *priv, bool up) { - int i = 0, stage = 0; + int i, stage; int target = 0xf; /* Enable/Reduce HP aux feedback loop gain step by step */ From a3966b254c481ee1890f75d809a52e5aa358c4b1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:38 -0600 Subject: [PATCH 0286/1091] ASoC: nau8825: remove useless assignment cppcheck warning: sound/soc/codecs/nau8825.c:2113:10: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int ret = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/nau8825.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/nau8825.c b/sound/soc/codecs/nau8825.c index e19db30c457b..67de0e49ccf4 100644 --- a/sound/soc/codecs/nau8825.c +++ b/sound/soc/codecs/nau8825.c @@ -2111,7 +2111,7 @@ static int nau8825_set_pll(struct snd_soc_component *component, int pll_id, int static int nau8825_mclk_prepare(struct nau8825 *nau8825, unsigned int freq) { - int ret = 0; + int ret; nau8825->mclk = devm_clk_get(nau8825->dev, "mclk"); if (IS_ERR(nau8825->mclk)) { From f10280d5c59b8d83ae9e9e2307075cc7ad32a6b8 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:39 -0600 Subject: [PATCH 0287/1091] ASoC: pcm1681: remove useless assignment cppcheck warning: sound/soc/codecs/pcm1681.c:87:8: style: Variable 'i' is assigned a value that is never used. [unreadVariable] int i = 0, val = -1, enable = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/pcm1681.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/pcm1681.c b/sound/soc/codecs/pcm1681.c index 07ed8fded471..5b78e9299c95 100644 --- a/sound/soc/codecs/pcm1681.c +++ b/sound/soc/codecs/pcm1681.c @@ -84,7 +84,7 @@ static const int pcm1681_deemph[] = { 44100, 48000, 32000 }; static int pcm1681_set_deemph(struct snd_soc_component *component) { struct pcm1681_private *priv = snd_soc_component_get_drvdata(component); - int i = 0, val = -1, enable = 0; + int i, val = -1, enable = 0; if (priv->deemph) { for (i = 0; i < ARRAY_SIZE(pcm1681_deemph); i++) { From 17d74e68e9765d9549acf1c36caa8b7559dc99ce Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:40 -0600 Subject: [PATCH 0288/1091] ASoC: sigmadsp: align function prototype cppcheck warning: sound/soc/codecs/sigmadsp.c:736:60: style:inconclusive: Function 'sigmadsp_setup' argument 2 names different: declaration 'rate' definition 'samplerate'. [funcArgNamesDifferent] int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int samplerate) ^ sound/soc/codecs/sigmadsp.h:62:60: note: Function 'sigmadsp_setup' argument 2 names different: declaration 'rate' definition 'samplerate'. int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int rate); ^ sound/soc/codecs/sigmadsp.c:736:60: note: Function 'sigmadsp_setup' argument 2 names different: declaration 'rate' definition 'samplerate'. int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int samplerate) ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/sigmadsp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/sigmadsp.h b/sound/soc/codecs/sigmadsp.h index e3c9656e006d..d63b8c366efb 100644 --- a/sound/soc/codecs/sigmadsp.h +++ b/sound/soc/codecs/sigmadsp.h @@ -59,7 +59,7 @@ struct sigmadsp *devm_sigmadsp_init_i2c(struct i2c_client *client, int sigmadsp_attach(struct sigmadsp *sigmadsp, struct snd_soc_component *component); -int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int rate); +int sigmadsp_setup(struct sigmadsp *sigmadsp, unsigned int samplerate); void sigmadsp_reset(struct sigmadsp *sigmadsp); #endif From 02a70d7f26e7a3d87c9a5af39ca399b52a451a1a Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:41 -0600 Subject: [PATCH 0289/1091] ASoC: sti-sas: remove unused struct members cppcheck warnings: sound/soc/codecs/sti-sas.c:54:25: style: struct member 'sti_dac_audio::field' is never used. [unusedStructMember] struct regmap_field **field; ^ sound/soc/codecs/sti-sas.c:55:24: style: struct member 'sti_dac_audio::rst' is never used. [unusedStructMember] struct reset_control *rst; ^ sound/soc/codecs/sti-sas.c:61:25: style: struct member 'sti_spdif_audio::field' is never used. [unusedStructMember] struct regmap_field **field; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-19-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/sti-sas.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/sound/soc/codecs/sti-sas.c b/sound/soc/codecs/sti-sas.c index ec9933b054ad..ffdf7e559515 100644 --- a/sound/soc/codecs/sti-sas.c +++ b/sound/soc/codecs/sti-sas.c @@ -51,14 +51,11 @@ static const struct reg_default stih407_sas_reg_defaults[] = { struct sti_dac_audio { struct regmap *regmap; struct regmap *virt_regmap; - struct regmap_field **field; - struct reset_control *rst; int mclk; }; struct sti_spdif_audio { struct regmap *regmap; - struct regmap_field **field; int mclk; }; From e83c47861c266f704d2344f51031ee67a93309ab Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:42 -0600 Subject: [PATCH 0290/1091] ASoC: tas2562: remove useless assignment cppcheck throws a warning: sound/soc/codecs/tas2562.c:203:4: style: Assignment of function parameter has no effect outside the function. [uselessAssignmentArg] tx_mask &= ~(1 << right_slot); ^ This assignment seems to come from a copy/paste but the value is indeed not used. Let's remove it. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-20-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2562.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index 19965fabe949..ba23f9f07f04 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -200,7 +200,6 @@ static int tas2562_set_dai_tdm_slot(struct snd_soc_dai *dai, right_slot = left_slot; } else { right_slot = __ffs(tx_mask); - tx_mask &= ~(1 << right_slot); } } From 2e40b21cd4f697a761f1c5e4f08aac1a5c6c6018 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:43 -0600 Subject: [PATCH 0291/1091] ASoC: tas2562: remove warning on return value cppcheck warning: sound/soc/codecs/tas2562.c:530:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/codecs/tas2562.c:525:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/codecs/tas2562.c:530:9: note: Returning identical expression 'ret' return ret; ^ Fix with return 0 Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-21-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2562.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2562.c b/sound/soc/codecs/tas2562.c index ba23f9f07f04..10302552195e 100644 --- a/sound/soc/codecs/tas2562.c +++ b/sound/soc/codecs/tas2562.c @@ -526,7 +526,7 @@ static int tas2562_volume_control_put(struct snd_kcontrol *kcontrol, tas2562->volume_lvl = ucontrol->value.integer.value[0]; - return ret; + return 0; } /* Digital Volume Control. From 0 dB to -110 dB in 1 dB steps */ From ffab1215bdbea7358051f8dd87b1240e4c6d56e6 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:44 -0600 Subject: [PATCH 0292/1091] ASoC: tas2770: remove useless initialization cppcheck warning: sound/soc/codecs/tas2770.c:109:10: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int ret = 0; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-22-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 15fca5109e14..781bf9cc4faa 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -106,7 +106,7 @@ static int tas2770_codec_suspend(struct snd_soc_component *component) static int tas2770_codec_resume(struct snd_soc_component *component) { struct tas2770_priv *tas2770 = snd_soc_component_get_drvdata(component); - int ret = 0; + int ret; if (tas2770->sdz_gpio) { gpiod_set_value_cansleep(tas2770->sdz_gpio, 1); From 39e69cef0aa9f6897161a11ed84362f5805c43fd Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:45 -0600 Subject: [PATCH 0293/1091] ASoC: tlv320dac33: clarify expression cppcheck warning: sound/soc/codecs/tlv320dac33.c:1074:43: style: Clarify calculation precedence for '%' and '?'. [clarifyCalculation] (dac33->alarm_threshold % period_size ? ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-23-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320dac33.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tlv320dac33.c b/sound/soc/codecs/tlv320dac33.c index d905e03aaec7..48572d66cb3b 100644 --- a/sound/soc/codecs/tlv320dac33.c +++ b/sound/soc/codecs/tlv320dac33.c @@ -1071,7 +1071,7 @@ static void dac33_calculate_times(struct snd_pcm_substream *substream, */ dac33->nsample = period_size * ((dac33->alarm_threshold / period_size) + - (dac33->alarm_threshold % period_size ? + ((dac33->alarm_threshold % period_size) ? 1 : 0)); else if (period_size > nsample_limit) dac33->nsample = nsample_limit; From a2cc1568dc50020a807c94bd14a053dd54e9c35e Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 12 Mar 2021 12:22:46 -0600 Subject: [PATCH 0294/1091] ASoC: tscs454: remove useless test on PLL disable cppcheck warning: sound/soc/codecs/tscs454.c:730:37: style: Same value in both branches of ternary operator. [duplicateValueTernary] val = pll1 ? FV_PLL1CLKEN_DISABLE : FV_PLL2CLKEN_DISABLE; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210312182246.5153-24-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/tscs454.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tscs454.c b/sound/soc/codecs/tscs454.c index 1bafc9d1101c..43220bb36701 100644 --- a/sound/soc/codecs/tscs454.c +++ b/sound/soc/codecs/tscs454.c @@ -727,7 +727,12 @@ static int pll_power_event(struct snd_soc_dapm_widget *w, if (enable) val = pll1 ? FV_PLL1CLKEN_ENABLE : FV_PLL2CLKEN_ENABLE; else - val = pll1 ? FV_PLL1CLKEN_DISABLE : FV_PLL2CLKEN_DISABLE; + /* + * FV_PLL1CLKEN_DISABLE and FV_PLL2CLKEN_DISABLE are + * identical zero vzalues, there is no need to test + * the PLL index + */ + val = FV_PLL1CLKEN_DISABLE; ret = snd_soc_component_update_bits(component, R_PLLCTL, msk, val); if (ret < 0) { From bef2897d31b97852d80b38e9376ed5ef3a90b309 Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Sun, 14 Mar 2021 18:39:08 -0700 Subject: [PATCH 0295/1091] ASoC: Intel: Skylake: skl-topology: fix -frame-larger-than sound/soc/intel/skylake/skl-topology.c:3613:13: warning: stack frame size of 1304 bytes in function 'skl_tplg_complete' [-Wframe-larger-than=] struct snd_ctl_elem_value is 1224 bytes in my configuration. Heap allocate it, then free it within the current frame. Suggested-by: Andy Shevchenko Signed-off-by: Nick Desaulniers Link: https://lore.kernel.org/r/20210315013908.217219-1-nick.desaulniers@gmail.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl-topology.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/sound/soc/intel/skylake/skl-topology.c b/sound/soc/intel/skylake/skl-topology.c index b824086203b9..c0fdab39e7c2 100644 --- a/sound/soc/intel/skylake/skl-topology.c +++ b/sound/soc/intel/skylake/skl-topology.c @@ -3613,10 +3613,15 @@ static int skl_manifest_load(struct snd_soc_component *cmpnt, int index, static void skl_tplg_complete(struct snd_soc_component *component) { struct snd_soc_dobj *dobj; - struct snd_soc_acpi_mach *mach = - dev_get_platdata(component->card->dev); + struct snd_soc_acpi_mach *mach; + struct snd_ctl_elem_value *val; int i; + val = kmalloc(sizeof(*val), GFP_KERNEL); + if (!val) + return; + + mach = dev_get_platdata(component->card->dev); list_for_each_entry(dobj, &component->dobj_list, list) { struct snd_kcontrol *kcontrol = dobj->control.kcontrol; struct soc_enum *se; @@ -3632,14 +3637,14 @@ static void skl_tplg_complete(struct snd_soc_component *component) sprintf(chan_text, "c%d", mach->mach_params.dmic_num); for (i = 0; i < se->items; i++) { - struct snd_ctl_elem_value val = {}; - if (strstr(texts[i], chan_text)) { - val.value.enumerated.item[0] = i; - kcontrol->put(kcontrol, &val); + memset(val, 0, sizeof(*val)); + val->value.enumerated.item[0] = i; + kcontrol->put(kcontrol, val); } } } + kfree(val); } static struct snd_soc_tplg_ops skl_tplg_ops = { From 8dd855334736f275e9de71096d816c8d9da46bf7 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Sun, 14 Mar 2021 04:48:50 +0530 Subject: [PATCH 0296/1091] ASoC: Fix a typo in the file rt5682.txt s/drving/driving/ Signed-off-by: Bhaskar Chowdhury Acked-by: Randy Dunlap Link: https://lore.kernel.org/r/20210313231850.17278-1-unixbhaskar@gmail.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt5682.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/rt5682.txt b/Documentation/devicetree/bindings/sound/rt5682.txt index 9c5fadb6ac82..cd8c53d8497e 100644 --- a/Documentation/devicetree/bindings/sound/rt5682.txt +++ b/Documentation/devicetree/bindings/sound/rt5682.txt @@ -44,7 +44,7 @@ Optional properties: - realtek,dmic-delay-ms : Set the delay time (ms) for the requirement of the particular DMIC. -- realtek,dmic-clk-driving-high : Set the high drving of the DMIC clock out. +- realtek,dmic-clk-driving-high : Set the high driving of the DMIC clock out. Pins on the device (for linking into audio routes) for RT5682: From 7ec79d3850d0cb6dc52e6aa472886ab3adf15863 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Thu, 11 Mar 2021 10:58:09 +0800 Subject: [PATCH 0297/1091] ASoC: rt1019: add rt1019 amplifier driver This is initial amplifier driver for rt1019. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20210311025809.31852-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/rt1019.yaml | 33 + sound/soc/codecs/Kconfig | 7 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/rt1019.c | 940 ++++++++++++++++++ sound/soc/codecs/rt1019.h | 320 ++++++ 5 files changed, 1302 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/rt1019.yaml create mode 100644 sound/soc/codecs/rt1019.c create mode 100644 sound/soc/codecs/rt1019.h diff --git a/Documentation/devicetree/bindings/sound/rt1019.yaml b/Documentation/devicetree/bindings/sound/rt1019.yaml new file mode 100644 index 000000000000..c24c29eafa54 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/rt1019.yaml @@ -0,0 +1,33 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/rt1019.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: RT1019 Mono Class-D Audio Amplifier + +maintainers: + - jack.yu@realtek.com + +properties: + compatible: + const: realtek,rt1019 + + reg: + maxItems: 1 + description: I2C address of the device. + +required: + - compatible + - reg + +additionalProperties: false + +examples: + - | + i2c { + rt1019: codec@28 { + compatible = "realtek,rt1019"; + reg = <0x28>; + }; + }; diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6ce74c99a305..4ab34bca71aa 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -161,6 +161,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_RT1011 imply SND_SOC_RT1015 imply SND_SOC_RT1015P + imply SND_SOC_RT1019 imply SND_SOC_RT1305 imply SND_SOC_RT1308 imply SND_SOC_RT5514 @@ -1079,6 +1080,7 @@ config SND_SOC_RL6231 default y if SND_SOC_RT1011=y default y if SND_SOC_RT1015=y default y if SND_SOC_RT1015P=y + default y if SND_SOC_RT1019=y default y if SND_SOC_RT1305=y default y if SND_SOC_RT1308=y default m if SND_SOC_RT5514=m @@ -1097,6 +1099,7 @@ config SND_SOC_RL6231 default m if SND_SOC_RT1011=m default m if SND_SOC_RT1015=m default m if SND_SOC_RT1015P=m + default m if SND_SOC_RT1019=m default m if SND_SOC_RT1305=m default m if SND_SOC_RT1308=m @@ -1133,6 +1136,10 @@ config SND_SOC_RT1015P tristate depends on GPIOLIB +config SND_SOC_RT1019 + tristate + depends on I2C + config SND_SOC_RT1305 tristate depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index dcc2f757bb82..edff5c5b92d3 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -170,6 +170,7 @@ snd-soc-rl6347a-objs := rl6347a.o snd-soc-rt1011-objs := rt1011.o snd-soc-rt1015-objs := rt1015.o snd-soc-rt1015p-objs := rt1015p.o +snd-soc-rt1019-objs := rt1019.o snd-soc-rt1305-objs := rt1305.o snd-soc-rt1308-objs := rt1308.o snd-soc-rt1308-sdw-objs := rt1308-sdw.o @@ -487,6 +488,7 @@ obj-$(CONFIG_SND_SOC_RL6347A) += snd-soc-rl6347a.o obj-$(CONFIG_SND_SOC_RT1011) += snd-soc-rt1011.o obj-$(CONFIG_SND_SOC_RT1015) += snd-soc-rt1015.o obj-$(CONFIG_SND_SOC_RT1015P) += snd-soc-rt1015p.o +obj-$(CONFIG_SND_SOC_RT1019) += snd-soc-rt1019.o obj-$(CONFIG_SND_SOC_RT1305) += snd-soc-rt1305.o obj-$(CONFIG_SND_SOC_RT1308) += snd-soc-rt1308.o obj-$(CONFIG_SND_SOC_RT1308_SDW) += snd-soc-rt1308-sdw.o diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c new file mode 100644 index 000000000000..fb275686a00f --- /dev/null +++ b/sound/soc/codecs/rt1019.c @@ -0,0 +1,940 @@ +// SPDX-License-Identifier: GPL-2.0-only +// +// rt1019.c -- RT1019 ALSA SoC audio amplifier driver +// Author: Jack Yu +// +// Copyright(c) 2021 Realtek Semiconductor Corp. +// +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "rl6231.h" +#include "rt1019.h" + +static const struct reg_default rt1019_reg[] = { + { 0x0000, 0x00 }, + { 0x0002, 0x55 }, + { 0x0003, 0x55 }, + { 0x0005, 0x54 }, + { 0x0006, 0x05 }, + { 0x0007, 0x01 }, + { 0x0008, 0x70 }, + { 0x0009, 0x28 }, + { 0x000a, 0x7f }, + { 0x0011, 0x04 }, + { 0x0013, 0x00 }, + { 0x0015, 0x00 }, + { 0x0017, 0x00 }, + { 0x0019, 0x30 }, + { 0x001b, 0x01 }, + { 0x001d, 0x18 }, + { 0x001f, 0x29 }, + { 0x0021, 0x09 }, + { 0x0023, 0x02 }, + { 0x0025, 0x00 }, + { 0x0026, 0x00 }, + { 0x0028, 0x03 }, + { 0x0053, 0x00 }, + { 0x0055, 0x00 }, + { 0x0056, 0x00 }, + { 0x0057, 0x00 }, + { 0x0058, 0x00 }, + { 0x005a, 0x00 }, + { 0x005c, 0x00 }, + { 0x005d, 0x00 }, + { 0x005e, 0x10 }, + { 0x005f, 0xec }, + { 0x0061, 0x10 }, + { 0x0062, 0x19 }, + { 0x0064, 0x00 }, + { 0x0066, 0x08 }, + { 0x0068, 0x00 }, + { 0x006a, 0x00 }, + { 0x006c, 0x00 }, + { 0x006e, 0x00 }, + { 0x0100, 0x80 }, + { 0x0100, 0x51 }, + { 0x0102, 0x23 }, + { 0x0102, 0x0f }, + { 0x0104, 0x6c }, + { 0x0105, 0xec }, + { 0x0106, 0x00 }, + { 0x0107, 0x00 }, + { 0x0108, 0x00 }, + { 0x0200, 0x40 }, + { 0x0201, 0x00 }, + { 0x0202, 0x00 }, + { 0x0203, 0x00 }, + { 0x0301, 0x02 }, + { 0x0302, 0xaa }, + { 0x0303, 0x2a }, + { 0x0304, 0x6a }, + { 0x0306, 0xb0 }, + { 0x0308, 0x48 }, + { 0x030a, 0x0a }, + { 0x030b, 0x4b }, + { 0x030d, 0x7d }, + { 0x030e, 0xef }, + { 0x030f, 0x5a }, + { 0x0311, 0x00 }, + { 0x0312, 0x3e }, + { 0x0313, 0x86 }, + { 0x0315, 0xa8 }, + { 0x0318, 0x1b }, + { 0x031a, 0x3d }, + { 0x031c, 0x40 }, + { 0x031d, 0x40 }, + { 0x031e, 0x30 }, + { 0x031f, 0xbb }, + { 0x0320, 0xa5 }, + { 0x0321, 0xa5 }, + { 0x0323, 0x5a }, + { 0x0324, 0xaa }, + { 0x0325, 0x80 }, + { 0x0326, 0xaa }, + { 0x0327, 0x66 }, + { 0x0328, 0x94 }, + { 0x0329, 0x00 }, + { 0x0330, 0x00 }, + { 0x0331, 0x30 }, + { 0x0332, 0x05 }, + { 0x0400, 0x03 }, + { 0x0401, 0x02 }, + { 0x0402, 0x01 }, + { 0x0403, 0x23 }, + { 0x0404, 0x45 }, + { 0x0405, 0x67 }, + { 0x0500, 0x80 }, + { 0x0501, 0x00 }, + { 0x0502, 0x00 }, + { 0x0503, 0x00 }, + { 0x0504, 0xff }, + { 0x0505, 0x24 }, + { 0x0600, 0x75 }, + { 0x0601, 0x41 }, + { 0x0602, 0x60 }, + { 0x0603, 0x7f }, + { 0x0604, 0x65 }, + { 0x0605, 0x43 }, + { 0x0606, 0x00 }, + { 0x0607, 0x00 }, + { 0x0608, 0x00 }, + { 0x0609, 0x00 }, + { 0x060a, 0x00 }, + { 0x060b, 0x00 }, + { 0x060c, 0x00 }, + { 0x060d, 0x00 }, + { 0x060e, 0x00 }, + { 0x060f, 0x00 }, + { 0x0700, 0x15 }, + { 0x0701, 0xc8 }, + { 0x0704, 0x02 }, + { 0x0705, 0x00 }, + { 0x0706, 0x00 }, + { 0x0707, 0x80 }, + { 0x0708, 0x08 }, + { 0x0709, 0x00 }, + { 0x0800, 0x00 }, + { 0x0801, 0x00 }, + { 0x0802, 0x09 }, + { 0x0803, 0x00 }, + { 0x0900, 0x87 }, + { 0x0a01, 0x99 }, + { 0x0a02, 0x40 }, + { 0x0a03, 0x10 }, + { 0x0b00, 0x50 }, + { 0x0b01, 0xc3 }, + { 0x0c00, 0x84 }, + { 0x0c01, 0x00 }, + { 0x0c02, 0xbb }, + { 0x0c03, 0x80 }, + { 0x0c04, 0x10 }, + { 0x0c05, 0x30 }, + { 0x0c06, 0x00 }, + { 0x0d00, 0x80 }, + { 0x0d01, 0xbb }, + { 0x0d02, 0x80 }, + { 0x0d03, 0x00 }, + { 0x0d04, 0x00 }, + { 0x0d05, 0x00 }, + { 0x0e00, 0x80 }, + { 0x0e01, 0xbb }, + { 0x0e02, 0x80 }, + { 0x0e03, 0x00 }, + { 0x0e04, 0x10 }, + { 0x0e05, 0x30 }, + { 0x0f00, 0x80 }, + { 0x0f01, 0xbb }, + { 0x0f02, 0x80 }, + { 0x0f03, 0x00 }, + { 0x0f04, 0x10 }, + { 0x0f05, 0x30 }, + { 0x0f06, 0x88 }, + { 0x0f07, 0x88 }, + { 0x0f08, 0x00 }, + { 0x0f09, 0x00 }, +}; + +static bool rt1019_volatile_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1019_PWR_STRP_1: + case RT1019_PWR_STRP_2: + case RT1019_SIL_DET_GAT: + case RT1019_PHASE_SYNC: + case RT1019_STAT_MACH_2: + case RT1019_FS_DET_1: + case RT1019_FS_DET_2: + case RT1019_FS_DET_3: + case RT1019_FS_DET_4: + case RT1019_FS_DET_5: + case RT1019_FS_DET_6: + case RT1019_FS_DET_7: + case RT1019_ANA_READ: + case RT1019_VER_ID: + case RT1019_CUSTOM_ID: + case RT1019_VEND_ID_1: + case RT1019_VEND_ID_2: + case RT1019_DEV_ID_1: + case RT1019_DEV_ID_2: + case RT1019_CAL_TOP_3: + case RT1019_CAL_TOP_7: + case RT1019_CAL_TOP_17: + case RT1019_CAL_TOP_18: + case RT1019_CAL_TOP_19: + case RT1019_CAL_TOP_20: + case RT1019_CAL_TOP_21: + case RT1019_CAL_TOP_22: + case RT1019_MDRE_CTRL_2: + case RT1019_MDRE_CTRL_3: + case RT1019_MDRE_CTRL_4: + case RT1019_SIL_DET_2: + case RT1019_PWM_DC_DET_1: + case RT1019_PMC_8: + case RT1019_PMC_9: + case RT1019_SPKDRC_7: + case RT1019_HALF_FREQ_7: + case RT1019_CUR_CTRL_11: + case RT1019_CUR_CTRL_12: + case RT1019_CUR_CTRL_13: + return true; + + default: + return false; + } +} + +static bool rt1019_readable_register(struct device *dev, unsigned int reg) +{ + switch (reg) { + case RT1019_RESET: + case RT1019_PAD_DRV_1: + case RT1019_PAD_DRV_2: + case RT1019_PAD_PULL_1: + case RT1019_PAD_PULL_2: + case RT1019_PAD_PULL_3: + case RT1019_I2C_CTRL_1: + case RT1019_I2C_CTRL_2: + case RT1019_I2C_CTRL_3: + case RT1019_IDS_CTRL: + case RT1019_ASEL_CTRL: + case RT1019_PLL_RESET: + case RT1019_PWR_STRP_1: + case RT1019_PWR_STRP_2: + case RT1019_BEEP_TONE: + case RT1019_SIL_DET_GAT: + case RT1019_CLASSD_TIME: + case RT1019_CLASSD_OCP: + case RT1019_PHASE_SYNC: + case RT1019_STAT_MACH_1: + case RT1019_STAT_MACH_2: + case RT1019_EFF_CTRL: + case RT1019_FS_DET_1: + case RT1019_FS_DET_2: + case RT1019_FS_DET_3: + case RT1019_FS_DET_4: + case RT1019_FS_DET_5: + case RT1019_FS_DET_6: + case RT1019_FS_DET_7: + case RT1019_ANA_CTRL: + case RT1019_DUMMY_A: + case RT1019_DUMMY_B: + case RT1019_DUMMY_C: + case RT1019_DUMMY_D: + case RT1019_ANA_READ: + case RT1019_VER_ID: + case RT1019_CUSTOM_ID: + case RT1019_VEND_ID_1: + case RT1019_VEND_ID_2: + case RT1019_DEV_ID_1: + case RT1019_DEV_ID_2: + case RT1019_TEST_PAD: + case RT1019_SDB_CTRL: + case RT1019_TEST_CTRL_1: + case RT1019_TEST_CTRL_2: + case RT1019_TEST_CTRL_3: + case RT1019_SCAN_MODE: + case RT1019_CLK_TREE_1: + case RT1019_CLK_TREE_2: + case RT1019_CLK_TREE_3: + case RT1019_CLK_TREE_4: + case RT1019_CLK_TREE_5: + case RT1019_CLK_TREE_6: + case RT1019_CLK_TREE_7: + case RT1019_CLK_TREE_8: + case RT1019_CLK_TREE_9: + case RT1019_ASRC_1: + case RT1019_ASRC_2: + case RT1019_ASRC_3: + case RT1019_ASRC_4: + case RT1019_SYS_CLK: + case RT1019_BIAS_CUR_1: + case RT1019_BIAS_CUR_2: + case RT1019_BIAS_CUR_3: + case RT1019_BIAS_CUR_4: + case RT1019_CHOP_CLK_DAC: + case RT1019_CHOP_CLK_ADC: + case RT1019_LDO_CTRL_1: + case RT1019_LDO_CTRL_2: + case RT1019_PM_ANA_1: + case RT1019_PM_ANA_2: + case RT1019_PM_ANA_3: + case RT1019_PLL_1: + case RT1019_PLL_2: + case RT1019_PLL_3: + case RT1019_PLL_INT_1: + case RT1019_PLL_INT_3: + case RT1019_MIXER: + case RT1019_CLD_OUT_1: + case RT1019_CLD_OUT_2: + case RT1019_CLD_OUT_3: + case RT1019_CLD_OUT_4: + case RT1019_CLD_OUT_5: + case RT1019_CLD_OUT_6: + case RT1019_CLS_INT_REG_1: + case RT1019_CLS_INT_REG_2: + case RT1019_CLS_INT_REG_3: + case RT1019_CLS_INT_REG_4: + case RT1019_CLS_INT_REG_5: + case RT1019_CLS_INT_REG_6: + case RT1019_CLS_INT_REG_7: + case RT1019_CLS_INT_REG_8: + case RT1019_CLS_INT_REG_9: + case RT1019_CLS_INT_REG_10: + case RT1019_TDM_1: + case RT1019_TDM_2: + case RT1019_TDM_3: + case RT1019_TDM_4: + case RT1019_TDM_5: + case RT1019_TDM_6: + case RT1019_DVOL_1: + case RT1019_DVOL_2: + case RT1019_DVOL_3: + case RT1019_DVOL_4: + case RT1019_DMIX_MONO_1: + case RT1019_DMIX_MONO_2: + case RT1019_CAL_TOP_1: + case RT1019_CAL_TOP_2: + case RT1019_CAL_TOP_3: + case RT1019_CAL_TOP_4: + case RT1019_CAL_TOP_5: + case RT1019_CAL_TOP_6: + case RT1019_CAL_TOP_7: + case RT1019_CAL_TOP_8: + case RT1019_CAL_TOP_9: + case RT1019_CAL_TOP_10: + case RT1019_CAL_TOP_11: + case RT1019_CAL_TOP_12: + case RT1019_CAL_TOP_13: + case RT1019_CAL_TOP_14: + case RT1019_CAL_TOP_15: + case RT1019_CAL_TOP_16: + case RT1019_CAL_TOP_17: + case RT1019_CAL_TOP_18: + case RT1019_CAL_TOP_19: + case RT1019_CAL_TOP_20: + case RT1019_CAL_TOP_21: + case RT1019_CAL_TOP_22: + case RT1019_MDRE_CTRL_1: + case RT1019_MDRE_CTRL_2: + case RT1019_MDRE_CTRL_3: + case RT1019_MDRE_CTRL_4: + case RT1019_MDRE_CTRL_5: + case RT1019_MDRE_CTRL_6: + case RT1019_MDRE_CTRL_7: + case RT1019_MDRE_CTRL_8: + case RT1019_MDRE_CTRL_9: + case RT1019_MDRE_CTRL_10: + case RT1019_SCC_CTRL_1: + case RT1019_SCC_CTRL_2: + case RT1019_SCC_CTRL_3: + case RT1019_SCC_DUMMY: + case RT1019_SIL_DET_1: + case RT1019_SIL_DET_2: + case RT1019_PWM_DC_DET_1: + case RT1019_PWM_DC_DET_2: + case RT1019_PWM_DC_DET_3: + case RT1019_PWM_DC_DET_4: + case RT1019_BEEP_1: + case RT1019_BEEP_2: + case RT1019_PMC_1: + case RT1019_PMC_2: + case RT1019_PMC_3: + case RT1019_PMC_4: + case RT1019_PMC_5: + case RT1019_PMC_6: + case RT1019_PMC_7: + case RT1019_PMC_8: + case RT1019_PMC_9: + case RT1019_SPKDRC_1: + case RT1019_SPKDRC_2: + case RT1019_SPKDRC_3: + case RT1019_SPKDRC_4: + case RT1019_SPKDRC_5: + case RT1019_SPKDRC_6: + case RT1019_SPKDRC_7: + case RT1019_HALF_FREQ_1: + case RT1019_HALF_FREQ_2: + case RT1019_HALF_FREQ_3: + case RT1019_HALF_FREQ_4: + case RT1019_HALF_FREQ_5: + case RT1019_HALF_FREQ_6: + case RT1019_HALF_FREQ_7: + case RT1019_CUR_CTRL_1: + case RT1019_CUR_CTRL_2: + case RT1019_CUR_CTRL_3: + case RT1019_CUR_CTRL_4: + case RT1019_CUR_CTRL_5: + case RT1019_CUR_CTRL_6: + case RT1019_CUR_CTRL_7: + case RT1019_CUR_CTRL_8: + case RT1019_CUR_CTRL_9: + case RT1019_CUR_CTRL_10: + case RT1019_CUR_CTRL_11: + case RT1019_CUR_CTRL_12: + case RT1019_CUR_CTRL_13: + return true; + default: + return false; + } +} + +static const DECLARE_TLV_DB_SCALE(dac_vol_tlv, -9525, 75, 0); + +static const char * const rt1019_din_source_select[] = { + "Left", + "Right", + "Left + Right average", +}; + +static SOC_ENUM_SINGLE_DECL(rt1019_mono_lr_sel, RT1019_IDS_CTRL, 0, + rt1019_din_source_select); + +static const struct snd_kcontrol_new rt1019_snd_controls[] = { + SOC_SINGLE_TLV("DAC Playback Volume", RT1019_DMIX_MONO_1, 0, + 127, 0, dac_vol_tlv), + SOC_ENUM("Mono LR Select", rt1019_mono_lr_sel), +}; + +static int r1019_dac_event(struct snd_soc_dapm_widget *w, + struct snd_kcontrol *kcontrol, int event) +{ + struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); + + switch (event) { + case SND_SOC_DAPM_PRE_PMU: + snd_soc_component_write(component, RT1019_SDB_CTRL, 0xb); + break; + case SND_SOC_DAPM_POST_PMD: + snd_soc_component_write(component, RT1019_SDB_CTRL, 0xa); + break; + default: + break; + } + + return 0; +} + +static const struct snd_soc_dapm_widget rt1019_dapm_widgets[] = { + SND_SOC_DAPM_AIF_IN("AIFRX", "AIF Playback", 0, SND_SOC_NOPM, 0, 0), + SND_SOC_DAPM_DAC_E("DAC", NULL, SND_SOC_NOPM, 0, 0, + r1019_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), + SND_SOC_DAPM_OUTPUT("SPO"), +}; + +static const struct snd_soc_dapm_route rt1019_dapm_routes[] = { + { "DAC", NULL, "AIFRX" }, + { "SPO", NULL, "DAC" }, +}; + +static int rt1019_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, struct snd_soc_dai *dai) +{ + struct snd_soc_component *component = dai->component; + struct rt1019_priv *rt1019 = snd_soc_component_get_drvdata(component); + int pre_div, bclk_ms, frame_size; + unsigned int val_len = 0, sys_div_da_filter = 0; + unsigned int sys_dac_osr = 0, sys_fifo_clk = 0; + unsigned int sys_clk_cal = 0, sys_asrc_in = 0; + + rt1019->lrck = params_rate(params); + pre_div = rl6231_get_clk_info(rt1019->sysclk, rt1019->lrck); + if (pre_div < 0) { + dev_err(component->dev, "Unsupported clock setting\n"); + return -EINVAL; + } + + frame_size = snd_soc_params_to_frame_size(params); + if (frame_size < 0) { + dev_err(component->dev, "Unsupported frame size: %d\n", frame_size); + return -EINVAL; + } + + bclk_ms = frame_size > 32; + rt1019->bclk = rt1019->lrck * (32 << bclk_ms); + + dev_dbg(dai->dev, "bclk is %dHz and lrck is %dHz\n", + rt1019->bclk, rt1019->lrck); + dev_dbg(dai->dev, "bclk_ms is %d and pre_div is %d for iis %d\n", + bclk_ms, pre_div, dai->id); + + switch (pre_div) { + case 0: + sys_div_da_filter = RT1019_SYS_DIV_DA_FIL_DIV1; + sys_dac_osr = RT1019_SYS_DA_OSR_DIV1; + sys_asrc_in = RT1019_ASRC_256FS_DIV1; + sys_fifo_clk = RT1019_SEL_FIFO_DIV1; + sys_clk_cal = RT1019_SEL_CLK_CAL_DIV1; + break; + case 1: + sys_div_da_filter = RT1019_SYS_DIV_DA_FIL_DIV2; + sys_dac_osr = RT1019_SYS_DA_OSR_DIV2; + sys_asrc_in = RT1019_ASRC_256FS_DIV2; + sys_fifo_clk = RT1019_SEL_FIFO_DIV2; + sys_clk_cal = RT1019_SEL_CLK_CAL_DIV2; + break; + case 3: + sys_div_da_filter = RT1019_SYS_DIV_DA_FIL_DIV4; + sys_dac_osr = RT1019_SYS_DA_OSR_DIV4; + sys_asrc_in = RT1019_ASRC_256FS_DIV4; + sys_fifo_clk = RT1019_SEL_FIFO_DIV4; + sys_clk_cal = RT1019_SEL_CLK_CAL_DIV4; + break; + default: + return -EINVAL; + } + + switch (params_width(params)) { + case 16: + break; + case 20: + val_len = RT1019_I2S_DL_20; + break; + case 24: + val_len = RT1019_I2S_DL_24; + break; + case 32: + val_len = RT1019_I2S_DL_32; + break; + case 8: + val_len = RT1019_I2S_DL_8; + break; + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT1019_TDM_2, RT1019_I2S_DL_MASK, + val_len); + snd_soc_component_update_bits(component, RT1019_CLK_TREE_1, + RT1019_SEL_FIFO_MASK, sys_fifo_clk); + snd_soc_component_update_bits(component, RT1019_CLK_TREE_2, + RT1019_SYS_DIV_DA_FIL_MASK | RT1019_SYS_DA_OSR_MASK | + RT1019_ASRC_256FS_MASK, sys_div_da_filter | sys_dac_osr | + sys_asrc_in); + snd_soc_component_update_bits(component, RT1019_CLK_TREE_3, + RT1019_SEL_CLK_CAL_MASK, sys_clk_cal); + + return 0; +} + +static int rt1019_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) +{ + struct snd_soc_component *component = dai->component; + unsigned int reg_val = 0, reg_val2 = 0; + + switch (fmt & SND_SOC_DAIFMT_INV_MASK) { + case SND_SOC_DAIFMT_NB_NF: + break; + case SND_SOC_DAIFMT_IB_NF: + reg_val2 |= RT1019_TDM_BCLK_INV; + break; + default: + return -EINVAL; + } + + switch (fmt & SND_SOC_DAIFMT_FORMAT_MASK) { + case SND_SOC_DAIFMT_I2S: + break; + + case SND_SOC_DAIFMT_LEFT_J: + reg_val |= RT1019_I2S_DF_LEFT; + break; + + case SND_SOC_DAIFMT_DSP_A: + reg_val |= RT1019_I2S_DF_PCM_A_R; + break; + + case SND_SOC_DAIFMT_DSP_B: + reg_val |= RT1019_I2S_DF_PCM_B_R; + break; + + default: + return -EINVAL; + } + + snd_soc_component_update_bits(component, RT1019_TDM_2, + RT1019_I2S_DF_MASK, reg_val); + snd_soc_component_update_bits(component, RT1019_TDM_1, + RT1019_TDM_BCLK_MASK, reg_val2); + + return 0; +} + +static int rt1019_set_dai_sysclk(struct snd_soc_dai *dai, + int clk_id, unsigned int freq, int dir) +{ + struct snd_soc_component *component = dai->component; + struct rt1019_priv *rt1019 = snd_soc_component_get_drvdata(component); + unsigned int reg_val = 0; + + if (freq == rt1019->sysclk && clk_id == rt1019->sysclk_src) + return 0; + + switch (clk_id) { + case RT1019_SCLK_S_BCLK: + reg_val |= RT1019_CLK_SYS_PRE_SEL_BCLK; + break; + + case RT1019_SCLK_S_PLL: + reg_val |= RT1019_CLK_SYS_PRE_SEL_PLL; + break; + + default: + dev_err(component->dev, "Invalid clock id (%d)\n", clk_id); + return -EINVAL; + } + + rt1019->sysclk = freq; + rt1019->sysclk_src = clk_id; + + dev_dbg(dai->dev, "Sysclk is %dHz and clock id is %d\n", freq, clk_id); + + snd_soc_component_update_bits(component, RT1019_CLK_TREE_1, + RT1019_CLK_SYS_PRE_SEL_MASK, reg_val); + + return 0; +} + +static int rt1019_set_dai_pll(struct snd_soc_dai *dai, int pll_id, int source, + unsigned int freq_in, unsigned int freq_out) +{ + struct snd_soc_component *component = dai->component; + struct rt1019_priv *rt1019 = snd_soc_component_get_drvdata(component); + struct rl6231_pll_code pll_code; + int ret; + + if (!freq_in || !freq_out) { + dev_dbg(component->dev, "PLL disabled\n"); + rt1019->pll_in = 0; + rt1019->pll_out = 0; + return 0; + } + + if (source == rt1019->pll_src && freq_in == rt1019->pll_in && + freq_out == rt1019->pll_out) + return 0; + + switch (source) { + case RT1019_PLL_S_BCLK: + snd_soc_component_update_bits(component, RT1019_CLK_TREE_1, + RT1019_PLL_SRC_MASK, RT1019_PLL_SRC_SEL_BCLK); + break; + + case RT1019_PLL_S_RC25M: + snd_soc_component_update_bits(component, RT1019_CLK_TREE_1, + RT1019_PLL_SRC_MASK, RT1019_PLL_SRC_SEL_RC); + break; + + default: + dev_err(component->dev, "Unknown PLL source %d\n", source); + return -EINVAL; + } + + ret = rl6231_pll_calc(freq_in, freq_out, &pll_code); + if (ret < 0) { + dev_err(component->dev, "Unsupport input clock %d\n", freq_in); + return ret; + } + + dev_dbg(component->dev, "bypass=%d m=%d n=%d k=%d\n", + pll_code.m_bp, (pll_code.m_bp ? 0 : pll_code.m_code), + pll_code.n_code, pll_code.k_code); + + snd_soc_component_update_bits(component, RT1019_PWR_STRP_2, + RT1019_AUTO_BITS_SEL_MASK | RT1019_AUTO_CLK_SEL_MASK, + RT1019_AUTO_BITS_SEL_MANU | RT1019_AUTO_CLK_SEL_MANU); + snd_soc_component_update_bits(component, RT1019_PLL_1, + RT1019_PLL_M_MASK | RT1019_PLL_M_BP_MASK | RT1019_PLL_Q_8_8_MASK, + (pll_code.m_bp ? 0 : pll_code.m_code) << RT1019_PLL_M_SFT | + pll_code.m_bp << RT1019_PLL_M_BP_SFT | + ((pll_code.n_code >> 8) & RT1019_PLL_Q_8_8_MASK)); + snd_soc_component_update_bits(component, RT1019_PLL_2, + RT1019_PLL_Q_7_0_MASK, pll_code.n_code & RT1019_PLL_Q_7_0_MASK); + snd_soc_component_update_bits(component, RT1019_PLL_3, + RT1019_PLL_K_MASK, pll_code.k_code); + + rt1019->pll_in = freq_in; + rt1019->pll_out = freq_out; + rt1019->pll_src = source; + + return 0; +} + +static int rt1019_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, + unsigned int rx_mask, int slots, int slot_width) +{ + struct snd_soc_component *component = dai->component; + unsigned int val = 0, rx_slotnum; + int ret = 0, first_bit; + + switch (slots) { + case 4: + val |= RT1019_I2S_TX_4CH; + break; + case 6: + val |= RT1019_I2S_TX_6CH; + break; + case 8: + val |= RT1019_I2S_TX_8CH; + break; + case 2: + break; + default: + return -EINVAL; + } + + switch (slot_width) { + case 20: + val |= RT1019_I2S_DL_20; + break; + case 24: + val |= RT1019_I2S_DL_24; + break; + case 32: + val |= RT1019_I2S_DL_32; + break; + case 8: + val |= RT1019_I2S_DL_8; + break; + case 16: + break; + default: + return -EINVAL; + } + + /* Rx slot configuration */ + rx_slotnum = hweight_long(rx_mask); + if (rx_slotnum != 1) { + ret = -EINVAL; + dev_err(component->dev, "too many rx slots or zero slot\n"); + goto _set_tdm_err_; + } + /* This is an assumption that the system sends stereo audio to the + * amplifier typically. And the stereo audio is placed in slot 0/2/4/6 + * as the starting slot. The users could select the channel from + * L/R/L+R by "Mono LR Select" control. + */ + first_bit = __ffs(rx_mask); + switch (first_bit) { + case 0: + case 2: + case 4: + case 6: + snd_soc_component_update_bits(component, + RT1019_TDM_3, + RT1019_TDM_I2S_TX_L_DAC1_1_MASK | + RT1019_TDM_I2S_TX_R_DAC1_1_MASK, + (first_bit << RT1019_TDM_I2S_TX_L_DAC1_1_SFT) | + ((first_bit + 1) << RT1019_TDM_I2S_TX_R_DAC1_1_SFT)); + break; + case 1: + case 3: + case 5: + case 7: + snd_soc_component_update_bits(component, + RT1019_TDM_3, + RT1019_TDM_I2S_TX_L_DAC1_1_MASK | + RT1019_TDM_I2S_TX_R_DAC1_1_MASK, + ((first_bit - 1) << RT1019_TDM_I2S_TX_L_DAC1_1_SFT) | + (first_bit << RT1019_TDM_I2S_TX_R_DAC1_1_SFT)); + break; + default: + ret = -EINVAL; + goto _set_tdm_err_; + } + + snd_soc_component_update_bits(component, RT1019_TDM_2, + RT1019_I2S_CH_TX_MASK | RT1019_I2S_DF_MASK, val); + +_set_tdm_err_: + return ret; +} + +static int rt1019_probe(struct snd_soc_component *component) +{ + struct rt1019_priv *rt1019 = snd_soc_component_get_drvdata(component); + + rt1019->component = component; + snd_soc_component_write(component, RT1019_SDB_CTRL, 0xa); + + return 0; +} + +#define RT1019_STEREO_RATES SNDRV_PCM_RATE_8000_192000 +#define RT1019_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ + SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) + +static struct snd_soc_dai_ops rt1019_aif_dai_ops = { + .hw_params = rt1019_hw_params, + .set_fmt = rt1019_set_dai_fmt, + .set_sysclk = rt1019_set_dai_sysclk, + .set_pll = rt1019_set_dai_pll, + .set_tdm_slot = rt1019_set_tdm_slot, +}; + +static struct snd_soc_dai_driver rt1019_dai[] = { + { + .name = "rt1019-aif", + .id = 0, + .playback = { + .stream_name = "AIF Playback", + .channels_min = 1, + .channels_max = 2, + .rates = RT1019_STEREO_RATES, + .formats = RT1019_FORMATS, + }, + .ops = &rt1019_aif_dai_ops, + } +}; + +static const struct snd_soc_component_driver soc_component_dev_rt1019 = { + .probe = rt1019_probe, + .controls = rt1019_snd_controls, + .num_controls = ARRAY_SIZE(rt1019_snd_controls), + .dapm_widgets = rt1019_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(rt1019_dapm_widgets), + .dapm_routes = rt1019_dapm_routes, + .num_dapm_routes = ARRAY_SIZE(rt1019_dapm_routes), +}; + +static const struct regmap_config rt1019_regmap = { + .reg_bits = 16, + .val_bits = 8, + .use_single_read = true, + .use_single_write = true, + .max_register = RT1019_CUR_CTRL_13, + .volatile_reg = rt1019_volatile_register, + .readable_reg = rt1019_readable_register, + .cache_type = REGCACHE_RBTREE, + .reg_defaults = rt1019_reg, + .num_reg_defaults = ARRAY_SIZE(rt1019_reg), +}; + +static const struct i2c_device_id rt1019_i2c_id[] = { + { "rt1019", 0 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, rt1019_i2c_id); + +static const struct of_device_id rt1019_of_match[] = { + { .compatible = "realtek,rt1019", }, + {}, +}; +MODULE_DEVICE_TABLE(of, rt1019_of_match); + +#ifdef CONFIG_ACPI +static const struct acpi_device_id rt1019_acpi_match[] = { + { "10EC1019", 0}, + { }, +}; +MODULE_DEVICE_TABLE(acpi, rt1019_acpi_match); +#endif + +static int rt1019_i2c_probe(struct i2c_client *i2c, + const struct i2c_device_id *id) +{ + struct rt1019_priv *rt1019; + int ret; + unsigned int val, val2, dev_id; + + rt1019 = devm_kzalloc(&i2c->dev, sizeof(struct rt1019_priv), + GFP_KERNEL); + if (!rt1019) + return -ENOMEM; + + i2c_set_clientdata(i2c, rt1019); + + rt1019->regmap = devm_regmap_init_i2c(i2c, &rt1019_regmap); + if (IS_ERR(rt1019->regmap)) { + ret = PTR_ERR(rt1019->regmap); + dev_err(&i2c->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + + regmap_read(rt1019->regmap, RT1019_DEV_ID_1, &val); + regmap_read(rt1019->regmap, RT1019_DEV_ID_2, &val2); + dev_id = val << 8 | val2; + if (dev_id != RT1019_DEVICE_ID_VAL && dev_id != RT1019_DEVICE_ID_VAL2) { + dev_err(&i2c->dev, + "Device with ID register 0x%x is not rt1019\n", dev_id); + return -ENODEV; + } + + return devm_snd_soc_register_component(&i2c->dev, + &soc_component_dev_rt1019, rt1019_dai, ARRAY_SIZE(rt1019_dai)); +} + +struct i2c_driver rt1019_i2c_driver = { + .driver = { + .name = "rt1019", + .of_match_table = of_match_ptr(rt1019_of_match), + .acpi_match_table = ACPI_PTR(rt1019_acpi_match), + }, + .probe = rt1019_i2c_probe, + .id_table = rt1019_i2c_id, +}; +module_i2c_driver(rt1019_i2c_driver); + +MODULE_DESCRIPTION("ASoC RT1019 driver"); +MODULE_AUTHOR("Jack Yu "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/rt1019.h b/sound/soc/codecs/rt1019.h new file mode 100644 index 000000000000..46973e71c963 --- /dev/null +++ b/sound/soc/codecs/rt1019.h @@ -0,0 +1,320 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * rt1019.h -- RT1019 ALSA SoC audio amplifier driver + * + * Copyright(c) 2021 Realtek Semiconductor Corp. + */ + +#ifndef __RT1019_H__ +#define __RT1019_H__ + +#define RT1019_DEVICE_ID_VAL 0x1019 +#define RT1019_DEVICE_ID_VAL2 0x6731 + +#define RT1019_RESET 0x0000 +#define RT1019_PAD_DRV_1 0x0002 +#define RT1019_PAD_DRV_2 0x0003 +#define RT1019_PAD_PULL_1 0x0005 +#define RT1019_PAD_PULL_2 0x0006 +#define RT1019_PAD_PULL_3 0x0007 +#define RT1019_I2C_CTRL_1 0x0008 +#define RT1019_I2C_CTRL_2 0x0009 +#define RT1019_I2C_CTRL_3 0x000a +#define RT1019_IDS_CTRL 0x0011 +#define RT1019_ASEL_CTRL 0x0013 +#define RT1019_PLL_RESET 0x0015 +#define RT1019_PWR_STRP_1 0x0017 +#define RT1019_PWR_STRP_2 0x0019 +#define RT1019_BEEP_TONE 0x001b +#define RT1019_SIL_DET_GAT 0x001d +#define RT1019_CLASSD_TIME 0x001f +#define RT1019_CLASSD_OCP 0x0021 +#define RT1019_PHASE_SYNC 0x0023 +#define RT1019_STAT_MACH_1 0x0025 +#define RT1019_STAT_MACH_2 0x0026 +#define RT1019_EFF_CTRL 0x0028 +#define RT1019_FS_DET_1 0x002a +#define RT1019_FS_DET_2 0x002b +#define RT1019_FS_DET_3 0x002c +#define RT1019_FS_DET_4 0x002d +#define RT1019_FS_DET_5 0x002e +#define RT1019_FS_DET_6 0x002f +#define RT1019_FS_DET_7 0x0030 +#define RT1019_ANA_CTRL 0x0053 +#define RT1019_DUMMY_A 0x0055 +#define RT1019_DUMMY_B 0x0056 +#define RT1019_DUMMY_C 0x0057 +#define RT1019_DUMMY_D 0x0058 +#define RT1019_ANA_READ 0x005a +#define RT1019_VER_ID 0x005c +#define RT1019_CUSTOM_ID 0x005d +#define RT1019_VEND_ID_1 0x005e +#define RT1019_VEND_ID_2 0x005f +#define RT1019_DEV_ID_1 0x0061 +#define RT1019_DEV_ID_2 0x0062 +#define RT1019_TEST_PAD 0x0064 +#define RT1019_SDB_CTRL 0x0066 +#define RT1019_TEST_CTRL_1 0x0068 +#define RT1019_TEST_CTRL_2 0x006a +#define RT1019_TEST_CTRL_3 0x006c +#define RT1019_SCAN_MODE 0x006e +#define RT1019_CLK_TREE_1 0x0100 +#define RT1019_CLK_TREE_2 0x0101 +#define RT1019_CLK_TREE_3 0x0102 +#define RT1019_CLK_TREE_4 0x0103 +#define RT1019_CLK_TREE_5 0x0104 +#define RT1019_CLK_TREE_6 0x0105 +#define RT1019_CLK_TREE_7 0x0106 +#define RT1019_CLK_TREE_8 0x0107 +#define RT1019_CLK_TREE_9 0x0108 +#define RT1019_ASRC_1 0x0200 +#define RT1019_ASRC_2 0x0201 +#define RT1019_ASRC_3 0x0202 +#define RT1019_ASRC_4 0x0203 +#define RT1019_SYS_CLK 0x0300 +#define RT1019_BIAS_CUR_1 0x0301 +#define RT1019_BIAS_CUR_2 0x0302 +#define RT1019_BIAS_CUR_3 0x0303 +#define RT1019_BIAS_CUR_4 0x0304 +#define RT1019_CHOP_CLK_DAC 0x0306 +#define RT1019_CHOP_CLK_ADC 0x0308 +#define RT1019_LDO_CTRL_1 0x030a +#define RT1019_LDO_CTRL_2 0x030b +#define RT1019_PM_ANA_1 0x030d +#define RT1019_PM_ANA_2 0x030e +#define RT1019_PM_ANA_3 0x030f +#define RT1019_PLL_1 0x0311 +#define RT1019_PLL_2 0x0312 +#define RT1019_PLL_3 0x0313 +#define RT1019_PLL_INT_1 0x0315 +#define RT1019_PLL_INT_3 0x0318 +#define RT1019_MIXER 0x031a +#define RT1019_CLD_OUT_1 0x031c +#define RT1019_CLD_OUT_2 0x031d +#define RT1019_CLD_OUT_3 0x031e +#define RT1019_CLD_OUT_4 0x031f +#define RT1019_CLD_OUT_5 0x0320 +#define RT1019_CLD_OUT_6 0x0321 +#define RT1019_CLS_INT_REG_1 0x0323 +#define RT1019_CLS_INT_REG_2 0x0324 +#define RT1019_CLS_INT_REG_3 0x0325 +#define RT1019_CLS_INT_REG_4 0x0326 +#define RT1019_CLS_INT_REG_5 0x0327 +#define RT1019_CLS_INT_REG_6 0x0328 +#define RT1019_CLS_INT_REG_7 0x0329 +#define RT1019_CLS_INT_REG_8 0x0330 +#define RT1019_CLS_INT_REG_9 0x0331 +#define RT1019_CLS_INT_REG_10 0x0332 +#define RT1019_TDM_1 0x0400 +#define RT1019_TDM_2 0x0401 +#define RT1019_TDM_3 0x0402 +#define RT1019_TDM_4 0x0403 +#define RT1019_TDM_5 0x0404 +#define RT1019_TDM_6 0x0405 +#define RT1019_DVOL_1 0x0500 +#define RT1019_DVOL_2 0x0501 +#define RT1019_DVOL_3 0x0502 +#define RT1019_DVOL_4 0x0503 +#define RT1019_DMIX_MONO_1 0x0504 +#define RT1019_DMIX_MONO_2 0x0505 +#define RT1019_CAL_TOP_1 0x0600 +#define RT1019_CAL_TOP_2 0x0601 +#define RT1019_CAL_TOP_3 0x0602 +#define RT1019_CAL_TOP_4 0x0603 +#define RT1019_CAL_TOP_5 0x0604 +#define RT1019_CAL_TOP_6 0x0605 +#define RT1019_CAL_TOP_7 0x0606 +#define RT1019_CAL_TOP_8 0x0607 +#define RT1019_CAL_TOP_9 0x0608 +#define RT1019_CAL_TOP_10 0x0609 +#define RT1019_CAL_TOP_11 0x060a +#define RT1019_CAL_TOP_12 0x060b +#define RT1019_CAL_TOP_13 0x060c +#define RT1019_CAL_TOP_14 0x060d +#define RT1019_CAL_TOP_15 0x060e +#define RT1019_CAL_TOP_16 0x060f +#define RT1019_CAL_TOP_17 0x0610 +#define RT1019_CAL_TOP_18 0x0611 +#define RT1019_CAL_TOP_19 0x0612 +#define RT1019_CAL_TOP_20 0x0613 +#define RT1019_CAL_TOP_21 0x0614 +#define RT1019_CAL_TOP_22 0x0615 +#define RT1019_MDRE_CTRL_1 0x0700 +#define RT1019_MDRE_CTRL_2 0x0701 +#define RT1019_MDRE_CTRL_3 0x0702 +#define RT1019_MDRE_CTRL_4 0x0703 +#define RT1019_MDRE_CTRL_5 0x0704 +#define RT1019_MDRE_CTRL_6 0x0705 +#define RT1019_MDRE_CTRL_7 0x0706 +#define RT1019_MDRE_CTRL_8 0x0707 +#define RT1019_MDRE_CTRL_9 0x0708 +#define RT1019_MDRE_CTRL_10 0x0709 +#define RT1019_SCC_CTRL_1 0x0800 +#define RT1019_SCC_CTRL_2 0x0801 +#define RT1019_SCC_CTRL_3 0x0802 +#define RT1019_SCC_DUMMY 0x0803 +#define RT1019_SIL_DET_1 0x0900 +#define RT1019_SIL_DET_2 0x0901 +#define RT1019_PWM_DC_DET_1 0x0a00 +#define RT1019_PWM_DC_DET_2 0x0a01 +#define RT1019_PWM_DC_DET_3 0x0a02 +#define RT1019_PWM_DC_DET_4 0x0a03 +#define RT1019_BEEP_1 0x0b00 +#define RT1019_BEEP_2 0x0b01 +#define RT1019_PMC_1 0x0c00 +#define RT1019_PMC_2 0x0c01 +#define RT1019_PMC_3 0x0c02 +#define RT1019_PMC_4 0x0c03 +#define RT1019_PMC_5 0x0c04 +#define RT1019_PMC_6 0x0c05 +#define RT1019_PMC_7 0x0c06 +#define RT1019_PMC_8 0x0c07 +#define RT1019_PMC_9 0x0c08 +#define RT1019_SPKDRC_1 0x0d00 +#define RT1019_SPKDRC_2 0x0d01 +#define RT1019_SPKDRC_3 0x0d02 +#define RT1019_SPKDRC_4 0x0d03 +#define RT1019_SPKDRC_5 0x0d04 +#define RT1019_SPKDRC_6 0x0d05 +#define RT1019_SPKDRC_7 0x0d06 +#define RT1019_HALF_FREQ_1 0x0e00 +#define RT1019_HALF_FREQ_2 0x0e01 +#define RT1019_HALF_FREQ_3 0x0e02 +#define RT1019_HALF_FREQ_4 0x0e03 +#define RT1019_HALF_FREQ_5 0x0e04 +#define RT1019_HALF_FREQ_6 0x0e05 +#define RT1019_HALF_FREQ_7 0x0e06 +#define RT1019_CUR_CTRL_1 0x0f00 +#define RT1019_CUR_CTRL_2 0x0f01 +#define RT1019_CUR_CTRL_3 0x0f02 +#define RT1019_CUR_CTRL_4 0x0f03 +#define RT1019_CUR_CTRL_5 0x0f04 +#define RT1019_CUR_CTRL_6 0x0f05 +#define RT1019_CUR_CTRL_7 0x0f06 +#define RT1019_CUR_CTRL_8 0x0f07 +#define RT1019_CUR_CTRL_9 0x0f08 +#define RT1019_CUR_CTRL_10 0x0f09 +#define RT1019_CUR_CTRL_11 0x0f0a +#define RT1019_CUR_CTRL_12 0x0f0b +#define RT1019_CUR_CTRL_13 0x0f0c + +/* 0x0019 Power On Strap Control-2 */ +#define RT1019_AUTO_BITS_SEL_MASK (0x1 << 5) +#define RT1019_AUTO_BITS_SEL_AUTO (0x1 << 5) +#define RT1019_AUTO_BITS_SEL_MANU (0x0 << 5) +#define RT1019_AUTO_CLK_SEL_MASK (0x1 << 4) +#define RT1019_AUTO_CLK_SEL_AUTO (0x1 << 4) +#define RT1019_AUTO_CLK_SEL_MANU (0x0 << 4) + +/* 0x0100 Clock Tree Control-1 */ +#define RT1019_CLK_SYS_PRE_SEL_MASK (0x1 << 7) +#define RT1019_CLK_SYS_PRE_SEL_SFT 7 +#define RT1019_CLK_SYS_PRE_SEL_BCLK (0x0 << 7) +#define RT1019_CLK_SYS_PRE_SEL_PLL (0x1 << 7) +#define RT1019_PLL_SRC_MASK (0x1 << 4) +#define RT1019_PLL_SRC_SFT 4 +#define RT1019_PLL_SRC_SEL_BCLK (0x0 << 4) +#define RT1019_PLL_SRC_SEL_RC (0x1 << 4) +#define RT1019_SEL_FIFO_MASK (0x3 << 2) +#define RT1019_SEL_FIFO_DIV1 (0x0 << 2) +#define RT1019_SEL_FIFO_DIV2 (0x1 << 2) +#define RT1019_SEL_FIFO_DIV4 (0x2 << 2) + +/* 0x0101 clock tree control-2 */ +#define RT1019_SYS_DIV_DA_FIL_MASK (0x7 << 5) +#define RT1019_SYS_DIV_DA_FIL_DIV1 (0x2 << 5) +#define RT1019_SYS_DIV_DA_FIL_DIV2 (0x3 << 5) +#define RT1019_SYS_DIV_DA_FIL_DIV4 (0x4 << 5) +#define RT1019_SYS_DA_OSR_MASK (0x3 << 2) +#define RT1019_SYS_DA_OSR_DIV1 (0x0 << 2) +#define RT1019_SYS_DA_OSR_DIV2 (0x1 << 2) +#define RT1019_SYS_DA_OSR_DIV4 (0x2 << 2) +#define RT1019_ASRC_256FS_MASK 0x3 +#define RT1019_ASRC_256FS_DIV1 0x0 +#define RT1019_ASRC_256FS_DIV2 0x1 +#define RT1019_ASRC_256FS_DIV4 0x2 + +/* 0x0102 clock tree control-3 */ +#define RT1019_SEL_CLK_CAL_MASK (0x3 << 6) +#define RT1019_SEL_CLK_CAL_DIV1 (0x0 << 6) +#define RT1019_SEL_CLK_CAL_DIV2 (0x1 << 6) +#define RT1019_SEL_CLK_CAL_DIV4 (0x2 << 6) + +/* 0x0311 PLL-1 */ +#define RT1019_PLL_M_MASK (0xf << 4) +#define RT1019_PLL_M_SFT 4 +#define RT1019_PLL_M_BP_MASK (0x1 << 1) +#define RT1019_PLL_M_BP_SFT 1 +#define RT1019_PLL_Q_8_8_MASK (0x1) + +/* 0x0312 PLL-2 */ +#define RT1019_PLL_Q_7_0_MASK 0xff + +/* 0x0313 PLL-3 */ +#define RT1019_PLL_K_MASK 0x1f + +/* 0x0400 TDM Control-1 */ +#define RT1019_TDM_BCLK_MASK (0x1 << 6) +#define RT1019_TDM_BCLK_NORM (0x0 << 6) +#define RT1019_TDM_BCLK_INV (0x1 << 6) + +/* 0x0401 TDM Control-2 */ +#define RT1019_I2S_CH_TX_MASK (0x3 << 6) +#define RT1019_I2S_CH_TX_SFT 6 +#define RT1019_I2S_TX_2CH (0x0 << 6) +#define RT1019_I2S_TX_4CH (0x1 << 6) +#define RT1019_I2S_TX_6CH (0x2 << 6) +#define RT1019_I2S_TX_8CH (0x3 << 6) +#define RT1019_I2S_DF_MASK (0x7 << 3) +#define RT1019_I2S_DF_SFT 3 +#define RT1019_I2S_DF_I2S (0x0 << 3) +#define RT1019_I2S_DF_LEFT (0x1 << 3) +#define RT1019_I2S_DF_PCM_A_R (0x2 << 3) +#define RT1019_I2S_DF_PCM_B_R (0x3 << 3) +#define RT1019_I2S_DF_PCM_A_F (0x6 << 3) +#define RT1019_I2S_DF_PCM_B_F (0x7 << 3) +#define RT1019_I2S_DL_MASK 0x7 +#define RT1019_I2S_DL_SFT 0 +#define RT1019_I2S_DL_16 0x0 +#define RT1019_I2S_DL_20 0x1 +#define RT1019_I2S_DL_24 0x2 +#define RT1019_I2S_DL_32 0x3 +#define RT1019_I2S_DL_8 0x4 + +/* TDM1 Control-3 (0x0402) */ +#define RT1019_TDM_I2S_TX_L_DAC1_1_MASK (0x7 << 4) +#define RT1019_TDM_I2S_TX_R_DAC1_1_MASK 0x7 +#define RT1019_TDM_I2S_TX_L_DAC1_1_SFT 4 +#define RT1019_TDM_I2S_TX_R_DAC1_1_SFT 0 + +/* System Clock Source */ +enum { + RT1019_SCLK_S_BCLK, + RT1019_SCLK_S_PLL, +}; + +/* PLL1 Source */ +enum { + RT1019_PLL_S_BCLK, + RT1019_PLL_S_RC25M, +}; + +enum { + RT1019_AIF1, + RT1019_AIFS +}; + +struct rt1019_priv { + struct snd_soc_component *component; + struct regmap *regmap; + int sysclk; + int sysclk_src; + int lrck; + int bclk; + int pll_src; + int pll_in; + int pll_out; + unsigned int bclk_ratio; +}; + +#endif /* __RT1019_H__ */ From ad83b1adc58d6693036fd330d6af95a33564eaae Mon Sep 17 00:00:00 2001 From: Brent Lu Date: Wed, 17 Mar 2021 19:08:24 +0800 Subject: [PATCH 0298/1091] ASoC: Intel: sof_rt5682: Add ALC1015Q-VB speaker amp support This patch adds jsl_rt5682_rt1015p which supports the RT5682 headset codec and ALC1015Q-VB speaker amplifier combination on JasperLake platform. This driver also supports ALC1015Q-CG if running in auto-mode. Following table shows the audio interface support of the two amplifiers. | ALC1015Q-CG | ALC1015Q-VB ===================================== I2C | Yes | No Auto-mode | 48K, 64fs | 16k, 32fs | 48k, 32fs | 48k, 64fs Signed-off-by: Brent Lu Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210317110824.20814-1-brent.lu@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/Kconfig | 1 + sound/soc/intel/boards/sof_realtek_common.c | 105 ++++++++++++++++++ sound/soc/intel/boards/sof_realtek_common.h | 7 ++ sound/soc/intel/boards/sof_rt5682.c | 19 +++- .../intel/common/soc-acpi-intel-jsl-match.c | 13 +++ 5 files changed, 143 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/Kconfig b/sound/soc/intel/boards/Kconfig index d1d28129a32b..58379393b8e4 100644 --- a/sound/soc/intel/boards/Kconfig +++ b/sound/soc/intel/boards/Kconfig @@ -457,6 +457,7 @@ config SND_SOC_INTEL_SOF_RT5682_MACH select SND_SOC_MAX98373_I2C select SND_SOC_RT1011 select SND_SOC_RT1015 + select SND_SOC_RT1015P select SND_SOC_RT5682_I2C select SND_SOC_DMIC select SND_SOC_HDAC_HDMI diff --git a/sound/soc/intel/boards/sof_realtek_common.c b/sound/soc/intel/boards/sof_realtek_common.c index f3cf73c620ba..2ec34f8df9e1 100644 --- a/sound/soc/intel/boards/sof_realtek_common.c +++ b/sound/soc/intel/boards/sof_realtek_common.c @@ -7,6 +7,7 @@ #include #include #include +#include #include #include #include @@ -136,3 +137,107 @@ void sof_rt1011_codec_conf(struct snd_soc_card *card) card->codec_conf = rt1011_codec_confs; card->num_configs = ARRAY_SIZE(rt1011_codec_confs); } + +/* + * rt1015: i2c mode driver for ALC1015 and ALC1015Q + * rt1015p: auto-mode driver for ALC1015, ALC1015Q, and ALC1015Q-VB + * + * For stereo output, there are always two amplifiers on the board. + * However, the ACPI implements only one device instance (UID=0) if they + * are sharing the same enable pin. The code will detect the number of + * device instance and use corresponding DAPM structures for + * initialization. + */ +static const struct snd_soc_dapm_route rt1015p_1dev_dapm_routes[] = { + /* speaker */ + { "Left Spk", NULL, "Speaker" }, + { "Right Spk", NULL, "Speaker" }, +}; + +static const struct snd_soc_dapm_route rt1015p_2dev_dapm_routes[] = { + /* speaker */ + { "Left Spk", NULL, "Left Speaker" }, + { "Right Spk", NULL, "Right Speaker" }, +}; + +static struct snd_soc_codec_conf rt1015p_codec_confs[] = { + { + .dlc = COMP_CODEC_CONF(RT1015P_DEV0_NAME), + .name_prefix = "Left", + }, + { + .dlc = COMP_CODEC_CONF(RT1015P_DEV1_NAME), + .name_prefix = "Right", + }, +}; + +static struct snd_soc_dai_link_component rt1015p_dai_link_components[] = { + { + .name = RT1015P_DEV0_NAME, + .dai_name = RT1015P_CODEC_DAI, + }, + { + .name = RT1015P_DEV1_NAME, + .dai_name = RT1015P_CODEC_DAI, + }, +}; + +static int rt1015p_get_num_codecs(void) +{ + static int dev_num; + + if (dev_num) + return dev_num; + + if (!acpi_dev_present("RTL1015", "1", -1)) + dev_num = 1; + else + dev_num = 2; + + return dev_num; +} + +static int rt1015p_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + /* reserved for debugging purpose */ + + return 0; +} + +static const struct snd_soc_ops rt1015p_ops = { + .hw_params = rt1015p_hw_params, +}; + +static int rt1015p_init(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_card *card = rtd->card; + int ret; + + if (rt1015p_get_num_codecs() == 1) + ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_1dev_dapm_routes, + ARRAY_SIZE(rt1015p_1dev_dapm_routes)); + else + ret = snd_soc_dapm_add_routes(&card->dapm, rt1015p_2dev_dapm_routes, + ARRAY_SIZE(rt1015p_2dev_dapm_routes)); + if (ret) + dev_err(rtd->dev, "Speaker map addition failed: %d\n", ret); + return ret; +} + +void sof_rt1015p_dai_link(struct snd_soc_dai_link *link) +{ + link->codecs = rt1015p_dai_link_components; + link->num_codecs = rt1015p_get_num_codecs(); + link->init = rt1015p_init; + link->ops = &rt1015p_ops; +} + +void sof_rt1015p_codec_conf(struct snd_soc_card *card) +{ + if (rt1015p_get_num_codecs() == 1) + return; + + card->codec_conf = rt1015p_codec_confs; + card->num_configs = ARRAY_SIZE(rt1015p_codec_confs); +} diff --git a/sound/soc/intel/boards/sof_realtek_common.h b/sound/soc/intel/boards/sof_realtek_common.h index 87cb3812b926..cb0b49b2855c 100644 --- a/sound/soc/intel/boards/sof_realtek_common.h +++ b/sound/soc/intel/boards/sof_realtek_common.h @@ -21,4 +21,11 @@ void sof_rt1011_dai_link(struct snd_soc_dai_link *link); void sof_rt1011_codec_conf(struct snd_soc_card *card); +#define RT1015P_CODEC_DAI "HiFi" +#define RT1015P_DEV0_NAME "RTL1015:00" +#define RT1015P_DEV1_NAME "RTL1015:01" + +void sof_rt1015p_dai_link(struct snd_soc_dai_link *link); +void sof_rt1015p_codec_conf(struct snd_soc_card *card); + #endif /* __SOF_REALTEK_COMMON_H */ diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index 55505e207bc0..f4b898c1719f 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -45,8 +45,9 @@ #define SOF_RT1011_SPEAKER_AMP_PRESENT BIT(13) #define SOF_RT1015_SPEAKER_AMP_PRESENT BIT(14) #define SOF_RT1015_SPEAKER_AMP_100FS BIT(15) -#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(16) -#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(17) +#define SOF_RT1015P_SPEAKER_AMP_PRESENT BIT(16) +#define SOF_MAX98373_SPEAKER_AMP_PRESENT BIT(17) +#define SOF_MAX98360A_SPEAKER_AMP_PRESENT BIT(18) /* Default: MCLK on, MCLK 19.2M, SSP0 */ static unsigned long sof_rt5682_quirk = SOF_RT5682_MCLK_EN | @@ -723,6 +724,8 @@ static struct snd_soc_dai_link *sof_card_dai_links_create(struct device *dev, links[id].num_codecs = ARRAY_SIZE(rt1015_components); links[id].init = speaker_codec_init_lr; links[id].ops = &sof_rt1015_ops; + } else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) { + sof_rt1015p_dai_link(&links[id]); } else if (sof_rt5682_quirk & SOF_MAX98373_SPEAKER_AMP_PRESENT) { links[id].codecs = max_98373_components; @@ -851,6 +854,8 @@ static int sof_audio_probe(struct platform_device *pdev) sof_max98373_codec_conf(&sof_audio_card_rt5682); else if (sof_rt5682_quirk & SOF_RT1011_SPEAKER_AMP_PRESENT) sof_rt1011_codec_conf(&sof_audio_card_rt5682); + else if (sof_rt5682_quirk & SOF_RT1015P_SPEAKER_AMP_PRESENT) + sof_rt1015p_codec_conf(&sof_audio_card_rt5682); dai_links = sof_card_dai_links_create(&pdev->dev, ssp_codec, ssp_amp, dmic_be_num, hdmi_num); @@ -940,6 +945,15 @@ static const struct platform_device_id board_ids[] = { SOF_RT5682_SSP_AMP(1) | SOF_RT5682_NUM_HDMIDEV(4)), }, + { + .name = "jsl_rt5682_rt1015p", + .driver_data = (kernel_ulong_t)(SOF_RT5682_MCLK_EN | + SOF_RT5682_MCLK_24MHZ | + SOF_RT5682_SSP_CODEC(0) | + SOF_SPEAKER_AMP_PRESENT | + SOF_RT1015P_SPEAKER_AMP_PRESENT | + SOF_RT5682_SSP_AMP(1)), + }, { } }; @@ -966,3 +980,4 @@ MODULE_ALIAS("platform:tgl_max98373_rt5682"); MODULE_ALIAS("platform:jsl_rt5682_max98360a"); MODULE_ALIAS("platform:cml_rt1015_rt5682"); MODULE_ALIAS("platform:tgl_rt1011_rt5682"); +MODULE_ALIAS("platform:jsl_rt5682_rt1015p"); diff --git a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c index 52238db0bcb5..73fe4f89a82d 100644 --- a/sound/soc/intel/common/soc-acpi-intel-jsl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-jsl-match.c @@ -19,6 +19,11 @@ static struct snd_soc_acpi_codecs rt1015_spk = { .codecs = {"10EC1015"} }; +static struct snd_soc_acpi_codecs rt1015p_spk = { + .num_codecs = 1, + .codecs = {"RTL1015"} +}; + static struct snd_soc_acpi_codecs mx98360a_spk = { .num_codecs = 1, .codecs = {"MX98360A"} @@ -52,6 +57,14 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_jsl_machines[] = { .quirk_data = &rt1015_spk, .sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg", }, + { + .id = "10EC5682", + .drv_name = "jsl_rt5682_rt1015p", + .sof_fw_filename = "sof-jsl.ri", + .machine_quirk = snd_soc_acpi_codec_list, + .quirk_data = &rt1015p_spk, + .sof_tplg_filename = "sof-jsl-rt5682-rt1015.tplg", + }, { .id = "10EC5682", .drv_name = "jsl_rt5682_max98360a", From 2e8496f31d0be8f43849b2980b069f3a9805d047 Mon Sep 17 00:00:00 2001 From: Richard Gong Date: Tue, 9 Feb 2021 16:20:27 -0600 Subject: [PATCH 0299/1091] firmware: stratix10-svc: reset COMMAND_RECONFIG_FLAG_PARTIAL to 0 Clean up COMMAND_RECONFIG_FLAG_PARTIAL flag by resetting it to 0, which aligns with the firmware settings. Fixes: 36847f9e3e56 ("firmware: stratix10-svc: correct reconfig flag and timeout values") Signed-off-by: Richard Gong Reviewed-by: Tom Rix Signed-off-by: Moritz Fischer --- include/linux/firmware/intel/stratix10-svc-client.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/firmware/intel/stratix10-svc-client.h b/include/linux/firmware/intel/stratix10-svc-client.h index ebc295647581..19781b0f6429 100644 --- a/include/linux/firmware/intel/stratix10-svc-client.h +++ b/include/linux/firmware/intel/stratix10-svc-client.h @@ -56,7 +56,7 @@ * COMMAND_RECONFIG_FLAG_PARTIAL: * Set to FPGA configuration type (full or partial). */ -#define COMMAND_RECONFIG_FLAG_PARTIAL 1 +#define COMMAND_RECONFIG_FLAG_PARTIAL 0 /* * Timeout settings for service clients: From 491aef7caeb345ccfd658a7fc8a42944a7f82494 Mon Sep 17 00:00:00 2001 From: Georgi Djakov Date: Thu, 18 Mar 2021 18:34:15 +0200 Subject: [PATCH 0300/1091] interconnect: Fix kerneldoc warning Fix the following warning: drivers/interconnect/bulk.c:63: warning: expecting prototype for icc_bulk_set(). Prototype was for icc_bulk_set_bw() instead Link: https://lore.kernel.org/r/20210318163415.30941-1-georgi.djakov@linaro.org Signed-off-by: Georgi Djakov --- drivers/interconnect/bulk.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/interconnect/bulk.c b/drivers/interconnect/bulk.c index 73e2c8d0a412..448cc536aa79 100644 --- a/drivers/interconnect/bulk.c +++ b/drivers/interconnect/bulk.c @@ -53,7 +53,7 @@ void icc_bulk_put(int num_paths, struct icc_bulk_data *paths) EXPORT_SYMBOL_GPL(icc_bulk_put); /** - * icc_bulk_set() - set bandwidth to a set of paths + * icc_bulk_set_bw() - set bandwidth to a set of paths * @num_paths: the number of icc_bulk_data * @paths: the icc_bulk_data table containing the paths and bandwidth * From e4b044f4582366de10b8b28614c24ac4ff22b299 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:57:37 +0900 Subject: [PATCH 0301/1091] ASoC: soc-pcm: indicate error message at soc_pcm_open() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch follow above style at soc_pcm_open(). By this patch, dpcm_fe/be_dai_startup(...) temporary lacks FE/BE error info, but it will reborn soon. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r1khutby.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a27385ab7b55..ad4b67bd0306 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -792,8 +792,10 @@ dynamic: err: mutex_unlock(&rtd->card->pcm_mutex); pm_err: - if (ret < 0) + if (ret < 0) { soc_pcm_clean(substream, 1); + dev_err(rtd->dev, "%s() failed (%d)", __func__, ret); + } return ret; } @@ -1504,7 +1506,6 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) be_substream->runtime = be->dpcm[stream].runtime; err = soc_pcm_open(be_substream); if (err < 0) { - dev_err(be->dev, "ASoC: BE open failed %d\n", err); be->dpcm[stream].users--; if (be->dpcm[stream].users < 0) dev_err(be->dev, "ASoC: no users %s at unwind %d\n", @@ -1744,10 +1745,8 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) /* start the DAI frontend */ ret = soc_pcm_open(fe_substream); - if (ret < 0) { - dev_err(fe->dev,"ASoC: failed to start FE %d\n", ret); + if (ret < 0) goto unwind; - } fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; From cb11f79b4af65005584880eb408f9748c32661d0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:57:42 +0900 Subject: [PATCH 0302/1091] ASoC: soc-pcm: indicate error message at soc_pcm_hw_params() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch follow above style at soc_pcm_hw_params(). By this patch, dpcm_fe/be_dai_hw_params(...) temporary lacks FE/BE error info, but it will reborn soon. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pn01utbt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ad4b67bd0306..a956d1852ade 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1001,8 +1001,10 @@ static int soc_pcm_hw_params(struct snd_pcm_substream *substream, out: mutex_unlock(&rtd->card->pcm_mutex); - if (ret < 0) + if (ret < 0) { soc_pcm_hw_clean(substream, 1); + dev_err(rtd->dev, "ASoC: %s() failed (%d)\n", __func__, ret); + } return ret; } @@ -1905,11 +1907,8 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) be->dai_link->name); ret = soc_pcm_hw_params(be_substream, &dpcm->hw_params); - if (ret < 0) { - dev_err(dpcm->be->dev, - "ASoC: hw_params BE failed %d\n", ret); + if (ret < 0) goto unwind; - } be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS; } @@ -1964,10 +1963,9 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, /* call hw_params on the frontend */ ret = soc_pcm_hw_params(substream, params); - if (ret < 0) { - dev_err(fe->dev,"ASoC: hw_params FE failed %d\n", ret); + if (ret < 0) dpcm_be_dai_hw_free(fe, stream); - } else + else fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_PARAMS; out: From dab7eeb4045cce074e083be1f3092d7390d6cfb2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:57:48 +0900 Subject: [PATCH 0303/1091] ASoC: soc-pcm: indicate error message at soc_pcm_prepare() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch follow above style at soc_pcm_prepare(). By this patch, dpcm_fe/be_dai_prepare(...) temporary lacks FE/BE error info, but it will reborn soon. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o8flutbn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a956d1852ade..82daf79f5b3f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -852,6 +852,10 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) out: mutex_unlock(&rtd->card->pcm_mutex); + + if (ret < 0) + dev_err(rtd->dev, "ASoC: %s() failed (%d)\n", __func__, ret); + return ret; } @@ -2234,11 +2238,8 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) be->dai_link->name); ret = soc_pcm_prepare(be_substream); - if (ret < 0) { - dev_err(be->dev, "ASoC: backend prepare failed %d\n", - ret); + if (ret < 0) break; - } be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; } @@ -2270,11 +2271,8 @@ static int dpcm_fe_dai_prepare(struct snd_pcm_substream *substream) /* call prepare on the frontend */ ret = soc_pcm_prepare(substream); - if (ret < 0) { - dev_err(fe->dev,"ASoC: prepare FE %s failed\n", - fe->dai_link->name); + if (ret < 0) goto out; - } fe->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; From d479f00b795ac62b24ef90f4ec421e65c3178ca7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:57:52 +0900 Subject: [PATCH 0304/1091] ASoC: soc-pcm: indicate error message at dpcm_path_get() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } Now, many place uses dpcm_path_get() like below ret = dpcm_path_get(...); if (ret < 0) goto error; (A) else if (ret == 0) dev_dbg(...) But here, (A) part can be indicated at dpcm_path_get() not caller. It is simple and readable code. This patch do it. Small detail behaviors will be exchanged by this patch. 1) indicates debug info (= path numbers) if path > 0 case only (It was *always* indicated). 2) soc_dpcm_fe_runtime_update() is indicating error message for paths < 0 case, but it is already done at dpcm_path_get(). Thus just remove it. but dev_dbg() vs dev_warn() is exchanged. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mtv5utbj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 4 +--- sound/soc/soc-pcm.c | 19 +++++++------------ 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 89445ba0e86b..94f1f7a9dd53 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -115,9 +115,7 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) ret = dpcm_path_get(fe, stream, &list); if (ret < 0) goto be_err; - else if (ret == 0) - dev_dbg(fe->dev, "Compress ASoC: %s no valid %s route\n", - fe->dai_link->name, stream ? "capture" : "playback"); + /* calculate valid and active FE <-> BE dpcms */ dpcm_process_paths(fe, stream, &list, 1); fe->dpcm[stream].runtime = fe_substream->runtime; diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 82daf79f5b3f..b21c53becd11 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1290,8 +1290,12 @@ int dpcm_path_get(struct snd_soc_pcm_runtime *fe, fe->card->component_chaining ? NULL : dpcm_end_walk_at_be); - dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, + if (paths > 0) + dev_dbg(fe->dev, "ASoC: found %d audio %s paths\n", paths, stream ? "capture" : "playback"); + else if (paths == 0) + dev_dbg(fe->dev, "ASoC: %s no valid %s path\n", fe->dai_link->name, + stream ? "capture" : "playback"); return paths; } @@ -2457,13 +2461,8 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) continue; paths = dpcm_path_get(fe, stream, &list); - if (paths < 0) { - dev_warn(fe->dev, "ASoC: %s no valid %s path\n", - fe->dai_link->name, - stream == SNDRV_PCM_STREAM_PLAYBACK ? - "playback" : "capture"); + if (paths < 0) return paths; - } /* update any playback/capture paths */ count = dpcm_process_paths(fe, stream, &list, new); @@ -2556,12 +2555,8 @@ static int dpcm_fe_dai_open(struct snd_pcm_substream *fe_substream) fe->dpcm[stream].runtime = fe_substream->runtime; ret = dpcm_path_get(fe, stream, &list); - if (ret < 0) { + if (ret < 0) goto open_end; - } else if (ret == 0) { - dev_dbg(fe->dev, "ASoC: %s no valid %s route\n", - fe->dai_link->name, stream ? "capture" : "playback"); - } /* calculate valid and active FE <-> BE dpcms */ dpcm_process_paths(fe, stream, &list, 1); From db3aa39c91068424407f71d23b028493eac994a1 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:57:57 +0900 Subject: [PATCH 0305/1091] ASoC: soc-pcm: indicate error message at dpcm_be_dai_trigger() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } Now, dpcm_be_dai_trigger() user uses it like below. err = dpcm_be_dai_trigger(...); if (err < 0) dev_err(..., "ASoC: trigger FE failed %d\n", err); But we can get more detail information if dpcm_be_dai_trigger() itself had dev_err(). And above error message is confusable, failed is *BE*, not *FE*. This patch indicates error message at dpcm_be_dai_trigger(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lfaputbe.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index b21c53becd11..35c62062b8f8 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1985,14 +1985,15 @@ out: int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd) { + struct snd_soc_pcm_runtime *be; struct snd_soc_dpcm *dpcm; int ret = 0; for_each_dpcm_be(fe, stream, dpcm) { + struct snd_pcm_substream *be_substream; - struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_pcm_substream *be_substream = - snd_soc_dpcm_get_substream(be, stream); + be = dpcm->be; + be_substream = snd_soc_dpcm_get_substream(be, stream); /* is this op for this BE ? */ if (!snd_soc_dpcm_be_can_update(fe, be, stream)) @@ -2010,7 +2011,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, ret = soc_pcm_trigger(be_substream, cmd); if (ret) - return ret; + goto end; be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; @@ -2020,7 +2021,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, ret = soc_pcm_trigger(be_substream, cmd); if (ret) - return ret; + goto end; be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; @@ -2030,7 +2031,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, ret = soc_pcm_trigger(be_substream, cmd); if (ret) - return ret; + goto end; be->dpcm[stream].state = SND_SOC_DPCM_STATE_START; break; @@ -2044,7 +2045,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, ret = soc_pcm_trigger(be_substream, cmd); if (ret) - return ret; + goto end; be->dpcm[stream].state = SND_SOC_DPCM_STATE_STOP; break; @@ -2057,7 +2058,7 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, ret = soc_pcm_trigger(be_substream, cmd); if (ret) - return ret; + goto end; be->dpcm[stream].state = SND_SOC_DPCM_STATE_SUSPEND; break; @@ -2070,13 +2071,16 @@ int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, ret = soc_pcm_trigger(be_substream, cmd); if (ret) - return ret; + goto end; be->dpcm[stream].state = SND_SOC_DPCM_STATE_PAUSED; break; } } - +end: + if (ret < 0) + dev_err(fe->dev, "ASoC: %s() failed at %s (%d)\n", + __func__, be->dai_link->name, ret); return ret; } EXPORT_SYMBOL_GPL(dpcm_be_dai_trigger); @@ -2310,8 +2314,6 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) fe->dai_link->name); err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP); - if (err < 0) - dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err); } err = dpcm_be_dai_hw_free(fe, stream); @@ -2393,10 +2395,8 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) ret = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_START); - if (ret < 0) { - dev_err(fe->dev,"ASoC: trigger FE failed %d\n", ret); + if (ret < 0) goto hw_free; - } } return 0; From bbd2bac8d6ca00ee0b032d3c03100328131425ac Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:02 +0900 Subject: [PATCH 0306/1091] ASoC: soc-pcm: indicate error message at dpcm_apply_symmetry() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch follow above style at dpcm_apply_symmetry(...) Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0q9utb9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 35c62062b8f8..855904c0938d 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1706,7 +1706,7 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, /* Symmetry only applies if we've got an active stream. */ err = soc_pcm_apply_symmetry(fe_substream, fe_cpu_dai); if (err < 0) - return err; + goto error; } /* apply symmetry for BE */ @@ -1731,11 +1731,14 @@ static int dpcm_apply_symmetry(struct snd_pcm_substream *fe_substream, for_each_rtd_dais(rtd, i, dai) { err = soc_pcm_apply_symmetry(fe_substream, dai); if (err < 0) - return err; + goto error; } } +error: + if (err < 0) + dev_err(fe->dev, "ASoC: %s failed (%d)\n", __func__, err); - return 0; + return err; } static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) @@ -1767,9 +1770,6 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) dpcm_runtime_setup_be_rate(fe_substream); ret = dpcm_apply_symmetry(fe_substream, stream); - if (ret < 0) - dev_err(fe->dev, "ASoC: failed to apply dpcm symmetry %d\n", - ret); unwind: if (ret < 0) From 81c82a9edbddc4cd97e4d974dfd7f2689ee63474 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:08 +0900 Subject: [PATCH 0307/1091] ASoC: soc-pcm: indicate error message at dpcm_run_update_startup/shutdown() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch also do below to dpcm_run_update_startup() 1) remove duplicated ret = -EINVAL 2) remove blank line do below to dpcm_run_update_shutdown() 1) remove unused ret Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87im5tutb3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 855904c0938d..a34b1fb9967a 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2325,7 +2325,10 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) /* run the stream event for each BE */ dpcm_dapm_stream_event(fe, stream, SND_SOC_DAPM_STREAM_NOP); - return 0; + if (err < 0) + dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, err); + + return err; } static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) @@ -2366,7 +2369,6 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) if (fe->dpcm[stream].state == SND_SOC_DPCM_STATE_HW_PARAMS) return 0; - ret = dpcm_be_dai_prepare(fe, stream); if (ret < 0) goto hw_free; @@ -2421,6 +2423,9 @@ disconnect: } spin_unlock_irqrestore(&fe->card->dpcm_lock, flags); + if (ret < 0) + dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret); + return ret; } @@ -2429,7 +2434,6 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) struct snd_soc_dapm_widget_list *list; int stream; int count, paths; - int ret; if (!fe->dai_link->dynamic) return 0; @@ -2469,11 +2473,9 @@ static int soc_dpcm_fe_runtime_update(struct snd_soc_pcm_runtime *fe, int new) if (count) { dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_BE); if (new) - ret = dpcm_run_update_startup(fe, stream); + dpcm_run_update_startup(fe, stream); else - ret = dpcm_run_update_shutdown(fe, stream); - if (ret < 0) - dev_err(fe->dev, "ASoC: failed to shutdown some BEs\n"); + dpcm_run_update_shutdown(fe, stream); dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); dpcm_clear_pending_state(fe, stream); From 06aaeb874256a10fe5b84f511da3c65f548a43b9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:13 +0900 Subject: [PATCH 0308/1091] ASoC: soc-pcm: indicate error message at dpcm_fe/be_dai_startup() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch follow above style at dpcm_fe/be_dai_startup(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h7ldutay.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a34b1fb9967a..9e3ecf788a74 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1475,15 +1475,16 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) { + struct snd_soc_pcm_runtime *be; struct snd_soc_dpcm *dpcm; int err, count = 0; /* only startup BE DAIs that are either sinks or sources to this FE DAI */ for_each_dpcm_be(fe, stream, dpcm) { + struct snd_pcm_substream *be_substream; - struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_pcm_substream *be_substream = - snd_soc_dpcm_get_substream(be, stream); + be = dpcm->be; + be_substream = snd_soc_dpcm_get_substream(be, stream); if (!be_substream) { dev_err(be->dev, "ASoC: no backend %s stream\n", @@ -1535,6 +1536,9 @@ int dpcm_be_dai_startup(struct snd_soc_pcm_runtime *fe, int stream) unwind: dpcm_be_dai_startup_rollback(fe, stream, dpcm); + dev_err(fe->dev, "ASoC: %s() failed at %s (%d)\n", + __func__, be->dai_link->name, err); + return err; } @@ -1749,10 +1753,8 @@ static int dpcm_fe_dai_startup(struct snd_pcm_substream *fe_substream) dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); ret = dpcm_be_dai_startup(fe, stream); - if (ret < 0) { - dev_err(fe->dev,"ASoC: failed to start some BEs %d\n", ret); + if (ret < 0) goto be_err; - } dev_dbg(fe->dev, "ASoC: open FE %s\n", fe->dai_link->name); @@ -1776,6 +1778,10 @@ unwind: dpcm_be_dai_startup_unwind(fe, stream); be_err: dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); + + if (ret < 0) + dev_err(fe->dev, "%s() failed (%d)\n", __func__, ret); + return ret; } From 33b6b94f55ec60517ce71ca2bc9c03a6d337c805 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:18 +0900 Subject: [PATCH 0309/1091] ASoC: soc-pcm: indicate error message at dpcm_fe/be_dai_hw_params() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch follow above style at dpcm_fe/be_dai_hw_params() Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87ft0xutat.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 9e3ecf788a74..e141d0658279 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1882,14 +1882,14 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) { + struct snd_soc_pcm_runtime *be; + struct snd_pcm_substream *be_substream; struct snd_soc_dpcm *dpcm; int ret; for_each_dpcm_be(fe, stream, dpcm) { - - struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_pcm_substream *be_substream = - snd_soc_dpcm_get_substream(be, stream); + be = dpcm->be; + be_substream = snd_soc_dpcm_get_substream(be, stream); /* is this op for this BE ? */ if (!snd_soc_dpcm_be_can_update(fe, be, stream)) @@ -1929,11 +1929,13 @@ int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int stream) return 0; unwind: + dev_dbg(fe->dev, "ASoC: %s() failed at %s (%d)\n", + __func__, be->dai_link->name, ret); + /* disable any enabled and non active backends */ for_each_dpcm_be_rollback(fe, stream, dpcm) { - struct snd_soc_pcm_runtime *be = dpcm->be; - struct snd_pcm_substream *be_substream = - snd_soc_dpcm_get_substream(be, stream); + be = dpcm->be; + be_substream = snd_soc_dpcm_get_substream(be, stream); if (!snd_soc_dpcm_be_can_update(fe, be, stream)) continue; @@ -1966,10 +1968,8 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, memcpy(&fe->dpcm[stream].hw_params, params, sizeof(struct snd_pcm_hw_params)); ret = dpcm_be_dai_hw_params(fe, stream); - if (ret < 0) { - dev_err(fe->dev,"ASoC: hw_params BE failed %d\n", ret); + if (ret < 0) goto out; - } dev_dbg(fe->dev, "ASoC: hw_params FE %s rate %d chan %x fmt %d\n", fe->dai_link->name, params_rate(params), @@ -1985,6 +1985,10 @@ static int dpcm_fe_dai_hw_params(struct snd_pcm_substream *substream, out: dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); mutex_unlock(&fe->card->mutex); + + if (ret < 0) + dev_err(fe->dev, "ASoC: %s failed (%d)\n", __func__, ret); + return ret; } From 273db971cf833d62c9e2d9381d190e14b1cd3641 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:22 +0900 Subject: [PATCH 0310/1091] ASoC: soc-pcm: indicate error message at dpcm_fe/be_dai_prepare() Indicating error message when failed case is very useful for debuging. In many case, its style is like below. int function(...) { ... return ret; } int caller(...) { ... ret = function(...); if (ret < 0) dev_err(...) ... } This is not so bad, but in this style *each caller* needs to indicate duplicate same error message, and some caller is forgetting to do it. And caller can't indicate detail function() error information. If function() indicates error message, we can get same and detail information without forgot. int function(...) { ... if (ret < 0) dev_err(...) return ret; } int caller(...) { ... ret = function(...); ... } This patch follow above style at dpcm_fe/be_dai_prepare() Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87eeghutap.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index e141d0658279..4a01a3925ab6 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2261,6 +2261,10 @@ int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream) be->dpcm[stream].state = SND_SOC_DPCM_STATE_PREPARE; } + + if (ret < 0) + dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret); + return ret; } @@ -2298,6 +2302,9 @@ out: dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); mutex_unlock(&fe->card->mutex); + if (ret < 0) + dev_err(fe->dev, "ASoC: %s() failed (%d)\n", __func__, ret); + return ret; } From e20c9c4f96d79aa48eb3649c57f1f2784f92b838 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:28 +0900 Subject: [PATCH 0311/1091] ASoC: soc-pcm: don't indicate error message for soc_pcm_hw_free() soc_pcm_hw_free() never fail, error message is not needed. We can't use void function for it, because it is used part of struct snd_pcm_ops :: hw_free. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87czw1utaj.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 4a01a3925ab6..eb52f78ca053 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1862,10 +1862,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) dev_dbg(fe->dev, "ASoC: hw_free FE %s\n", fe->dai_link->name); /* call hw_free on the frontend */ - err = soc_pcm_hw_free(substream); - if (err < 0) - dev_err(fe->dev,"ASoC: hw_free FE %s failed\n", - fe->dai_link->name); + soc_pcm_hw_free(substream); /* only hw_params backends that are either sinks or sources * to this frontend DAI */ From f52366e6831ecb2da133b6ecfc7c69266086660c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:32 +0900 Subject: [PATCH 0312/1091] ASoC: soc-pcm: don't indicate error message for dpcm_be_dai_hw_free() dpcm_be_dai_hw_free() never fail, error message is not needed. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87blblutaf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-dpcm.h | 2 +- sound/soc/soc-compress.c | 5 +---- sound/soc/soc-pcm.c | 14 ++++---------- 3 files changed, 6 insertions(+), 15 deletions(-) diff --git a/include/sound/soc-dpcm.h b/include/sound/soc-dpcm.h index d76cb1eeeaca..e296a3949b18 100644 --- a/include/sound/soc-dpcm.h +++ b/include/sound/soc-dpcm.h @@ -153,7 +153,7 @@ void dpcm_be_dai_stop(struct snd_soc_pcm_runtime *fe, int stream, int do_hw_free, struct snd_soc_dpcm *last); void dpcm_be_disconnect(struct snd_soc_pcm_runtime *fe, int stream); void dpcm_clear_pending_state(struct snd_soc_pcm_runtime *fe, int stream); -int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); +void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream); int dpcm_be_dai_hw_params(struct snd_soc_pcm_runtime *fe, int tream); int dpcm_be_dai_trigger(struct snd_soc_pcm_runtime *fe, int stream, int cmd); int dpcm_be_dai_prepare(struct snd_soc_pcm_runtime *fe, int stream); diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 94f1f7a9dd53..83b511f8b8c9 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -175,7 +175,6 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(fe, 0); struct snd_soc_dpcm *dpcm; int stream = cstream->direction; /* SND_COMPRESS_xxx is same as SNDRV_PCM_STREAM_xxx */ - int ret; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); @@ -183,9 +182,7 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; - ret = dpcm_be_dai_hw_free(fe, stream); - if (ret < 0) - dev_err(fe->dev, "Compressed ASoC: hw_free failed: %d\n", ret); + dpcm_be_dai_hw_free(fe, stream); dpcm_be_dai_shutdown(fe, stream); diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index eb52f78ca053..2a126840677c 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -1808,7 +1808,7 @@ static int dpcm_fe_dai_shutdown(struct snd_pcm_substream *substream) return 0; } -int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) +void dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) { struct snd_soc_dpcm *dpcm; @@ -1847,14 +1847,12 @@ int dpcm_be_dai_hw_free(struct snd_soc_pcm_runtime *fe, int stream) be->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; } - - return 0; } static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *fe = asoc_substream_to_rtd(substream); - int err, stream = substream->stream; + int stream = substream->stream; mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_FE); @@ -1866,9 +1864,7 @@ static int dpcm_fe_dai_hw_free(struct snd_pcm_substream *substream) /* only hw_params backends that are either sinks or sources * to this frontend DAI */ - err = dpcm_be_dai_hw_free(fe, stream); - if (err < 0) - dev_err(fe->dev, "ASoC: hw_free BE failed %d\n", err); + dpcm_be_dai_hw_free(fe, stream); fe->dpcm[stream].state = SND_SOC_DPCM_STATE_HW_FREE; dpcm_set_fe_update_state(fe, stream, SND_SOC_DPCM_UPDATE_NO); @@ -2330,9 +2326,7 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) err = dpcm_be_dai_trigger(fe, stream, SNDRV_PCM_TRIGGER_STOP); } - err = dpcm_be_dai_hw_free(fe, stream); - if (err < 0) - dev_err(fe->dev,"ASoC: hw_free FE failed %d\n", err); + dpcm_be_dai_hw_free(fe, stream); dpcm_be_dai_shutdown(fe, stream); From 62462e018220895267450155b188f5804f54c202 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:37 +0900 Subject: [PATCH 0313/1091] ASoC: don't indicate error message for snd_soc_[pcm_]dai_xxx() All snd_soc_dai_xxx() and snd_soc_pcm_dai_xxx() itself indicate error message if failed. Its caller doesn't need to indicate duplicated error message. This patch removes it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a6r5utaa.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 16 +++------------- sound/soc/soc-dapm.c | 24 ++++++------------------ sound/soc/soc-pcm.c | 10 ++-------- 3 files changed, 11 insertions(+), 39 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index c7e4600b2dd4..f12c763973fa 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1088,12 +1088,8 @@ static int soc_init_pcm_runtime(struct snd_soc_card *card, /* create compress_device if possible */ ret = snd_soc_dai_compress_new(cpu_dai, rtd, num); - if (ret != -ENOTSUPP) { - if (ret < 0) - dev_err(card->dev, "ASoC: can't create compress %s\n", - dai_link->stream_name); + if (ret != -ENOTSUPP) return ret; - } /* create the pcm */ ret = soc_new_pcm(rtd, num); @@ -1422,11 +1418,8 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, for_each_rtd_codec_dais(rtd, i, codec_dai) { ret = snd_soc_dai_set_fmt(codec_dai, dai_fmt); - if (ret != 0 && ret != -ENOTSUPP) { - dev_warn(codec_dai->dev, - "ASoC: Failed to set DAI format: %d\n", ret); + if (ret != 0 && ret != -ENOTSUPP) return ret; - } } /* @@ -1455,11 +1448,8 @@ int snd_soc_runtime_set_dai_fmt(struct snd_soc_pcm_runtime *rtd, fmt = inv_dai_fmt; ret = snd_soc_dai_set_fmt(cpu_dai, fmt); - if (ret != 0 && ret != -ENOTSUPP) { - dev_warn(cpu_dai->dev, - "ASoC: Failed to set DAI format: %d\n", ret); + if (ret != 0 && ret != -ENOTSUPP) return ret; - } } return 0; diff --git a/sound/soc/soc-dapm.c b/sound/soc/soc-dapm.c index b005f9eadd71..91bf939d5233 100644 --- a/sound/soc/soc-dapm.c +++ b/sound/soc/soc-dapm.c @@ -3831,11 +3831,9 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, source = path->source->priv; ret = snd_soc_dai_startup(source, substream); - if (ret < 0) { - dev_err(source->dev, - "ASoC: startup() failed: %d\n", ret); + if (ret < 0) goto out; - } + snd_soc_dai_activate(source, substream->stream); } @@ -3844,11 +3842,9 @@ snd_soc_dai_link_event_pre_pmu(struct snd_soc_dapm_widget *w, sink = path->sink->priv; ret = snd_soc_dai_startup(sink, substream); - if (ret < 0) { - dev_err(sink->dev, - "ASoC: startup() failed: %d\n", ret); + if (ret < 0) goto out; - } + snd_soc_dai_activate(sink, substream->stream); } @@ -3943,11 +3939,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; - ret = snd_soc_dai_digital_mute(sink, 0, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret != 0 && ret != -ENOTSUPP) - dev_warn(sink->dev, - "ASoC: Failed to unmute: %d\n", ret); + snd_soc_dai_digital_mute(sink, 0, SNDRV_PCM_STREAM_PLAYBACK); ret = 0; } break; @@ -3956,11 +3948,7 @@ static int snd_soc_dai_link_event(struct snd_soc_dapm_widget *w, snd_soc_dapm_widget_for_each_sink_path(w, path) { sink = path->sink->priv; - ret = snd_soc_dai_digital_mute(sink, 1, - SNDRV_PCM_STREAM_PLAYBACK); - if (ret != 0 && ret != -ENOTSUPP) - dev_warn(sink->dev, - "ASoC: Failed to mute: %d\n", ret); + snd_soc_dai_digital_mute(sink, 1, SNDRV_PCM_STREAM_PLAYBACK); ret = 0; } diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2a126840677c..ecf2bfa9640b 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -832,10 +832,8 @@ static int soc_pcm_prepare(struct snd_pcm_substream *substream) goto out; ret = snd_soc_pcm_dai_prepare(substream); - if (ret < 0) { - dev_err(rtd->dev, "ASoC: DAI prepare error: %d\n", ret); + if (ret < 0) goto out; - } /* cancel any delayed stream shutdown that is pending */ if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK && @@ -2317,8 +2315,6 @@ static int dpcm_run_update_shutdown(struct snd_soc_pcm_runtime *fe, int stream) fe->dai_link->name); err = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_STOP); - if (err < 0) - dev_err(fe->dev,"ASoC: trigger FE failed %d\n", err); } else { dev_dbg(fe->dev, "ASoC: trigger FE %s cmd stop\n", fe->dai_link->name); @@ -2395,10 +2391,8 @@ static int dpcm_run_update_startup(struct snd_soc_pcm_runtime *fe, int stream) fe->dai_link->name); ret = snd_soc_pcm_dai_bespoke_trigger(substream, SNDRV_PCM_TRIGGER_START); - if (ret < 0) { - dev_err(fe->dev,"ASoC: bespoke trigger FE failed %d\n", ret); + if (ret < 0) goto hw_free; - } } else { dev_dbg(fe->dev, "ASoC: trigger FE %s cmd start\n", fe->dai_link->name); From 60adbd8fbf486214f4ae1946e61df69c3867e20b Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 15 Mar 2021 09:58:41 +0900 Subject: [PATCH 0314/1091] ASoC: don't indicate error message for snd_soc_[pcm_]component_xxx() All snd_soc_component_xxx() and snd_soc_pcm_component_xxx() itself indicate error message if failed. Its caller doesn't need to indicate duplicated error message. This patch removes it. All snd_soc_component_xxx() indicate error message if failed. Its caller doesn't need to indicate duplicated error message. This patch removes it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878s6puta6.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 ++---- sound/soc/soc-pcm.c | 5 +---- 2 files changed, 3 insertions(+), 8 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index f12c763973fa..522bae73640a 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1203,11 +1203,9 @@ static int soc_probe_component(struct snd_soc_card *card, } ret = snd_soc_component_probe(component); - if (ret < 0) { - dev_err(component->dev, - "ASoC: failed to probe component %d\n", ret); + if (ret < 0) goto err_probe; - } + WARN(dapm->idle_bias_off && dapm->bias_level != SND_SOC_BIAS_OFF, "codec %s can not start from non-off bias with idle_bias_off==1\n", diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index ecf2bfa9640b..2df70ab851ea 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2781,11 +2781,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) snd_pcm_set_ops(pcm, SNDRV_PCM_STREAM_CAPTURE, &rtd->ops); ret = snd_soc_pcm_component_new(rtd); - if (ret < 0) { - dev_err(rtd->dev, "ASoC: pcm constructor failed for dailink %s: %d\n", - rtd->dai_link->name, ret); + if (ret < 0) return ret; - } pcm->no_device_suspend = true; out: From e6d8af6687fa7730885d5c8d8f62e75e8dff29f0 Mon Sep 17 00:00:00 2001 From: Wei Yongjun Date: Fri, 19 Mar 2021 09:41:02 +0000 Subject: [PATCH 0315/1091] ASoC: rt1019: make symbol 'rt1019_i2c_driver' static The sparse tool complains as follows: sound/soc/codecs/rt1019.c:927:19: warning: symbol 'rt1019_i2c_driver' was not declared. Should it be static? This symbol is not used outside of rt1019.c, so this commit marks it static. Fixes: 7ec79d3850d0 ("ASoC: rt1019: add rt1019 amplifier driver") Reported-by: Hulk Robot Signed-off-by: Wei Yongjun Link: https://lore.kernel.org/r/20210319094102.4185096-1-weiyongjun1@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1019.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index fb275686a00f..5138f028d9f2 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -924,7 +924,7 @@ static int rt1019_i2c_probe(struct i2c_client *i2c, &soc_component_dev_rt1019, rt1019_dai, ARRAY_SIZE(rt1019_dai)); } -struct i2c_driver rt1019_i2c_driver = { +static struct i2c_driver rt1019_i2c_driver = { .driver = { .name = "rt1019", .of_match_table = of_match_ptr(rt1019_of_match), From 3a85969e9d912d5dd85362ee37b5f81266e00e77 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 21 Mar 2021 15:49:13 +0900 Subject: [PATCH 0316/1091] lockdep: Add a missing initialization hint to the "INFO: Trying to register non-static key" message Since this message is printed when dynamically allocated spinlocks (e.g. kzalloc()) are used without initialization (e.g. spin_lock_init()), suggest to developers to check whether initialization functions for objects were called, before making developers wonder what annotation is missing. [ mingo: Minor tweaks to the message. ] Signed-off-by: Tetsuo Handa Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20210321064913.4619-1-penguin-kernel@I-love.SAKURA.ne.jp Signed-off-by: Ingo Molnar --- kernel/locking/lockdep.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index c6d0c1dc6253..c30eb887ca7d 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -930,7 +930,8 @@ static bool assign_lock_key(struct lockdep_map *lock) /* Debug-check: all keys must be persistent! */ debug_locks_off(); pr_err("INFO: trying to register non-static key.\n"); - pr_err("the code is fine but needs lockdep annotation.\n"); + pr_err("The code is fine but needs lockdep annotation, or maybe\n"); + pr_err("you didn't initialize this object before use?\n"); pr_err("turning off the locking correctness validator.\n"); dump_stack(); return false; From e88add19f68191448427a6e4eb059664650a837f Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Tue, 16 Mar 2021 11:56:29 +0100 Subject: [PATCH 0317/1091] net: xfrm: Localize sequence counter per network namespace A sequence counter write section must be serialized or its internal state can get corrupted. The "xfrm_state_hash_generation" seqcount is global, but its write serialization lock (net->xfrm.xfrm_state_lock) is instantiated per network namespace. The write protection is thus insufficient. To provide full protection, localize the sequence counter per network namespace instead. This should be safe as both the seqcount read and write sections access data exclusively within the network namespace. It also lays the foundation for transforming "xfrm_state_hash_generation" data type from seqcount_t to seqcount_LOCKNAME_t in further commits. Fixes: b65e3d7be06f ("xfrm: state: add sequence count to detect hash resizes") Signed-off-by: Ahmed S. Darwish Signed-off-by: Steffen Klassert --- include/net/netns/xfrm.h | 4 +++- net/xfrm/xfrm_state.c | 10 +++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index 59f45b1e9dac..b59d73d529ba 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -72,7 +72,9 @@ struct netns_xfrm { #if IS_ENABLED(CONFIG_IPV6) struct dst_ops xfrm6_dst_ops; #endif - spinlock_t xfrm_state_lock; + spinlock_t xfrm_state_lock; + seqcount_t xfrm_state_hash_generation; + spinlock_t xfrm_policy_lock; struct mutex xfrm_cfg_mutex; }; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index d01ca1a18418..ffd315cff984 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -44,7 +44,6 @@ static void xfrm_state_gc_task(struct work_struct *work); */ static unsigned int xfrm_state_hashmax __read_mostly = 1 * 1024 * 1024; -static __read_mostly seqcount_t xfrm_state_hash_generation = SEQCNT_ZERO(xfrm_state_hash_generation); static struct kmem_cache *xfrm_state_cache __ro_after_init; static DECLARE_WORK(xfrm_state_gc_work, xfrm_state_gc_task); @@ -140,7 +139,7 @@ static void xfrm_hash_resize(struct work_struct *work) } spin_lock_bh(&net->xfrm.xfrm_state_lock); - write_seqcount_begin(&xfrm_state_hash_generation); + write_seqcount_begin(&net->xfrm.xfrm_state_hash_generation); nhashmask = (nsize / sizeof(struct hlist_head)) - 1U; odst = xfrm_state_deref_prot(net->xfrm.state_bydst, net); @@ -156,7 +155,7 @@ static void xfrm_hash_resize(struct work_struct *work) rcu_assign_pointer(net->xfrm.state_byspi, nspi); net->xfrm.state_hmask = nhashmask; - write_seqcount_end(&xfrm_state_hash_generation); + write_seqcount_end(&net->xfrm.xfrm_state_hash_generation); spin_unlock_bh(&net->xfrm.xfrm_state_lock); osize = (ohashmask + 1) * sizeof(struct hlist_head); @@ -1063,7 +1062,7 @@ xfrm_state_find(const xfrm_address_t *daddr, const xfrm_address_t *saddr, to_put = NULL; - sequence = read_seqcount_begin(&xfrm_state_hash_generation); + sequence = read_seqcount_begin(&net->xfrm.xfrm_state_hash_generation); rcu_read_lock(); h = xfrm_dst_hash(net, daddr, saddr, tmpl->reqid, encap_family); @@ -1176,7 +1175,7 @@ out: if (to_put) xfrm_state_put(to_put); - if (read_seqcount_retry(&xfrm_state_hash_generation, sequence)) { + if (read_seqcount_retry(&net->xfrm.xfrm_state_hash_generation, sequence)) { *err = -EAGAIN; if (x) { xfrm_state_put(x); @@ -2666,6 +2665,7 @@ int __net_init xfrm_state_init(struct net *net) net->xfrm.state_num = 0; INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); spin_lock_init(&net->xfrm.xfrm_state_lock); + seqcount_init(&net->xfrm.xfrm_state_hash_generation); return 0; out_byspi: From bc8e0adff343d992ca76d871e8b5e6cb86e1fad9 Mon Sep 17 00:00:00 2001 From: "Ahmed S. Darwish" Date: Tue, 16 Mar 2021 11:56:30 +0100 Subject: [PATCH 0318/1091] net: xfrm: Use sequence counter with associated spinlock A sequence counter write section must be serialized or its internal state can get corrupted. A plain seqcount_t does not contain the information of which lock must be held to guaranteee write side serialization. For xfrm_state_hash_generation, use seqcount_spinlock_t instead of plain seqcount_t. This allows to associate the spinlock used for write serialization with the sequence counter. It thus enables lockdep to verify that the write serialization lock is indeed held before entering the sequence counter write section. If lockdep is disabled, this lock association is compiled out and has neither storage size nor runtime overhead. Signed-off-by: Ahmed S. Darwish Signed-off-by: Steffen Klassert --- include/net/netns/xfrm.h | 2 +- net/xfrm/xfrm_state.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/net/netns/xfrm.h b/include/net/netns/xfrm.h index b59d73d529ba..e816b6a3ef2b 100644 --- a/include/net/netns/xfrm.h +++ b/include/net/netns/xfrm.h @@ -73,7 +73,7 @@ struct netns_xfrm { struct dst_ops xfrm6_dst_ops; #endif spinlock_t xfrm_state_lock; - seqcount_t xfrm_state_hash_generation; + seqcount_spinlock_t xfrm_state_hash_generation; spinlock_t xfrm_policy_lock; struct mutex xfrm_cfg_mutex; diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c index ffd315cff984..4496f7efa220 100644 --- a/net/xfrm/xfrm_state.c +++ b/net/xfrm/xfrm_state.c @@ -2665,7 +2665,8 @@ int __net_init xfrm_state_init(struct net *net) net->xfrm.state_num = 0; INIT_WORK(&net->xfrm.state_hash_work, xfrm_hash_resize); spin_lock_init(&net->xfrm.xfrm_state_lock); - seqcount_init(&net->xfrm.xfrm_state_hash_generation); + seqcount_spinlock_init(&net->xfrm.xfrm_state_hash_generation, + &net->xfrm.xfrm_state_lock); return 0; out_byspi: From 154deab6a3ba47792936edf77f2f13a1cbc4351d Mon Sep 17 00:00:00 2001 From: Xin Long Date: Fri, 19 Mar 2021 15:35:07 +0800 Subject: [PATCH 0319/1091] esp: delete NETIF_F_SCTP_CRC bit from features for esp offload Now in esp4/6_gso_segment(), before calling inner proto .gso_segment, NETIF_F_CSUM_MASK bits are deleted, as HW won't be able to do the csum for inner proto due to the packet encrypted already. So the UDP/TCP packet has to do the checksum on its own .gso_segment. But SCTP is using CRC checksum, and for that NETIF_F_SCTP_CRC should be deleted to make SCTP do the csum in own .gso_segment as well. In Xiumei's testing with SCTP over IPsec/veth, the packets are kept dropping due to the wrong CRC checksum. Reported-by: Xiumei Mu Fixes: 7862b4058b9f ("esp: Add gso handlers for esp4 and esp6") Signed-off-by: Xin Long Signed-off-by: Steffen Klassert --- net/ipv4/esp4_offload.c | 6 ++++-- net/ipv6/esp6_offload.c | 6 ++++-- 2 files changed, 8 insertions(+), 4 deletions(-) diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c index 601f5fbfc63f..ed3de486ea34 100644 --- a/net/ipv4/esp4_offload.c +++ b/net/ipv4/esp4_offload.c @@ -217,10 +217,12 @@ static struct sk_buff *esp4_gso_segment(struct sk_buff *skb, if ((!(skb->dev->gso_partial_features & NETIF_F_HW_ESP) && !(features & NETIF_F_HW_ESP)) || x->xso.dev != skb->dev) - esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK); + esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK | + NETIF_F_SCTP_CRC); else if (!(features & NETIF_F_HW_ESP_TX_CSUM) && !(skb->dev->gso_partial_features & NETIF_F_HW_ESP_TX_CSUM)) - esp_features = features & ~NETIF_F_CSUM_MASK; + esp_features = features & ~(NETIF_F_CSUM_MASK | + NETIF_F_SCTP_CRC); xo->flags |= XFRM_GSO_SEGMENT; diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c index 1ca516fb30e1..f35203ab39f5 100644 --- a/net/ipv6/esp6_offload.c +++ b/net/ipv6/esp6_offload.c @@ -254,9 +254,11 @@ static struct sk_buff *esp6_gso_segment(struct sk_buff *skb, skb->encap_hdr_csum = 1; if (!(features & NETIF_F_HW_ESP) || x->xso.dev != skb->dev) - esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK); + esp_features = features & ~(NETIF_F_SG | NETIF_F_CSUM_MASK | + NETIF_F_SCTP_CRC); else if (!(features & NETIF_F_HW_ESP_TX_CSUM)) - esp_features = features & ~NETIF_F_CSUM_MASK; + esp_features = features & ~(NETIF_F_CSUM_MASK | + NETIF_F_SCTP_CRC); xo->flags |= XFRM_GSO_SEGMENT; From 7e71b48f9e27e437ca523432ea285c2585a539dc Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 19 Mar 2021 07:10:42 +0530 Subject: [PATCH 0320/1091] ASoC: amd: Add support for RT5682 codec in machine driver Add support for RT5682 codec in machine driver. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/1616118056-5506-1-git-send-email-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 5 +- sound/soc/amd/acp-da7219-max98357a.c | 355 +++++++++++++++++++++++++-- 2 files changed, 344 insertions(+), 16 deletions(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index a6ce000fac3f..43f5d29d7c53 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -5,14 +5,15 @@ config SND_SOC_AMD_ACP This option enables ACP DMA support on AMD platform. config SND_SOC_AMD_CZ_DA7219MX98357_MACH - tristate "AMD CZ support for DA7219 and MAX9835" + tristate "AMD CZ support for DA7219, RT5682 and MAX9835" select SND_SOC_DA7219 + select SND_SOC_RT5682_I2C select SND_SOC_MAX98357A select SND_SOC_ADAU7002 select REGULATOR depends on SND_SOC_AMD_ACP && I2C && GPIOLIB help - This option enables machine driver for DA7219 and MAX9835. + This option enables machine driver for DA7219, RT5682 and MAX9835. config SND_SOC_AMD_CZ_RT5645_MACH tristate "AMD CZ support for RT5645" diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index 849288d01c6b..e65e007fc604 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -41,14 +41,19 @@ #include "acp.h" #include "../codecs/da7219.h" #include "../codecs/da7219-aad.h" +#include "../codecs/rt5682.h" #define CZ_PLAT_CLK 48000000 #define DUAL_CHANNEL 2 +#define RT5682_PLL_FREQ (48000 * 512) static struct snd_soc_jack cz_jack; static struct clk *da7219_dai_wclk; static struct clk *da7219_dai_bclk; +static struct clk *rt5682_dai_wclk; +static struct clk *rt5682_dai_bclk; extern bool bt_uart_enable; +void *acp_soc_is_rltk_max(struct device *dev); static int cz_da7219_init(struct snd_soc_pcm_runtime *rtd) { @@ -128,6 +133,96 @@ static void da7219_clk_disable(void) clk_disable_unprepare(da7219_dai_bclk); } +static int cz_rt5682_init(struct snd_soc_pcm_runtime *rtd) +{ + int ret; + struct snd_soc_card *card = rtd->card; + struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); + struct snd_soc_component *component = codec_dai->component; + + dev_info(codec_dai->dev, "codec dai name = %s\n", codec_dai->name); + + /* Set codec sysclk */ + ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL2, + RT5682_PLL_FREQ, SND_SOC_CLOCK_IN); + if (ret < 0) { + dev_err(codec_dai->dev, + "Failed to set rt5682 SYSCLK: %d\n", ret); + return ret; + } + /* set codec PLL */ + ret = snd_soc_dai_set_pll(codec_dai, RT5682_PLL2, RT5682_PLL2_S_MCLK, + CZ_PLAT_CLK, RT5682_PLL_FREQ); + if (ret < 0) { + dev_err(codec_dai->dev, "can't set rt5682 PLL: %d\n", ret); + return ret; + } + + rt5682_dai_wclk = devm_clk_get(component->dev, "rt5682-dai-wclk"); + if (IS_ERR(rt5682_dai_wclk)) + return PTR_ERR(rt5682_dai_wclk); + + rt5682_dai_bclk = devm_clk_get(component->dev, "rt5682-dai-bclk"); + if (IS_ERR(rt5682_dai_bclk)) + return PTR_ERR(rt5682_dai_bclk); + + ret = snd_soc_card_jack_new(card, "Headset Jack", + SND_JACK_HEADSET | SND_JACK_LINEOUT | + SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3, + &cz_jack, NULL, 0); + if (ret) { + dev_err(card->dev, "HP jack creation failed %d\n", ret); + return ret; + } + + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_1, KEY_VOLUMEUP); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_2, KEY_VOLUMEDOWN); + snd_jack_set_key(cz_jack.jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + ret = snd_soc_component_set_jack(component, &cz_jack, NULL); + if (ret) { + dev_err(rtd->dev, "Headset Jack call-back failed: %d\n", ret); + return ret; + } + return 0; +} + +static int rt5682_clk_enable(struct snd_pcm_substream *substream) +{ + int ret; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + + /* + * Set wclk to 48000 because the rate constraint of this driver is + * 48000. ADAU7002 spec: "The ADAU7002 requires a BCLK rate that is + * minimum of 64x the LRCLK sample rate." RT5682 is the only clk + * source so for all codecs we have to limit bclk to 64X lrclk. + */ + ret = clk_set_rate(rt5682_dai_wclk, 48000); + if (ret) { + dev_err(rtd->dev, "Error setting wclk rate: %d\n", ret); + return ret; + } + ret = clk_set_rate(rt5682_dai_bclk, 48000 * 64); + if (ret) { + dev_err(rtd->dev, "Error setting bclk rate: %d\n", ret); + return ret; + } + ret = clk_prepare_enable(rt5682_dai_wclk); + if (ret < 0) { + dev_err(rtd->dev, "can't enable wclk %d\n", ret); + return ret; + } + return ret; +} + +static void rt5682_clk_disable(void) +{ + clk_disable_unprepare(rt5682_dai_wclk); +} + static const unsigned int channels[] = { DUAL_CHANNEL, }; @@ -260,6 +355,118 @@ static void cz_da7219_shutdown(struct snd_pcm_substream *substream) da7219_clk_disable(); } +static int cz_rt5682_play_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->play_i2s_instance = I2S_SP_INSTANCE; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_cap_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL1; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_max_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->play_i2s_instance = I2S_BT_INSTANCE; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_dmic0_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_BT_INSTANCE; + return rt5682_clk_enable(substream); +} + +static int cz_rt5682_dmic1_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_card *card = rtd->card; + struct acp_platform_info *machine = snd_soc_card_get_drvdata(card); + + /* + * On this platform for PCM device we support stereo + */ + + runtime->hw.channels_max = DUAL_CHANNEL; + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_channels); + snd_pcm_hw_constraint_list(runtime, 0, SNDRV_PCM_HW_PARAM_RATE, + &constraints_rates); + + machine->cap_i2s_instance = I2S_SP_INSTANCE; + machine->capture_channel = CAP_CHANNEL0; + return rt5682_clk_enable(substream); +} + +static void cz_rt5682_shutdown(struct snd_pcm_substream *substream) +{ + rt5682_clk_disable(); +} + static const struct snd_soc_ops cz_da7219_play_ops = { .startup = cz_da7219_play_startup, .shutdown = cz_da7219_shutdown, @@ -285,6 +492,31 @@ static const struct snd_soc_ops cz_dmic1_cap_ops = { .shutdown = cz_da7219_shutdown, }; +static const struct snd_soc_ops cz_rt5682_play_ops = { + .startup = cz_rt5682_play_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_cap_ops = { + .startup = cz_rt5682_cap_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_max_play_ops = { + .startup = cz_rt5682_max_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_dmic0_cap_ops = { + .startup = cz_rt5682_dmic0_startup, + .shutdown = cz_rt5682_shutdown, +}; + +static const struct snd_soc_ops cz_rt5682_dmic1_cap_ops = { + .startup = cz_rt5682_dmic1_startup, + .shutdown = cz_rt5682_shutdown, +}; + SND_SOC_DAILINK_DEF(designware1, DAILINK_COMP_ARRAY(COMP_CPU("designware-i2s.1.auto"))); SND_SOC_DAILINK_DEF(designware2, @@ -294,6 +526,8 @@ SND_SOC_DAILINK_DEF(designware3, SND_SOC_DAILINK_DEF(dlgs, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-DLGS7219:00", "da7219-hifi"))); +SND_SOC_DAILINK_DEF(rt5682, + DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); SND_SOC_DAILINK_DEF(mx, DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); SND_SOC_DAILINK_DEF(adau, @@ -353,6 +587,57 @@ static struct snd_soc_dai_link cz_dai_7219_98357[] = { }, }; +static struct snd_soc_dai_link cz_dai_5682_98357[] = { + { + .name = "amd-rt5682-play", + .stream_name = "Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .init = cz_rt5682_init, + .dpcm_playback = 1, + .ops = &cz_rt5682_play_ops, + SND_SOC_DAILINK_REG(designware1, rt5682, platform), + }, + { + .name = "amd-rt5682-cap", + .stream_name = "Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_capture = 1, + .ops = &cz_rt5682_cap_ops, + SND_SOC_DAILINK_REG(designware2, rt5682, platform), + }, + { + .name = "amd-max98357-play", + .stream_name = "HiFi Playback", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_playback = 1, + .ops = &cz_rt5682_max_play_ops, + SND_SOC_DAILINK_REG(designware3, mx, platform), + }, + { + /* C panel DMIC */ + .name = "dmic0", + .stream_name = "DMIC0 Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_capture = 1, + .ops = &cz_rt5682_dmic0_cap_ops, + SND_SOC_DAILINK_REG(designware3, adau, platform), + }, + { + /* A/B panel DMIC */ + .name = "dmic1", + .stream_name = "DMIC1 Capture", + .dai_fmt = SND_SOC_DAIFMT_I2S | SND_SOC_DAIFMT_NB_NF + | SND_SOC_DAIFMT_CBM_CFM, + .dpcm_capture = 1, + .ops = &cz_rt5682_dmic1_cap_ops, + SND_SOC_DAILINK_REG(designware2, adau, platform), + }, +}; + static const struct snd_soc_dapm_widget cz_widgets[] = { SND_SOC_DAPM_HP("Headphones", NULL), SND_SOC_DAPM_SPK("Speakers", NULL), @@ -368,6 +653,14 @@ static const struct snd_soc_dapm_route cz_audio_route[] = { {"PDM_DAT", NULL, "Int Mic"}, }; +static const struct snd_soc_dapm_route cz_rt5682_audio_route[] = { + {"Headphones", NULL, "HPOL"}, + {"Headphones", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Speakers", NULL, "Speaker"}, + {"PDM_DAT", NULL, "Int Mic"}, +}; + static const struct snd_kcontrol_new cz_mc_controls[] = { SOC_DAPM_PIN_SWITCH("Headphones"), SOC_DAPM_PIN_SWITCH("Speakers"), @@ -388,6 +681,28 @@ static struct snd_soc_card cz_card = { .num_controls = ARRAY_SIZE(cz_mc_controls), }; +static struct snd_soc_card cz_rt5682_card = { + .name = "acpr5682m98357", + .owner = THIS_MODULE, + .dai_link = cz_dai_5682_98357, + .num_links = ARRAY_SIZE(cz_dai_5682_98357), + .dapm_widgets = cz_widgets, + .num_dapm_widgets = ARRAY_SIZE(cz_widgets), + .dapm_routes = cz_rt5682_audio_route, + .controls = cz_mc_controls, + .num_controls = ARRAY_SIZE(cz_mc_controls), +}; + +void *acp_soc_is_rltk_max(struct device *dev) +{ + const struct acpi_device_id *match; + + match = acpi_match_device(dev->driver->acpi_match_table, dev); + if (!match) + return NULL; + return (void *)match->driver_data; +} + static struct regulator_consumer_supply acp_da7219_supplies[] = { REGULATOR_SUPPLY("VDD", "i2c-DLGS7219:00"), REGULATOR_SUPPLY("VDDMIC", "i2c-DLGS7219:00"), @@ -425,29 +740,39 @@ static int cz_probe(struct platform_device *pdev) struct snd_soc_card *card; struct acp_platform_info *machine; struct regulator_dev *rdev; + struct device *dev = &pdev->dev; - acp_da7219_cfg.dev = &pdev->dev; - rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc, - &acp_da7219_cfg); - if (IS_ERR(rdev)) { - dev_err(&pdev->dev, "Failed to register regulator: %d\n", - (int)PTR_ERR(rdev)); - return -EINVAL; + card = (struct snd_soc_card *)acp_soc_is_rltk_max(dev); + if (!card) + return -ENODEV; + if (!strcmp(card->name, "acpd7219m98357")) { + acp_da7219_cfg.dev = &pdev->dev; + rdev = devm_regulator_register(&pdev->dev, &acp_da7219_desc, + &acp_da7219_cfg); + if (IS_ERR(rdev)) { + dev_err(&pdev->dev, "Failed to register regulator: %d\n", + (int)PTR_ERR(rdev)); + return -EINVAL; + } } machine = devm_kzalloc(&pdev->dev, sizeof(struct acp_platform_info), GFP_KERNEL); if (!machine) return -ENOMEM; - card = &cz_card; - cz_card.dev = &pdev->dev; + card->dev = &pdev->dev; platform_set_drvdata(pdev, card); snd_soc_card_set_drvdata(card, machine); - ret = devm_snd_soc_register_card(&pdev->dev, &cz_card); + ret = devm_snd_soc_register_card(&pdev->dev, card); if (ret) { - dev_err(&pdev->dev, + if (ret != -EPROBE_DEFER) + dev_err(&pdev->dev, "devm_snd_soc_register_card(%s) failed: %d\n", - cz_card.name, ret); + card->name, ret); + else + dev_dbg(&pdev->dev, + "devm_snd_soc_register_card(%s) probe deferred: %d\n", + card->name, ret); return ret; } bt_uart_enable = !device_property_read_bool(&pdev->dev, @@ -457,7 +782,8 @@ static int cz_probe(struct platform_device *pdev) #ifdef CONFIG_ACPI static const struct acpi_device_id cz_audio_acpi_match[] = { - { "AMD7219", 0 }, + { "AMD7219", (unsigned long)&cz_card }, + { "AMDI5682", (unsigned long)&cz_rt5682_card}, {}, }; MODULE_DEVICE_TABLE(acpi, cz_audio_acpi_match); @@ -475,5 +801,6 @@ static struct platform_driver cz_pcm_driver = { module_platform_driver(cz_pcm_driver); MODULE_AUTHOR("akshu.agrawal@amd.com"); -MODULE_DESCRIPTION("DA7219 & MAX98357A audio support"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("DA7219, RT5682 & MAX98357A audio support"); MODULE_LICENSE("GPL v2"); From 2277e7e36b4b8c27eb8d2fb33a20440bc800c2d7 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 19 Mar 2021 16:06:43 +0800 Subject: [PATCH 0321/1091] ASoC: fsl_sai: Don't use devm_regmap_init_mmio_clk When there is power domain bind with bus clock, The call flow: devm_regmap_init_mmio_clk - clk_prepare() - clk_pm_runtime_get() cause the power domain of clock always be enabled after regmap_init(). which impact the power consumption. So use devm_regmap_init_mmio instead of devm_regmap_init_mmio_clk, then explicitly enable clock when using by pm_runtime_get(), if CONFIG_PM=n, then fsl_sai_runtime_resume will be explicitly called. Signed-off-by: Shengjiu Wang Signed-off-by: Viorel Suman Link: https://lore.kernel.org/r/1616141203-13344-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_sai.c | 48 +++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/sound/soc/fsl/fsl_sai.c b/sound/soc/fsl/fsl_sai.c index 6ef2ce348232..407a45e48eee 100644 --- a/sound/soc/fsl/fsl_sai.c +++ b/sound/soc/fsl/fsl_sai.c @@ -994,6 +994,9 @@ static int fsl_sai_check_version(struct device *dev) return 0; } +static int fsl_sai_runtime_suspend(struct device *dev); +static int fsl_sai_runtime_resume(struct device *dev); + static int fsl_sai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1026,24 +1029,21 @@ static int fsl_sai_probe(struct platform_device *pdev) ARRAY_SIZE(fsl_sai_reg_defaults_ofs8); } - sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, - "bus", base, &fsl_sai_regmap_config); - - /* Compatible with old DTB cases */ - if (IS_ERR(sai->regmap) && PTR_ERR(sai->regmap) != -EPROBE_DEFER) - sai->regmap = devm_regmap_init_mmio_clk(&pdev->dev, - "sai", base, &fsl_sai_regmap_config); + sai->regmap = devm_regmap_init_mmio(&pdev->dev, base, &fsl_sai_regmap_config); if (IS_ERR(sai->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); return PTR_ERR(sai->regmap); } - /* No error out for old DTB cases but only mark the clock NULL */ sai->bus_clk = devm_clk_get(&pdev->dev, "bus"); + /* Compatible with old DTB cases */ + if (IS_ERR(sai->bus_clk) && PTR_ERR(sai->bus_clk) != -EPROBE_DEFER) + sai->bus_clk = devm_clk_get(&pdev->dev, "sai"); if (IS_ERR(sai->bus_clk)) { dev_err(&pdev->dev, "failed to get bus clock: %ld\n", PTR_ERR(sai->bus_clk)); - sai->bus_clk = NULL; + /* -EPROBE_DEFER */ + return PTR_ERR(sai->bus_clk); } for (i = 1; i < FSL_SAI_MCLK_MAX; i++) { @@ -1124,6 +1124,18 @@ static int fsl_sai_probe(struct platform_device *pdev) sai->dma_params_tx.maxburst = FSL_SAI_MAXBURST_TX; platform_set_drvdata(pdev, sai); + pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + ret = fsl_sai_runtime_resume(&pdev->dev); + if (ret) + goto err_pm_disable; + } + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); + goto err_pm_get_sync; + } /* Get sai version */ ret = fsl_sai_check_version(&pdev->dev); @@ -1137,26 +1149,30 @@ static int fsl_sai_probe(struct platform_device *pdev) FSL_SAI_MCTL_MCLK_EN, FSL_SAI_MCTL_MCLK_EN); } - pm_runtime_enable(&pdev->dev); - regcache_cache_only(sai->regmap, true); + ret = pm_runtime_put_sync(&pdev->dev); + if (ret < 0) + goto err_pm_get_sync; ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, &sai->cpu_dai_drv, 1); if (ret) - goto err_pm_disable; + goto err_pm_get_sync; if (sai->soc_data->use_imx_pcm) { ret = imx_pcm_dma_init(pdev, IMX_SAI_DMABUF_SIZE); if (ret) - goto err_pm_disable; + goto err_pm_get_sync; } else { ret = devm_snd_dmaengine_pcm_register(&pdev->dev, NULL, 0); if (ret) - goto err_pm_disable; + goto err_pm_get_sync; } return ret; +err_pm_get_sync: + if (!pm_runtime_status_suspended(&pdev->dev)) + fsl_sai_runtime_suspend(&pdev->dev); err_pm_disable: pm_runtime_disable(&pdev->dev); @@ -1166,6 +1182,8 @@ err_pm_disable: static int fsl_sai_remove(struct platform_device *pdev) { pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + fsl_sai_runtime_suspend(&pdev->dev); return 0; } @@ -1226,7 +1244,6 @@ static const struct of_device_id fsl_sai_ids[] = { }; MODULE_DEVICE_TABLE(of, fsl_sai_ids); -#ifdef CONFIG_PM static int fsl_sai_runtime_suspend(struct device *dev) { struct fsl_sai *sai = dev_get_drvdata(dev); @@ -1299,7 +1316,6 @@ disable_bus_clk: return ret; } -#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_sai_pm_ops = { SET_RUNTIME_PM_OPS(fsl_sai_runtime_suspend, From b951b51e2ca4d37dc9781e14d8a49d2f2b7e715b Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 19 Mar 2021 14:49:49 +0200 Subject: [PATCH 0322/1091] ASoC: SOF: add a helper to get topology configured mclk Add helper sof_dai_ssp_mclk to get the topology configured MCLK from a pcm_runtime, return 0 if it is not available, and error if the dai type is not SSP at the moment. Export the helper for external use, e.g. from machine drivers. Signed-off-by: Keyon Jie Reviewed-by: Guennadi Liakhovetski Reviewed-by: Daniel Baluta Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210319124950.3853994-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 1 + sound/soc/sof/sof-audio.c | 27 +++++++++++++++++++++++++++ 2 files changed, 28 insertions(+) diff --git a/include/sound/sof.h b/include/sound/sof.h index 646a655c3c6b..b93bb8038080 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -103,5 +103,6 @@ struct sof_dev_desc { int sof_nocodec_setup(struct device *dev, const struct snd_sof_dsp_ops *ops, int (*pcm_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params)); +int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd); #endif diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 3277489fee5e..928d7a46d820 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -433,6 +433,33 @@ struct snd_sof_dai *snd_sof_find_dai(struct snd_soc_component *scomp, return NULL; } +/* + * Helper to get SSP MCLK from a pcm_runtime. + * Return 0 if not exist. + */ +int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd) +{ + struct snd_soc_component *component = + snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); + struct snd_sof_dai *dai = + snd_sof_find_dai(component, (char *)rtd->dai_link->name); + + /* use the tplg configured mclk if existed */ + if (!dai || !dai->dai_config) + return 0; + + switch (dai->dai_config->type) { + case SOF_DAI_INTEL_SSP: + return dai->dai_config->ssp.mclk_rate; + default: + /* not yet implemented for platforms other than the above */ + dev_err(rtd->dev, "mclk for dai_config->type %d not supported yet!\n", + dai->dai_config->type); + return -EINVAL; + } +} +EXPORT_SYMBOL(sof_dai_get_mclk); + /* * SOF Driver enumeration. */ From bf939446c357242b3306e88c5f48976940d29679 Mon Sep 17 00:00:00 2001 From: Keyon Jie Date: Fri, 19 Mar 2021 14:49:50 +0200 Subject: [PATCH 0323/1091] ASoC: intel: sof_rt5682: use the topology mclk We should use the topology configured mclk if it existed, which can make sure we are aligned with the FW side about the mclk usage. Signed-off-by: Keyon Jie Reviewed-by: Guennadi Liakhovetski Reviewed-by: Daniel Baluta Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210319124950.3853994-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_rt5682.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/boards/sof_rt5682.c b/sound/soc/intel/boards/sof_rt5682.c index f4b898c1719f..58548ea0d915 100644 --- a/sound/soc/intel/boards/sof_rt5682.c +++ b/sound/soc/intel/boards/sof_rt5682.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include "../../codecs/rt1015.h" @@ -268,10 +269,21 @@ static int sof_rt5682_hw_params(struct snd_pcm_substream *substream, } clk_id = RT5682_PLL1_S_MCLK; - if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ) + + /* get the tplg configured mclk. */ + clk_freq = sof_dai_get_mclk(rtd); + + /* mclk from the quirk is the first choice */ + if (sof_rt5682_quirk & SOF_RT5682_MCLK_24MHZ) { + if (clk_freq != 24000000) + dev_warn(rtd->dev, "configure wrong mclk in tplg, please use 24MHz.\n"); clk_freq = 24000000; - else + } else if (clk_freq == 0) { + /* use default mclk if not specified correct in topology */ clk_freq = 19200000; + } else if (clk_freq < 0) { + return clk_freq; + } } else { clk_id = RT5682_PLL1_S_BCLK1; clk_freq = params_rate(params) * 50; From 9de82caad0282205d4c38a39456bce58e3219540 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Mar 2021 12:44:58 +0100 Subject: [PATCH 0324/1091] dax: avoid -Wempty-body warnings gcc warns about an empty body in an else statement: drivers/dax/bus.c: In function 'do_id_store': drivers/dax/bus.c:94:48: error: suggest braces around empty body in an 'else' statement [-Werror=empty-body] 94 | /* nothing to remove */; | ^ drivers/dax/bus.c:99:43: error: suggest braces around empty body in an 'else' statement [-Werror=empty-body] 99 | /* dax_id already added */; | ^ In both of these cases, the 'else' exists only to have a place to add a comment, but that comment doesn't really explain that much either, so the easiest way to shut up that warning is to just remove the else. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210322114514.3490752-1-arnd@kernel.org Signed-off-by: Dan Williams --- drivers/dax/bus.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/drivers/dax/bus.c b/drivers/dax/bus.c index 452e85ae87a8..5aee26e1bbd6 100644 --- a/drivers/dax/bus.c +++ b/drivers/dax/bus.c @@ -90,13 +90,11 @@ static ssize_t do_id_store(struct device_driver *drv, const char *buf, list_add(&dax_id->list, &dax_drv->ids); } else rc = -ENOMEM; - } else - /* nothing to remove */; + } } else if (action == ID_REMOVE) { list_del(&dax_id->list); kfree(dax_id); - } else - /* dax_id already added */; + } mutex_unlock(&dax_bus_lock); if (rc < 0) From 46e152186cd89d940b26726fff11eb3f4935b45a Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Mon, 1 Mar 2021 20:05:48 +0800 Subject: [PATCH 0325/1091] arc: kernel: Return -EFAULT if copy_to_user() fails The copy_to_user() function returns the number of bytes remaining to be copied, but we want to return -EFAULT if the copy doesn't complete. Signed-off-by: Wang Qing Signed-off-by: Vineet Gupta --- arch/arc/kernel/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arc/kernel/signal.c b/arch/arc/kernel/signal.c index a78d8f745a67..fdbe06c98895 100644 --- a/arch/arc/kernel/signal.c +++ b/arch/arc/kernel/signal.c @@ -96,7 +96,7 @@ stash_usr_regs(struct rt_sigframe __user *sf, struct pt_regs *regs, sizeof(sf->uc.uc_mcontext.regs.scratch)); err |= __copy_to_user(&sf->uc.uc_sigmask, set, sizeof(sigset_t)); - return err; + return err ? -EFAULT : 0; } static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) @@ -110,7 +110,7 @@ static int restore_usr_regs(struct pt_regs *regs, struct rt_sigframe __user *sf) &(sf->uc.uc_mcontext.regs.scratch), sizeof(sf->uc.uc_mcontext.regs.scratch)); if (err) - return err; + return -EFAULT; set_current_blocked(&set); regs->bta = uregs.scratch.bta; From 83520d62cc5a94d2ff0e2d37c8204fca13dd2637 Mon Sep 17 00:00:00 2001 From: "dean.yang_cp" Date: Tue, 23 Feb 2021 10:00:31 +0800 Subject: [PATCH 0326/1091] ARC: treewide: avoid the pointer addition with NULL pointer Signed-off-by: dean.yang_cp Acked-by: Vineet Gupta Signed-off-by: Vineet Gupta --- arch/arc/kernel/unwind.c | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/arch/arc/kernel/unwind.c b/arch/arc/kernel/unwind.c index 74ad4256022e..47bab67f8649 100644 --- a/arch/arc/kernel/unwind.c +++ b/arch/arc/kernel/unwind.c @@ -187,25 +187,26 @@ static void init_unwind_table(struct unwind_table *table, const char *name, const void *table_start, unsigned long table_size, const u8 *header_start, unsigned long header_size) { - const u8 *ptr = header_start + 4; - const u8 *end = header_start + header_size; - table->core.pc = (unsigned long)core_start; table->core.range = core_size; table->init.pc = (unsigned long)init_start; table->init.range = init_size; table->address = table_start; table->size = table_size; - - /* See if the linker provided table looks valid. */ - if (header_size <= 4 - || header_start[0] != 1 - || (void *)read_pointer(&ptr, end, header_start[1]) != table_start - || header_start[2] == DW_EH_PE_omit - || read_pointer(&ptr, end, header_start[2]) <= 0 - || header_start[3] == DW_EH_PE_omit) - header_start = NULL; - + /* To avoid the pointer addition with NULL pointer.*/ + if (header_start != NULL) { + const u8 *ptr = header_start + 4; + const u8 *end = header_start + header_size; + /* See if the linker provided table looks valid. */ + if (header_size <= 4 + || header_start[0] != 1 + || (void *)read_pointer(&ptr, end, header_start[1]) + != table_start + || header_start[2] == DW_EH_PE_omit + || read_pointer(&ptr, end, header_start[2]) <= 0 + || header_start[3] == DW_EH_PE_omit) + header_start = NULL; + } table->hdrsz = header_size; smp_wmb(); table->header = header_start; From 6d48b7912cc72275dc7c59ff961c8bac7ef66a92 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 22 Mar 2021 12:55:25 +0100 Subject: [PATCH 0327/1091] lockdep: Address clang -Wformat warning printing for %hd Clang doesn't like format strings that truncate a 32-bit value to something shorter: kernel/locking/lockdep.c:709:4: error: format specifies type 'short' but the argument has type 'int' [-Werror,-Wformat] In this case, the warning is a slightly questionable, as it could realize that both class->wait_type_outer and class->wait_type_inner are in fact 8-bit struct members, even though the result of the ?: operator becomes an 'int'. However, there is really no point in printing the number as a 16-bit 'short' rather than either an 8-bit or 32-bit number, so just change it to a normal %d. Fixes: de8f5e4f2dc1 ("lockdep: Introduce wait-type checks") Signed-off-by: Arnd Bergmann Signed-off-by: Ingo Molnar Link: https://lore.kernel.org/r/20210322115531.3987555-1-arnd@kernel.org --- kernel/locking/lockdep.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/locking/lockdep.c b/kernel/locking/lockdep.c index c30eb887ca7d..f160f1c97ca1 100644 --- a/kernel/locking/lockdep.c +++ b/kernel/locking/lockdep.c @@ -705,7 +705,7 @@ static void print_lock_name(struct lock_class *class) printk(KERN_CONT " ("); __print_lock_name(class); - printk(KERN_CONT "){%s}-{%hd:%hd}", usage, + printk(KERN_CONT "){%s}-{%d:%d}", usage, class->wait_type_outer ?: class->wait_type_inner, class->wait_type_inner); } From e834df6cfc71d8e5ce2c27a0184145ea125c3f0f Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 15 Mar 2021 03:00:44 -0500 Subject: [PATCH 0328/1091] powerpc/pseries/mobility: use struct for shared state The atomic_t counter is the only shared state for the join/suspend sequence so far, but that will change. Contain it in a struct (pseries_suspend_info), and document its intended use. No functional change. Signed-off-by: Nathan Lynch Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20210315080045.460331-2-nathanl@linux.ibm.com --- arch/powerpc/platforms/pseries/mobility.c | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index ea4d6a660e0d..a6739ce9feac 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -452,9 +452,21 @@ static int do_suspend(void) return ret; } +/** + * struct pseries_suspend_info - State shared between CPUs for join/suspend. + * @counter: Threads are to increment this upon resuming from suspend + * or if an error is received from H_JOIN. The thread which performs + * the first increment (i.e. sets it to 1) is responsible for + * waking the other threads. + */ +struct pseries_suspend_info { + atomic_t counter; +}; + static int do_join(void *arg) { - atomic_t *counter = arg; + struct pseries_suspend_info *info = arg; + atomic_t *counter = &info->counter; long hvrc; int ret; @@ -535,11 +547,15 @@ static int pseries_suspend(u64 handle) int ret; while (true) { - atomic_t counter = ATOMIC_INIT(0); + struct pseries_suspend_info info; unsigned long vasi_state; int vasi_err; - ret = stop_machine(do_join, &counter, cpu_online_mask); + info = (struct pseries_suspend_info) { + .counter = ATOMIC_INIT(0), + }; + + ret = stop_machine(do_join, &info, cpu_online_mask); if (ret == 0) break; /* From 274cb1ca2e7ce02cab56f5f4c61a74aeb566f931 Mon Sep 17 00:00:00 2001 From: Nathan Lynch Date: Mon, 15 Mar 2021 03:00:45 -0500 Subject: [PATCH 0329/1091] powerpc/pseries/mobility: handle premature return from H_JOIN The pseries join/suspend sequence in its current form was written with the assumption that it was the only user of H_PROD and that it needn't handle spurious successful returns from H_JOIN. That's wrong; powerpc's paravirt spinlock code uses H_PROD, and CPUs entering do_join() can be woken prematurely from H_JOIN with a status of H_SUCCESS as a result. This causes all CPUs to exit the sequence early, preventing suspend from occurring at all. Add a 'done' boolean flag to the pseries_suspend_info struct, and have the waking thread set it before waking the other threads. Threads which receive H_SUCCESS from H_JOIN retry if the 'done' flag is still unset. Fixes: 9327dc0aeef3 ("powerpc/pseries/mobility: use stop_machine for join/suspend") Signed-off-by: Nathan Lynch Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20210315080045.460331-3-nathanl@linux.ibm.com --- arch/powerpc/platforms/pseries/mobility.c | 26 ++++++++++++++++++++++- 1 file changed, 25 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/mobility.c b/arch/powerpc/platforms/pseries/mobility.c index a6739ce9feac..e83e0891272d 100644 --- a/arch/powerpc/platforms/pseries/mobility.c +++ b/arch/powerpc/platforms/pseries/mobility.c @@ -458,9 +458,12 @@ static int do_suspend(void) * or if an error is received from H_JOIN. The thread which performs * the first increment (i.e. sets it to 1) is responsible for * waking the other threads. + * @done: False if join/suspend is in progress. True if the operation is + * complete (successful or not). */ struct pseries_suspend_info { atomic_t counter; + bool done; }; static int do_join(void *arg) @@ -470,6 +473,7 @@ static int do_join(void *arg) long hvrc; int ret; +retry: /* Must ensure MSR.EE off for H_JOIN. */ hard_irq_disable(); hvrc = plpar_hcall_norets(H_JOIN); @@ -485,8 +489,20 @@ static int do_join(void *arg) case H_SUCCESS: /* * The suspend is complete and this cpu has received a - * prod. + * prod, or we've received a stray prod from unrelated + * code (e.g. paravirt spinlocks) and we need to join + * again. + * + * This barrier orders the return from H_JOIN above vs + * the load of info->done. It pairs with the barrier + * in the wakeup/prod path below. */ + smp_mb(); + if (READ_ONCE(info->done) == false) { + pr_info_ratelimited("premature return from H_JOIN on CPU %i, retrying", + smp_processor_id()); + goto retry; + } ret = 0; break; case H_BAD_MODE: @@ -500,6 +516,13 @@ static int do_join(void *arg) if (atomic_inc_return(counter) == 1) { pr_info("CPU %u waking all threads\n", smp_processor_id()); + WRITE_ONCE(info->done, true); + /* + * This barrier orders the store to info->done vs subsequent + * H_PRODs to wake the other CPUs. It pairs with the barrier + * in the H_SUCCESS case above. + */ + smp_mb(); prod_others(); } /* @@ -553,6 +576,7 @@ static int pseries_suspend(u64 handle) info = (struct pseries_suspend_info) { .counter = ATOMIC_INIT(0), + .done = false, }; ret = stop_machine(do_join, &info, cpu_online_mask); From 2800aadc18a64c96b051bcb7da8a7df7d505db3f Mon Sep 17 00:00:00 2001 From: Jiri Kosina Date: Tue, 2 Mar 2021 11:26:55 +0100 Subject: [PATCH 0330/1091] iwlwifi: Fix softirq/hardirq disabling in iwl_pcie_enqueue_hcmd() It's possible for iwl_pcie_enqueue_hcmd() to be called with hard IRQs disabled (e.g. from LED core). We can't enable BHs in such a situation. Turn the unconditional BH-enable/BH-disable code into hardirq-disable/conditional-enable. This fixes the warning below. WARNING: CPU: 1 PID: 1139 at kernel/softirq.c:178 __local_bh_enable_ip+0xa5/0xf0 CPU: 1 PID: 1139 Comm: NetworkManager Not tainted 5.12.0-rc1-00004-gb4ded168af79 #7 Hardware name: LENOVO 20K5S22R00/20K5S22R00, BIOS R0IET38W (1.16 ) 05/31/2017 RIP: 0010:__local_bh_enable_ip+0xa5/0xf0 Code: f7 69 e8 ee 23 14 00 fb 66 0f 1f 44 00 00 65 8b 05 f0 f4 f7 69 85 c0 74 3f 48 83 c4 08 5b c3 65 8b 05 9b fe f7 69 85 c0 75 8e <0f> 0b eb 8a 48 89 3c 24 e8 4e 20 14 00 48 8b 3c 24 eb 91 e8 13 4e RSP: 0018:ffffafd580b13298 EFLAGS: 00010046 RAX: 0000000000000000 RBX: 0000000000000201 RCX: 0000000000000000 RDX: 0000000000000003 RSI: 0000000000000201 RDI: ffffffffc1272389 RBP: ffff96517ae4c018 R08: 0000000000000001 R09: 0000000000000000 R10: ffffafd580b13178 R11: 0000000000000001 R12: ffff96517b060000 R13: 0000000000000000 R14: ffffffff80000000 R15: 0000000000000001 FS: 00007fc604ebefc0(0000) GS:ffff965267480000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 000055fb3fef13b2 CR3: 0000000109112004 CR4: 00000000003706e0 Call Trace: ? _raw_spin_unlock_bh+0x1f/0x30 iwl_pcie_enqueue_hcmd+0x5d9/0xa00 [iwlwifi] iwl_trans_txq_send_hcmd+0x6c/0x430 [iwlwifi] iwl_trans_send_cmd+0x88/0x170 [iwlwifi] ? lock_acquire+0x277/0x3d0 iwl_mvm_send_cmd+0x32/0x80 [iwlmvm] iwl_mvm_led_set+0xc2/0xe0 [iwlmvm] ? led_trigger_event+0x46/0x70 led_trigger_event+0x46/0x70 ieee80211_do_open+0x5c5/0xa20 [mac80211] ieee80211_open+0x67/0x90 [mac80211] __dev_open+0xd4/0x150 __dev_change_flags+0x19e/0x1f0 dev_change_flags+0x23/0x60 do_setlink+0x30d/0x1230 ? lock_is_held_type+0xb4/0x120 ? __nla_validate_parse.part.7+0x57/0xcb0 ? __lock_acquire+0x2e1/0x1a50 __rtnl_newlink+0x560/0x910 ? __lock_acquire+0x2e1/0x1a50 ? __lock_acquire+0x2e1/0x1a50 ? lock_acquire+0x277/0x3d0 ? sock_def_readable+0x5/0x290 ? lock_is_held_type+0xb4/0x120 ? find_held_lock+0x2d/0x90 ? sock_def_readable+0xb3/0x290 ? lock_release+0x166/0x2a0 ? lock_is_held_type+0x90/0x120 rtnl_newlink+0x47/0x70 rtnetlink_rcv_msg+0x25c/0x470 ? netlink_deliver_tap+0x97/0x3e0 ? validate_linkmsg+0x350/0x350 netlink_rcv_skb+0x50/0x100 netlink_unicast+0x1b2/0x280 netlink_sendmsg+0x336/0x450 sock_sendmsg+0x5b/0x60 ____sys_sendmsg+0x1ed/0x250 ? copy_msghdr_from_user+0x5c/0x90 ___sys_sendmsg+0x88/0xd0 ? lock_is_held_type+0xb4/0x120 ? find_held_lock+0x2d/0x90 ? lock_release+0x166/0x2a0 ? __fget_files+0xfe/0x1d0 ? __sys_sendmsg+0x5e/0xa0 __sys_sendmsg+0x5e/0xa0 ? lockdep_hardirqs_on_prepare+0xd9/0x170 do_syscall_64+0x33/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7fc605c9572d Code: 28 89 54 24 1c 48 89 74 24 10 89 7c 24 08 e8 da ee ff ff 8b 54 24 1c 48 8b 74 24 10 41 89 c0 8b 7c 24 08 b8 2e 00 00 00 0f 05 <48> 3d 00 f0 ff ff 77 33 44 89 c7 48 89 44 24 08 e8 2e ef ff ff 48 RSP: 002b:00007fffc83789f0 EFLAGS: 00000293 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 000055ef468570c0 RCX: 00007fc605c9572d RDX: 0000000000000000 RSI: 00007fffc8378a30 RDI: 000000000000000c RBP: 0000000000000010 R08: 0000000000000000 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000293 R12: 0000000000000000 R13: 00007fffc8378b80 R14: 00007fffc8378b7c R15: 0000000000000000 irq event stamp: 170785 hardirqs last enabled at (170783): [] __local_bh_enable_ip+0x82/0xf0 hardirqs last disabled at (170784): [] _raw_read_lock_irqsave+0x8d/0x90 softirqs last enabled at (170782): [] iwl_pcie_enqueue_hcmd+0x5d9/0xa00 [iwlwifi] softirqs last disabled at (170785): [] iwl_pcie_enqueue_hcmd+0x116/0xa00 [iwlwifi] Signed-off-by: Jiri Kosina Tested-by: Sedat Dilek # LLVM/Clang v12.0.0-rc3 Acked-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/nycvar.YFH.7.76.2103021125430.12405@cbobk.fhfr.pm --- drivers/net/wireless/intel/iwlwifi/pcie/tx.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c index 381e8f90b6f2..7ae32491b5da 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/tx.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/tx.c @@ -928,6 +928,7 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, u32 cmd_pos; const u8 *cmddata[IWL_MAX_CMD_TBS_PER_TFD]; u16 cmdlen[IWL_MAX_CMD_TBS_PER_TFD]; + unsigned long flags; if (WARN(!trans->wide_cmd_header && group_id > IWL_ALWAYS_LONG_GROUP, @@ -1011,10 +1012,10 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, goto free_dup_buf; } - spin_lock_bh(&txq->lock); + spin_lock_irqsave(&txq->lock, flags); if (iwl_txq_space(trans, txq) < ((cmd->flags & CMD_ASYNC) ? 2 : 1)) { - spin_unlock_bh(&txq->lock); + spin_unlock_irqrestore(&txq->lock, flags); IWL_ERR(trans, "No space in command queue\n"); iwl_op_mode_cmd_queue_full(trans->op_mode); @@ -1174,7 +1175,7 @@ int iwl_pcie_enqueue_hcmd(struct iwl_trans *trans, unlock_reg: spin_unlock(&trans_pcie->reg_lock); out: - spin_unlock_bh(&txq->lock); + spin_unlock_irqrestore(&txq->lock, flags); free_dup_buf: if (idx < 0) kfree(dup_buf); From 8f6a70fd71a3d7a6b120f83681263fc370eb52ba Mon Sep 17 00:00:00 2001 From: Lorenzo Bianconi Date: Tue, 9 Mar 2021 11:09:03 +0100 Subject: [PATCH 0331/1091] mt76: mt7921: fix airtime reporting Fix {tx,rx}_airtime reporting for mt7921 driver. Wrong register definitions trigger a tx hangs before resetting airtime stats. Fixes: 163f4d22c118d ("mt76: mt7921: add MAC support") Tested-by: Leon Yen Signed-off-by: Lorenzo Bianconi Acked-by: Felix Fietkau Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/c05333be0e3e85a50a71bb2de81034fe425e3701.1615284335.git.lorenzo@kernel.org --- drivers/net/wireless/mediatek/mt76/mt7921/regs.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h index 18980bb32dee..6dad7f6ab09d 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7921/regs.h +++ b/drivers/net/wireless/mediatek/mt76/mt7921/regs.h @@ -135,10 +135,10 @@ #define MT_WTBLON_TOP_BASE 0x34000 #define MT_WTBLON_TOP(ofs) (MT_WTBLON_TOP_BASE + (ofs)) -#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x0) +#define MT_WTBLON_TOP_WDUCR MT_WTBLON_TOP(0x200) #define MT_WTBLON_TOP_WDUCR_GROUP GENMASK(2, 0) -#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x030) +#define MT_WTBL_UPDATE MT_WTBLON_TOP(0x230) #define MT_WTBL_UPDATE_WLAN_IDX GENMASK(9, 0) #define MT_WTBL_UPDATE_ADM_COUNT_CLEAR BIT(12) #define MT_WTBL_UPDATE_BUSY BIT(31) From bd83a2fc05ed323d7ae38443a6d2e253ef1c4237 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sat, 13 Mar 2021 15:36:35 +0100 Subject: [PATCH 0332/1091] brcmfmac: p2p: Fix recently introduced deadlock issue Commit a05829a7222e ("cfg80211: avoid holding the RTNL when calling the driver") replaced the rtnl_lock parameter passed to various brcmf functions with just lock, because since that commit it is not just about the rtnl_lock but also about the wiphy_lock . During this search/replace the "if (!rtnl_locked)" check in brcmfmac/p2p.c was accidentally replaced with "if (locked)", dropping the inversion of the check. This causes the code to now call rtnl_lock() while already holding the lock, causing a deadlock. Add back the "!" to the if-condition to fix this. Cc: Johannes Berg Fixes: a05829a7222e ("cfg80211: avoid holding the RTNL when calling the driver") Signed-off-by: Hans de Goede Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/20210313143635.109154-1-hdegoede@redhat.com --- drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c index 6d30a0fcecea..34cd8a7401fe 100644 --- a/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c +++ b/drivers/net/wireless/broadcom/brcm80211/brcmfmac/p2p.c @@ -2439,7 +2439,7 @@ void brcmf_p2p_ifp_removed(struct brcmf_if *ifp, bool locked) vif = ifp->vif; cfg = wdev_to_cfg(&vif->wdev); cfg->p2p.bss_idx[P2PAPI_BSSCFG_DEVICE].vif = NULL; - if (locked) { + if (!locked) { rtnl_lock(); wiphy_lock(cfg->wiphy); cfg80211_unregister_wdev(&vif->wdev); From 5e4010e36a58978e42b2ee13739ff9b50209c830 Mon Sep 17 00:00:00 2001 From: Shawn Guo Date: Thu, 11 Mar 2021 14:03:18 +0800 Subject: [PATCH 0333/1091] usb: dwc3: qcom: skip interconnect init for ACPI probe The ACPI probe starts failing since commit bea46b981515 ("usb: dwc3: qcom: Add interconnect support in dwc3 driver"), because there is no interconnect support for ACPI, and of_icc_get() call in dwc3_qcom_interconnect_init() will just return -EINVAL. Fix the problem by skipping interconnect init for ACPI probe, and then the NULL icc_path_ddr will simply just scheild all ICC calls. Fixes: bea46b981515 ("usb: dwc3: qcom: Add interconnect support in dwc3 driver") Signed-off-by: Shawn Guo Cc: stable Link: https://lore.kernel.org/r/20210311060318.25418-1-shawn.guo@linaro.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/dwc3-qcom.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-qcom.c b/drivers/usb/dwc3/dwc3-qcom.c index fcaf04483ad0..3de291ab951a 100644 --- a/drivers/usb/dwc3/dwc3-qcom.c +++ b/drivers/usb/dwc3/dwc3-qcom.c @@ -244,6 +244,9 @@ static int dwc3_qcom_interconnect_init(struct dwc3_qcom *qcom) struct device *dev = qcom->dev; int ret; + if (has_acpi_companion(dev)) + return 0; + qcom->icc_path_ddr = of_icc_get(dev, "usb-ddr"); if (IS_ERR(qcom->icc_path_ddr)) { dev_err(dev, "failed to get usb-ddr path: %ld\n", From cdb651b6021ee091abc24e9fbd9774d318ab96a6 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Mon, 8 Mar 2021 18:16:44 -0800 Subject: [PATCH 0334/1091] usb: dwc3: gadget: Set gadget_max_speed when set ssp_rate Set the dwc->gadget_max_speed to SuperSpeed Plus if the user sets the ssp_rate. The udc_set_ssp_rate() is intended for setting the gadget's speed to SuperSpeed Plus at the specified rate. Fixes: 072cab8a0fe2 ("usb: dwc3: gadget: Implement setting of SSP rate") Cc: Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/0b2732e2f380d9912ee87f39dc82c2139223bad9.1615254129.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4a337f348651..006476a4737b 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2523,6 +2523,7 @@ static void dwc3_gadget_set_ssp_rate(struct usb_gadget *g, unsigned long flags; spin_lock_irqsave(&dwc->lock, flags); + dwc->gadget_max_speed = USB_SPEED_SUPER_PLUS; dwc->gadget_ssp_rate = rate; spin_unlock_irqrestore(&dwc->lock, flags); } From 93f1d43c5767d70a1af89f54ef16a7d3e99af048 Mon Sep 17 00:00:00 2001 From: Thinh Nguyen Date: Mon, 8 Mar 2021 18:16:50 -0800 Subject: [PATCH 0335/1091] usb: dwc3: gadget: Use max speed if unspecified If the gadget driver doesn't specify a max_speed, then use the controller's maximum supported speed as default. For DWC_usb32 IP, the gadget's speed maybe limited to gen2x1 rate only if the driver's max_speed is unknown. This scenario should not occur with the current implementation since the default gadget driver's max_speed should always be specified. However, to make the driver more robust and help with readability, let's cover all the scenarios in __dwc3_gadget_set_speed(). Fixes: 450b9e9fabd8 ("usb: dwc3: gadget: Set speed only up to the max supported") Cc: Signed-off-by: Thinh Nguyen Link: https://lore.kernel.org/r/55ac7001af73bfe9bc750c6446ef4ac8cf6f9313.1615254129.git.Thinh.Nguyen@synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 006476a4737b..4c15c3fce303 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -2083,7 +2083,7 @@ static void __dwc3_gadget_set_speed(struct dwc3 *dwc) u32 reg; speed = dwc->gadget_max_speed; - if (speed > dwc->maximum_speed) + if (speed == USB_SPEED_UNKNOWN || speed > dwc->maximum_speed) speed = dwc->maximum_speed; if (speed == USB_SPEED_SUPER_PLUS && From b522f830d35189e0283fa4d5b4b3ef8d7a78cfcb Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Mon, 22 Mar 2021 14:52:44 +0200 Subject: [PATCH 0336/1091] usb: dwc3: pci: Enable dis_uX_susphy_quirk for Intel Merrifield It seems that on Intel Merrifield platform the USB PHY shouldn't be suspended. Otherwise it can't be enabled by simply change the cable in the connector. Enable corresponding quirk for the platform in question. Fixes: e5f4ca3fce90 ("usb: dwc3: ulpi: Fix USB2.0 HS/FS/LS PHY suspend regression") Suggested-by: Serge Semin Signed-off-by: Andy Shevchenko Link: https://lore.kernel.org/r/20210322125244.79407-1-andriy.shevchenko@linux.intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/dwc3-pci.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/dwc3/dwc3-pci.c b/drivers/usb/dwc3/dwc3-pci.c index 3d3918a8d5fb..4c5c6972124a 100644 --- a/drivers/usb/dwc3/dwc3-pci.c +++ b/drivers/usb/dwc3/dwc3-pci.c @@ -120,6 +120,8 @@ static const struct property_entry dwc3_pci_intel_properties[] = { static const struct property_entry dwc3_pci_mrfld_properties[] = { PROPERTY_ENTRY_STRING("dr_mode", "otg"), PROPERTY_ENTRY_STRING("linux,extcon-name", "mrfld_bcove_pwrsrc"), + PROPERTY_ENTRY_BOOL("snps,dis_u3_susphy_quirk"), + PROPERTY_ENTRY_BOOL("snps,dis_u2_susphy_quirk"), PROPERTY_ENTRY_BOOL("linux,sysdev_is_parent"), {} }; From 72035f4954f0bca2d8c47cf31b3629c42116f5b7 Mon Sep 17 00:00:00 2001 From: Tong Zhang Date: Wed, 17 Mar 2021 19:04:00 -0400 Subject: [PATCH 0337/1091] usb: gadget: udc: amd5536udc_pci fix null-ptr-dereference init_dma_pools() calls dma_pool_create(...dev->dev) to create dma pool. however, dev->dev is actually set after calling init_dma_pools(), which effectively makes dma_pool_create(..NULL) and cause crash. To fix this issue, init dma only after dev->dev is set. [ 1.317993] RIP: 0010:dma_pool_create+0x83/0x290 [ 1.323257] Call Trace: [ 1.323390] ? pci_write_config_word+0x27/0x30 [ 1.323626] init_dma_pools+0x41/0x1a0 [snps_udc_core] [ 1.323899] udc_pci_probe+0x202/0x2b1 [amd5536udc_pci] Fixes: 7c51247a1f62 (usb: gadget: udc: Provide correct arguments for 'dma_pool_create') Cc: stable Signed-off-by: Tong Zhang Link: https://lore.kernel.org/r/20210317230400.357756-1-ztong0001@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/gadget/udc/amd5536udc_pci.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/usb/gadget/udc/amd5536udc_pci.c b/drivers/usb/gadget/udc/amd5536udc_pci.c index 8d387e0e4d91..c80f9bd51b75 100644 --- a/drivers/usb/gadget/udc/amd5536udc_pci.c +++ b/drivers/usb/gadget/udc/amd5536udc_pci.c @@ -153,6 +153,11 @@ static int udc_pci_probe( pci_set_master(pdev); pci_try_set_mwi(pdev); + dev->phys_addr = resource; + dev->irq = pdev->irq; + dev->pdev = pdev; + dev->dev = &pdev->dev; + /* init dma pools */ if (use_dma) { retval = init_dma_pools(dev); @@ -160,11 +165,6 @@ static int udc_pci_probe( goto err_dma; } - dev->phys_addr = resource; - dev->irq = pdev->irq; - dev->pdev = pdev; - dev->dev = &pdev->dev; - /* general probing */ if (udc_probe(dev)) { retval = -ENODEV; From 08dff274edda54310d6f1cf27b62fddf0f8d146e Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 11 Mar 2021 14:37:14 +0100 Subject: [PATCH 0338/1091] cdc-acm: fix BREAK rx code path adding necessary calls Counting break events is nice but we should actually report them to the tty layer. Fixes: 5a6a62bdb9257 ("cdc-acm: add TIOCMIWAIT") Signed-off-by: Oliver Neukum Link: https://lore.kernel.org/r/20210311133714.31881-1-oneukum@suse.com Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 39ddb5585ded..b013671261a2 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -313,8 +313,10 @@ static void acm_process_notification(struct acm *acm, unsigned char *buf) acm->iocount.dsr++; if (difference & ACM_CTRL_DCD) acm->iocount.dcd++; - if (newctrl & ACM_CTRL_BRK) + if (newctrl & ACM_CTRL_BRK) { acm->iocount.brk++; + tty_insert_flip_char(&acm->port, 0, TTY_BREAK); + } if (newctrl & ACM_CTRL_RI) acm->iocount.rng++; if (newctrl & ACM_CTRL_FRAMING) From 6069e3e927c8fb3a1947b07d1a561644ea960248 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 11 Mar 2021 14:01:25 +0100 Subject: [PATCH 0339/1091] USB: cdc-acm: untangle a circular dependency between callback and softint We have a cycle of callbacks scheduling works which submit URBs with thos callbacks. This needs to be blocked, stopped and unblocked to untangle the circle. The issue leads to faults like: [ 55.068392] Unable to handle kernel paging request at virtual address 6b6b6c03 [ 55.075624] pgd = be866494 [ 55.078335] [6b6b6c03] *pgd=00000000 [ 55.081924] Internal error: Oops: 5 [#1] PREEMPT SMP ARM [ 55.087238] Modules linked in: ppp_async crc_ccitt ppp_generic slhc xt_TCPMSS xt_tcpmss xt_hl nf_log_ipv6 nf_log_ipv4 nf_log_common xt_policy xt_limit xt_conntrack xt_tcpudp xt_pkttype ip6table_mangle iptable_nat nf_nat nf_conntrack nf_defrag_ipv6 nf_defrag_ipv4 iptable_mangle ip6table_filter ip6_tables iptable_filter ip_tables des_generic md5 sch_fq_codel cdc_mbim cdc_wdm cdc_ncm usbnet mii cdc_acm usb_storage ip_tunnel xfrm_user xfrm6_tunnel tunnel6 xfrm4_tunnel tunnel4 esp6 esp4 ah6 ah4 xfrm_algo xt_LOG xt_LED xt_comment x_tables ipv6 [ 55.134954] CPU: 0 PID: 82 Comm: kworker/0:2 Tainted: G T 5.8.17 #1 [ 55.142526] Hardware name: Freescale i.MX7 Dual (Device Tree) [ 55.148304] Workqueue: events acm_softint [cdc_acm] [ 55.153196] PC is at kobject_get+0x10/0xa4 [ 55.157302] LR is at usb_get_dev+0x14/0x1c [ 55.161402] pc : [<8047c06c>] lr : [<80560448>] psr: 20000193 [ 55.167671] sp : bca39ea8 ip : 00007374 fp : bf6cbd80 [ 55.172899] r10: 00000000 r9 : bdd92284 r8 : bdd92008 [ 55.178128] r7 : 6b6b6b6b r6 : fffffffe r5 : 60000113 r4 : 6b6b6be3 [ 55.184658] r3 : 6b6b6b6b r2 : 00000111 r1 : 00000000 r0 : 6b6b6be3 [ 55.191191] Flags: nzCv IRQs off FIQs on Mode SVC_32 ISA ARM Segment none [ 55.198417] Control: 10c5387d Table: bcf0c06a DAC: 00000051 [ 55.204168] Process kworker/0:2 (pid: 82, stack limit = 0x9bdd2a89) [ 55.210439] Stack: (0xbca39ea8 to 0xbca3a000) [ 55.214805] 9ea0: bf6cbd80 80769a50 6b6b6b6b 80560448 bdeb0500 8056bfe8 [ 55.222991] 9ec0: 00000002 b76da000 00000000 bdeb0500 bdd92448 bca38000 bdeb0510 8056d69c [ 55.231177] 9ee0: bca38000 00000000 80c050fc 00000000 bca39f44 09d42015 00000000 00000001 [ 55.239363] 9f00: bdd92448 bdd92438 bdd92000 7f1158c4 bdd92448 bca2ee00 bf6cbd80 bf6cef00 [ 55.247549] 9f20: 00000000 00000000 00000000 801412d8 bf6cbd98 80c03d00 bca2ee00 bf6cbd80 [ 55.255735] 9f40: bca2ee14 bf6cbd98 80c03d00 00000008 bca38000 80141568 00000000 80c446ae [ 55.263921] 9f60: 00000000 bc9ed880 bc9f0700 bca38000 bc117eb4 80141524 bca2ee00 bc9ed8a4 [ 55.272107] 9f80: 00000000 80147cc8 00000000 bc9f0700 80147b84 00000000 00000000 00000000 [ 55.280292] 9fa0: 00000000 00000000 00000000 80100148 00000000 00000000 00000000 00000000 [ 55.288477] 9fc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 [ 55.296662] 9fe0: 00000000 00000000 00000000 00000000 00000013 00000000 00000000 00000000 [ 55.304860] [<8047c06c>] (kobject_get) from [<80560448>] (usb_get_dev+0x14/0x1c) [ 55.312271] [<80560448>] (usb_get_dev) from [<8056bfe8>] (usb_hcd_unlink_urb+0x50/0xd8) [ 55.320286] [<8056bfe8>] (usb_hcd_unlink_urb) from [<8056d69c>] (usb_kill_urb.part.0+0x44/0xd0) [ 55.329004] [<8056d69c>] (usb_kill_urb.part.0) from [<7f1158c4>] (acm_softint+0x4c/0x10c [cdc_acm]) [ 55.338082] [<7f1158c4>] (acm_softint [cdc_acm]) from [<801412d8>] (process_one_work+0x19c/0x3e8) [ 55.346969] [<801412d8>] (process_one_work) from [<80141568>] (worker_thread+0x44/0x4dc) [ 55.355072] [<80141568>] (worker_thread) from [<80147cc8>] (kthread+0x144/0x180) [ 55.362481] [<80147cc8>] (kthread) from [<80100148>] (ret_from_fork+0x14/0x2c) [ 55.369706] Exception stack(0xbca39fb0 to 0xbca39ff8) Tested-by: Bruno Thomsen Signed-off-by: Oliver Neukum Cc: stable Link: https://lore.kernel.org/r/20210311130126.15972-1-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 48 ++++++++++++++++++++++++------------- 1 file changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index b013671261a2..d684cf94b1c0 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -147,17 +147,29 @@ static inline int acm_set_control(struct acm *acm, int control) #define acm_send_break(acm, ms) \ acm_ctrl_msg(acm, USB_CDC_REQ_SEND_BREAK, ms, NULL, 0) -static void acm_kill_urbs(struct acm *acm) +static void acm_poison_urbs(struct acm *acm) { int i; - usb_kill_urb(acm->ctrlurb); + usb_poison_urb(acm->ctrlurb); for (i = 0; i < ACM_NW; i++) - usb_kill_urb(acm->wb[i].urb); + usb_poison_urb(acm->wb[i].urb); for (i = 0; i < acm->rx_buflimit; i++) - usb_kill_urb(acm->read_urbs[i]); + usb_poison_urb(acm->read_urbs[i]); } +static void acm_unpoison_urbs(struct acm *acm) +{ + int i; + + for (i = 0; i < acm->rx_buflimit; i++) + usb_unpoison_urb(acm->read_urbs[i]); + for (i = 0; i < ACM_NW; i++) + usb_unpoison_urb(acm->wb[i].urb); + usb_unpoison_urb(acm->ctrlurb); +} + + /* * Write buffer management. * All of these assume proper locks taken by the caller. @@ -226,9 +238,10 @@ static int acm_start_wb(struct acm *acm, struct acm_wb *wb) rc = usb_submit_urb(wb->urb, GFP_ATOMIC); if (rc < 0) { - dev_err(&acm->data->dev, - "%s - usb_submit_urb(write bulk) failed: %d\n", - __func__, rc); + if (rc != -EPERM) + dev_err(&acm->data->dev, + "%s - usb_submit_urb(write bulk) failed: %d\n", + __func__, rc); acm_write_done(acm, wb); } return rc; @@ -482,11 +495,6 @@ static void acm_read_bulk_callback(struct urb *urb) dev_vdbg(&acm->data->dev, "got urb %d, len %d, status %d\n", rb->index, urb->actual_length, status); - if (!acm->dev) { - dev_dbg(&acm->data->dev, "%s - disconnected\n", __func__); - return; - } - switch (status) { case 0: usb_mark_last_busy(acm->dev); @@ -733,6 +741,7 @@ static void acm_port_shutdown(struct tty_port *port) * Need to grab write_lock to prevent race with resume, but no need to * hold it due to the tty-port initialised flag. */ + acm_poison_urbs(acm); spin_lock_irq(&acm->write_lock); spin_unlock_irq(&acm->write_lock); @@ -749,7 +758,8 @@ static void acm_port_shutdown(struct tty_port *port) usb_autopm_put_interface_async(acm->control); } - acm_kill_urbs(acm); + acm_unpoison_urbs(acm); + } static void acm_tty_cleanup(struct tty_struct *tty) @@ -1542,8 +1552,14 @@ static void acm_disconnect(struct usb_interface *intf) if (!acm) return; - mutex_lock(&acm->mutex); acm->disconnected = true; + /* + * there is a circular dependency. acm_softint() can resubmit + * the URBs in error handling so we need to block any + * submission right away + */ + acm_poison_urbs(acm); + mutex_lock(&acm->mutex); if (acm->country_codes) { device_remove_file(&acm->control->dev, &dev_attr_wCountryCodes); @@ -1562,7 +1578,6 @@ static void acm_disconnect(struct usb_interface *intf) tty_kref_put(tty); } - acm_kill_urbs(acm); cancel_delayed_work_sync(&acm->dwork); tty_unregister_device(acm_tty_driver, acm->minor); @@ -1604,7 +1619,7 @@ static int acm_suspend(struct usb_interface *intf, pm_message_t message) if (cnt) return 0; - acm_kill_urbs(acm); + acm_poison_urbs(acm); cancel_delayed_work_sync(&acm->dwork); acm->urbs_in_error_delay = 0; @@ -1617,6 +1632,7 @@ static int acm_resume(struct usb_interface *intf) struct urb *urb; int rv = 0; + acm_unpoison_urbs(acm); spin_lock_irq(&acm->write_lock); if (--acm->susp_count) From e4c77070ad45fc940af1d7fb1e637c349e848951 Mon Sep 17 00:00:00 2001 From: Oliver Neukum Date: Thu, 11 Mar 2021 14:01:26 +0100 Subject: [PATCH 0340/1091] USB: cdc-acm: downgrade message to debug This failure is so common that logging an error here amounts to spamming log files. Reviewed-by: Bruno Thomsen Signed-off-by: Oliver Neukum Cc: stable Link: https://lore.kernel.org/r/20210311130126.15972-2-oneukum@suse.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d684cf94b1c0..fd2fce072985 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -659,7 +659,8 @@ static void acm_port_dtr_rts(struct tty_port *port, int raise) res = acm_set_control(acm, val); if (res && (acm->ctrl_caps & USB_CDC_CAP_LINE)) - dev_err(&acm->control->dev, "failed to set dtr/rts\n"); + /* This is broken in too many devices to spam the logs */ + dev_dbg(&acm->control->dev, "failed to set dtr/rts\n"); } static int acm_port_activate(struct tty_port *port, struct tty_struct *tty) From 7180495cb3d0e2a2860d282a468b4146c21da78f Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:11 +0100 Subject: [PATCH 0341/1091] USB: cdc-acm: fix double free on probe failure If tty-device registration fails the driver copy of any Country Selection functional descriptor would end up being freed twice; first explicitly in the error path and then again in the tty-port destructor. Drop the first erroneous free that was left when fixing a tty-port resource leak. Fixes: cae2bc768d17 ("usb: cdc-acm: Decrement tty port's refcount if probe() fail") Cc: stable@vger.kernel.org # 4.19 Cc: Jaejoong Kim Acked-by: Oliver Neukum Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-2-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index fd2fce072985..d5fbb943c4c1 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1521,7 +1521,6 @@ alloc_fail6: &dev_attr_wCountryCodes); device_remove_file(&acm->control->dev, &dev_attr_iCountryCodeRelDate); - kfree(acm->country_codes); } device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); alloc_fail5: From 4e49bf376c0451ad2eae2592e093659cde12be9a Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:12 +0100 Subject: [PATCH 0342/1091] USB: cdc-acm: fix use-after-free after probe failure If tty-device registration fails the driver would fail to release the data interface. When the device is later disconnected, the disconnect callback would still be called for the data interface and would go about releasing already freed resources. Fixes: c93d81955005 ("usb: cdc-acm: fix error handling in acm_probe()") Cc: stable@vger.kernel.org # 3.9 Cc: Alexey Khoroshilov Acked-by: Oliver Neukum Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-3-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d5fbb943c4c1..6decf8f2b9ae 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1516,6 +1516,11 @@ skip_countries: return 0; alloc_fail6: + if (!acm->combined_interfaces) { + /* Clear driver data so that disconnect() returns early. */ + usb_set_intfdata(data_interface, NULL); + usb_driver_release_interface(&acm_driver, data_interface); + } if (acm->country_codes) { device_remove_file(&acm->control->dev, &dev_attr_wCountryCodes); From 8111a8cbd5dde0b6ea8c388ff4840d4e465b5edd Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:13 +0100 Subject: [PATCH 0343/1091] USB: cdc-acm: drop redundant driver-data assignment The interface driver data has already been set by usb_driver_claim_interface() so drop the redundant subsequent assignment. Acked-by: Oliver Neukum Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-4-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 6decf8f2b9ae..d73570d31ed8 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1500,7 +1500,6 @@ skip_countries: acm_set_line(acm, &acm->line); usb_driver_claim_interface(&acm_driver, data_interface, acm); - usb_set_intfdata(data_interface, acm); tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, &control_interface->dev); From dda6faaa2bdadc56b9ad034602307a51d11e26a7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:14 +0100 Subject: [PATCH 0344/1091] USB: cdc-acm: drop redundant driver-data reset There's no need to clear the interface driver data on failed probe (and driver core will clear it anyway). Acked-by: Oliver Neukum Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-5-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index d73570d31ed8..104e10b4ebfa 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1528,7 +1528,6 @@ alloc_fail6: } device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); alloc_fail5: - usb_set_intfdata(intf, NULL); for (i = 0; i < ACM_NW; i++) usb_free_urb(acm->wb[i].urb); alloc_fail4: From 4cde059acd11e79b205525e5fd66175d8576ec88 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:15 +0100 Subject: [PATCH 0345/1091] USB: cdc-acm: clean up probe error labels Name the probe error labels after what they do rather than using sequence numbers which is harder to review and maintain (e.g. may require renaming unrelated labels when a label is added or removed). Acked-by: Oliver Neukum Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-6-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 104e10b4ebfa..4844f50e54de 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1337,7 +1337,7 @@ made_compressed_probe: acm = kzalloc(sizeof(struct acm), GFP_KERNEL); if (acm == NULL) - goto alloc_fail; + return -ENOMEM; tty_port_init(&acm->port); acm->port.ops = &acm_port_ops; @@ -1354,7 +1354,7 @@ made_compressed_probe: minor = acm_alloc_minor(acm); if (minor < 0) - goto alloc_fail1; + goto err_put_port; acm->minor = minor; acm->dev = usb_dev; @@ -1385,15 +1385,15 @@ made_compressed_probe: buf = usb_alloc_coherent(usb_dev, ctrlsize, GFP_KERNEL, &acm->ctrl_dma); if (!buf) - goto alloc_fail1; + goto err_put_port; acm->ctrl_buffer = buf; if (acm_write_buffers_alloc(acm) < 0) - goto alloc_fail2; + goto err_free_ctrl_buffer; acm->ctrlurb = usb_alloc_urb(0, GFP_KERNEL); if (!acm->ctrlurb) - goto alloc_fail3; + goto err_free_write_buffers; for (i = 0; i < num_rx_buf; i++) { struct acm_rb *rb = &(acm->read_buffers[i]); @@ -1402,13 +1402,13 @@ made_compressed_probe: rb->base = usb_alloc_coherent(acm->dev, readsize, GFP_KERNEL, &rb->dma); if (!rb->base) - goto alloc_fail4; + goto err_free_read_urbs; rb->index = i; rb->instance = acm; urb = usb_alloc_urb(0, GFP_KERNEL); if (!urb) - goto alloc_fail4; + goto err_free_read_urbs; urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP; urb->transfer_dma = rb->dma; @@ -1430,7 +1430,7 @@ made_compressed_probe: snd->urb = usb_alloc_urb(0, GFP_KERNEL); if (snd->urb == NULL) - goto alloc_fail5; + goto err_free_write_urbs; if (usb_endpoint_xfer_int(epwrite)) usb_fill_int_urb(snd->urb, usb_dev, acm->out, @@ -1448,7 +1448,7 @@ made_compressed_probe: i = device_create_file(&intf->dev, &dev_attr_bmCapabilities); if (i < 0) - goto alloc_fail5; + goto err_free_write_urbs; if (h.usb_cdc_country_functional_desc) { /* export the country data */ struct usb_cdc_country_functional_desc * cfd = @@ -1505,7 +1505,7 @@ skip_countries: &control_interface->dev); if (IS_ERR(tty_dev)) { rv = PTR_ERR(tty_dev); - goto alloc_fail6; + goto err_release_data_interface; } if (quirks & CLEAR_HALT_CONDITIONS) { @@ -1514,7 +1514,8 @@ skip_countries: } return 0; -alloc_fail6: + +err_release_data_interface: if (!acm->combined_interfaces) { /* Clear driver data so that disconnect() returns early. */ usb_set_intfdata(data_interface, NULL); @@ -1527,21 +1528,21 @@ alloc_fail6: &dev_attr_iCountryCodeRelDate); } device_remove_file(&acm->control->dev, &dev_attr_bmCapabilities); -alloc_fail5: +err_free_write_urbs: for (i = 0; i < ACM_NW; i++) usb_free_urb(acm->wb[i].urb); -alloc_fail4: +err_free_read_urbs: for (i = 0; i < num_rx_buf; i++) usb_free_urb(acm->read_urbs[i]); acm_read_buffers_free(acm); usb_free_urb(acm->ctrlurb); -alloc_fail3: +err_free_write_buffers: acm_write_buffers_free(acm); -alloc_fail2: +err_free_ctrl_buffer: usb_free_coherent(usb_dev, ctrlsize, acm->ctrl_buffer, acm->ctrl_dma); -alloc_fail1: +err_put_port: tty_port_put(&acm->port); -alloc_fail: + return rv; } From f8255ee192e92fdb885a9ff6bc90d74f5bfb7cd6 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:16 +0100 Subject: [PATCH 0346/1091] USB: cdc-acm: use negation for NULL checks Use negation consistently throughout the driver for NULL checks. Acked-by: Oliver Neukum Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-7-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 4844f50e54de..1f0fcabef5d2 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1336,7 +1336,7 @@ made_compressed_probe: dev_dbg(&intf->dev, "interfaces are valid\n"); acm = kzalloc(sizeof(struct acm), GFP_KERNEL); - if (acm == NULL) + if (!acm) return -ENOMEM; tty_port_init(&acm->port); @@ -1429,7 +1429,7 @@ made_compressed_probe: struct acm_wb *snd = &(acm->wb[i]); snd->urb = usb_alloc_urb(0, GFP_KERNEL); - if (snd->urb == NULL) + if (!snd->urb) goto err_free_write_urbs; if (usb_endpoint_xfer_int(epwrite)) From 0b2b23ca20ac9329d91bdba713028cf279423383 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:17 +0100 Subject: [PATCH 0347/1091] USB: cdc-acm: always claim data interface Make sure to always claim the data interface and bail out if binding fails. Note that the driver had a check to verify that the data interface was not already bound to a driver but would not detect other failures (e.g. if the interface was not authorised). Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-8-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 1f0fcabef5d2..5ce525d22425 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1309,13 +1309,6 @@ skip_normal_probe: if (!combined_interfaces && intf != control_interface) return -ENODEV; - if (!combined_interfaces && usb_interface_claimed(data_interface)) { - /* valid in this context */ - dev_dbg(&intf->dev, "The data interface isn't available\n"); - return -EBUSY; - } - - if (data_interface->cur_altsetting->desc.bNumEndpoints < 2 || control_interface->cur_altsetting->desc.bNumEndpoints == 0) return -EINVAL; @@ -1499,7 +1492,11 @@ skip_countries: acm->line.bDataBits = 8; acm_set_line(acm, &acm->line); - usb_driver_claim_interface(&acm_driver, data_interface, acm); + if (!acm->combined_interfaces) { + rv = usb_driver_claim_interface(&acm_driver, data_interface, acm); + if (rv) + goto err_remove_files; + } tty_dev = tty_port_register_device(&acm->port, acm_tty_driver, minor, &control_interface->dev); @@ -1521,6 +1518,7 @@ err_release_data_interface: usb_set_intfdata(data_interface, NULL); usb_driver_release_interface(&acm_driver, data_interface); } +err_remove_files: if (acm->country_codes) { device_remove_file(&acm->control->dev, &dev_attr_wCountryCodes); From 79579411826647fd573dbe301c4d933bc90e4be7 Mon Sep 17 00:00:00 2001 From: Johan Hovold Date: Mon, 22 Mar 2021 16:53:18 +0100 Subject: [PATCH 0348/1091] USB: cdc-acm: do not log successful probe on later errors Do not log the successful-probe message until the tty device has been registered. Signed-off-by: Johan Hovold Link: https://lore.kernel.org/r/20210322155318.9837-9-johan@kernel.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/class/cdc-acm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/usb/class/cdc-acm.c b/drivers/usb/class/cdc-acm.c index 5ce525d22425..3fda1ec961d7 100644 --- a/drivers/usb/class/cdc-acm.c +++ b/drivers/usb/class/cdc-acm.c @@ -1486,8 +1486,6 @@ skip_countries: acm->nb_index = 0; acm->nb_size = 0; - dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); - acm->line.dwDTERate = cpu_to_le32(9600); acm->line.bDataBits = 8; acm_set_line(acm, &acm->line); @@ -1510,6 +1508,8 @@ skip_countries: usb_clear_halt(usb_dev, acm->out); } + dev_info(&intf->dev, "ttyACM%d: USB ACM device\n", minor); + return 0; err_release_data_interface: From 0bd860493f81eb2a46173f6f5e44cc38331c8dbd Mon Sep 17 00:00:00 2001 From: Vincent Palatin Date: Fri, 19 Mar 2021 13:48:02 +0100 Subject: [PATCH 0349/1091] USB: quirks: ignore remote wake-up on Fibocom L850-GL LTE modem This LTE modem (M.2 card) has a bug in its power management: there is some kind of race condition for U3 wake-up between the host and the device. The modem firmware sometimes crashes/locks when both events happen at the same time and the modem fully drops off the USB bus (and sometimes re-enumerates, sometimes just gets stuck until the next reboot). Tested with the modem wired to the XHCI controller on an AMD 3015Ce platform. Without the patch, the modem dropped of the USB bus 5 times in 3 days. With the quirk, it stayed connected for a week while the 'runtime_suspended_time' counter incremented as excepted. Signed-off-by: Vincent Palatin Link: https://lore.kernel.org/r/20210319124802.2315195-1-vpalatin@chromium.org Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/core/quirks.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/core/quirks.c b/drivers/usb/core/quirks.c index 6ade3daf7858..76ac5d6555ae 100644 --- a/drivers/usb/core/quirks.c +++ b/drivers/usb/core/quirks.c @@ -498,6 +498,10 @@ static const struct usb_device_id usb_quirk_list[] = { /* DJI CineSSD */ { USB_DEVICE(0x2ca3, 0x0031), .driver_info = USB_QUIRK_NO_LPM }, + /* Fibocom L850-GL LTE Modem */ + { USB_DEVICE(0x2cb7, 0x0007), .driver_info = + USB_QUIRK_IGNORE_REMOTE_WAKEUP }, + /* INTEL VALUE SSD */ { USB_DEVICE(0x8086, 0xf1a5), .driver_info = USB_QUIRK_RESET_RESUME }, From 72ad25fbbb78930f892b191637359ab5b94b3190 Mon Sep 17 00:00:00 2001 From: Atul Gopinathan Date: Tue, 23 Mar 2021 17:04:12 +0530 Subject: [PATCH 0350/1091] staging: rtl8192e: Fix incorrect source in memcpy() The variable "info_element" is of the following type: struct rtllib_info_element *info_element defined in drivers/staging/rtl8192e/rtllib.h: struct rtllib_info_element { u8 id; u8 len; u8 data[]; } __packed; The "len" field defines the size of the "data[]" array. The code is supposed to check if "info_element->len" is greater than 4 and later equal to 6. If this is satisfied then, the last two bytes (the 4th and 5th element of u8 "data[]" array) are copied into "network->CcxRmState". Right now the code uses "memcpy()" with the source as "&info_element[4]" which would copy in wrong and unintended information. The struct "rtllib_info_element" has a size of 2 bytes for "id" and "len", therefore indexing will be done in interval of 2 bytes. So, "info_element[4]" would point to data which is beyond the memory allocated for this pointer (that is, at x+8, while "info_element" has been allocated only from x to x+7 (2 + 6 => 8 bytes)). This patch rectifies this error by using "&info_element->data[4]" which correctly copies the last two bytes of "data[]". NOTE: The faulty line of code came from the following commit: commit ecdfa44610fa ("Staging: add Realtek 8192 PCI wireless driver") The above commit created the file `rtl8192e/ieee80211/ieee80211_rx.c` which had the faulty line of code. This file has been deleted (or possibly renamed) with the contents copied in to a new file `rtl8192e/rtllib_rx.c` along with additional code in the commit 94a799425eee (tagged in Fixes). Fixes: 94a799425eee ("From: wlanfae [PATCH 1/8] rtl8192e: Import new version of driver from realtek") Cc: stable@vger.kernel.org Signed-off-by: Atul Gopinathan Link: https://lore.kernel.org/r/20210323113413.29179-1-atulgopinathan@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib_rx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192e/rtllib_rx.c b/drivers/staging/rtl8192e/rtllib_rx.c index 66c135321da4..15bbb63ca130 100644 --- a/drivers/staging/rtl8192e/rtllib_rx.c +++ b/drivers/staging/rtl8192e/rtllib_rx.c @@ -1967,7 +1967,7 @@ static void rtllib_parse_mife_generic(struct rtllib_device *ieee, info_element->data[2] == 0x96 && info_element->data[3] == 0x01) { if (info_element->len == 6) { - memcpy(network->CcxRmState, &info_element[4], 2); + memcpy(network->CcxRmState, &info_element->data[4], 2); if (network->CcxRmState[0] != 0) network->bCcxRmEnable = true; else From e78836ae76d20f38eed8c8c67f21db97529949da Mon Sep 17 00:00:00 2001 From: Atul Gopinathan Date: Tue, 23 Mar 2021 17:04:14 +0530 Subject: [PATCH 0351/1091] staging: rtl8192e: Change state information from u16 to u8 The "u16 CcxRmState[2];" array field in struct "rtllib_network" has 4 bytes in total while the operations performed on this array through-out the code base are only 2 bytes. The "CcxRmState" field is fed only 2 bytes of data using memcpy(): (In rtllib_rx.c:1972) memcpy(network->CcxRmState, &info_element->data[4], 2) With "info_element->data[]" being a u8 array, if 2 bytes are written into "CcxRmState" (whose one element is u16 size), then the 2 u8 elements from "data[]" gets squashed and written into the first element ("CcxRmState[0]") while the second element ("CcxRmState[1]") is never fed with any data. Same in file rtllib_rx.c:2522: memcpy(dst->CcxRmState, src->CcxRmState, 2); The above line duplicates "src" data to "dst" but only writes 2 bytes (and not 4, which is the actual size). Again, only 1st element gets the value while the 2nd element remains uninitialized. This later makes operations done with CcxRmState unpredictable in the following lines as the 1st element is having a squashed number while the 2nd element is having an uninitialized random number. rtllib_rx.c:1973: if (network->CcxRmState[0] != 0) rtllib_rx.c:1977: network->MBssidMask = network->CcxRmState[1] & 0x07; network->MBssidMask is also of type u8 and not u16. Fix this by changing the type of "CcxRmState" from u16 to u8 so that the data written into this array and read from it make sense and are not random values. NOTE: The wrong initialization of "CcxRmState" can be seen in the following commit: commit ecdfa44610fa ("Staging: add Realtek 8192 PCI wireless driver") The above commit created a file `rtl8192e/ieee80211.h` which used to have the faulty line. The file has been deleted (or possibly renamed) with the contents copied in to a new file `rtl8192e/rtllib.h` along with additional code in the commit 94a799425eee (tagged in Fixes). Fixes: 94a799425eee ("From: wlanfae [PATCH 1/8] rtl8192e: Import new version of driver from realtek") Cc: stable@vger.kernel.org Signed-off-by: Atul Gopinathan Link: https://lore.kernel.org/r/20210323113413.29179-2-atulgopinathan@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/staging/rtl8192e/rtllib.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/staging/rtl8192e/rtllib.h b/drivers/staging/rtl8192e/rtllib.h index b84f00b8d18b..4cabaf21c1ca 100644 --- a/drivers/staging/rtl8192e/rtllib.h +++ b/drivers/staging/rtl8192e/rtllib.h @@ -1105,7 +1105,7 @@ struct rtllib_network { bool bWithAironetIE; bool bCkipSupported; bool bCcxRmEnable; - u16 CcxRmState[2]; + u8 CcxRmState[2]; bool bMBssidValid; u8 MBssidMask; u8 MBssid[ETH_ALEN]; From f0acf637d60ffcef3ccb6e279f743e587b3c7359 Mon Sep 17 00:00:00 2001 From: Ahmad Fatoum Date: Fri, 19 Mar 2021 12:04:57 +0100 Subject: [PATCH 0352/1091] driver core: clear deferred probe reason on probe retry When retrying a deferred probe, any old defer reason string should be discarded. Otherwise, if the probe is deferred again at a different spot, but without setting a message, the now incorrect probe reason will remain. This was observed with the i.MX I2C driver, which ultimately failed to probe due to lack of the GPIO driver. The probe defer for GPIO doesn't record a message, but a previous probe defer to clock_get did. This had the effect that /sys/kernel/debug/devices_deferred listed a misleading probe deferral reason. Cc: stable Fixes: d090b70ede02 ("driver core: add deferring probe reason to devices_deferred property") Reviewed-by: Andy Shevchenko Reviewed-by: Andrzej Hajda Signed-off-by: Ahmad Fatoum Link: https://lore.kernel.org/r/20210319110459.19966-1-a.fatoum@pengutronix.de Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index 9179825ff646..e2cf3b29123e 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -97,6 +97,9 @@ static void deferred_probe_work_func(struct work_struct *work) get_device(dev); + kfree(dev->p->deferred_probe_reason); + dev->p->deferred_probe_reason = NULL; + /* * Drop the mutex while probing each device; the probe path may * manipulate the deferred list From 903079a54cac47ab115fa5abbde6860cf94e258f Mon Sep 17 00:00:00 2001 From: Vinod Koul Date: Fri, 26 Feb 2021 16:42:33 +0530 Subject: [PATCH 0353/1091] MAINTAINERS: Add linux-phy list and patchwork Linux-phy subsystem gained mailing list and a patchwork instance. Add the details to MAINTAINERS file Signed-off-by: Vinod Koul Link: https://lore.kernel.org/r/20210226111233.2601369-1-vkoul@kernel.org Signed-off-by: Greg Kroah-Hartman --- MAINTAINERS | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index aa84121c5611..cc47802933f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7476,8 +7476,9 @@ F: include/uapi/asm-generic/ GENERIC PHY FRAMEWORK M: Kishon Vijay Abraham I M: Vinod Koul -L: linux-kernel@vger.kernel.org +L: linux-phy@lists.infradead.org S: Supported +Q: https://patchwork.kernel.org/project/linux-phy/list/ T: git git://git.kernel.org/pub/scm/linux/kernel/git/phy/linux-phy.git F: Documentation/devicetree/bindings/phy/ F: drivers/phy/ From ce068bc7da473e39b64d130101e178406023df0c Mon Sep 17 00:00:00 2001 From: Tomas Winkler Date: Thu, 18 Mar 2021 07:59:59 +0200 Subject: [PATCH 0354/1091] mei: allow map and unmap of client dma buffer only for disconnected client Allow map and unmap of the client dma buffer only when the client is not connected. The functions return -EPROTO if the client is already connected. This is to fix the race when traffic may start or stop when buffer is not available. Cc: #v5.11+ Signed-off-by: Tomas Winkler Link: https://lore.kernel.org/r/20210318055959.305627-1-tomas.winkler@intel.com Signed-off-by: Greg Kroah-Hartman --- drivers/misc/mei/client.c | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/drivers/misc/mei/client.c b/drivers/misc/mei/client.c index 4378a9b25848..2cc370adb238 100644 --- a/drivers/misc/mei/client.c +++ b/drivers/misc/mei/client.c @@ -2286,8 +2286,8 @@ int mei_cl_dma_alloc_and_map(struct mei_cl *cl, const struct file *fp, if (buffer_id == 0) return -EINVAL; - if (!mei_cl_is_connected(cl)) - return -ENODEV; + if (mei_cl_is_connected(cl)) + return -EPROTO; if (cl->dma_mapped) return -EPROTO; @@ -2327,9 +2327,7 @@ int mei_cl_dma_alloc_and_map(struct mei_cl *cl, const struct file *fp, mutex_unlock(&dev->device_lock); wait_event_timeout(cl->wait, - cl->dma_mapped || - cl->status || - !mei_cl_is_connected(cl), + cl->dma_mapped || cl->status, mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); mutex_lock(&dev->device_lock); @@ -2376,8 +2374,9 @@ int mei_cl_dma_unmap(struct mei_cl *cl, const struct file *fp) return -EOPNOTSUPP; } - if (!mei_cl_is_connected(cl)) - return -ENODEV; + /* do not allow unmap for connected client */ + if (mei_cl_is_connected(cl)) + return -EPROTO; if (!cl->dma_mapped) return -EPROTO; @@ -2405,9 +2404,7 @@ int mei_cl_dma_unmap(struct mei_cl *cl, const struct file *fp) mutex_unlock(&dev->device_lock); wait_event_timeout(cl->wait, - !cl->dma_mapped || - cl->status || - !mei_cl_is_connected(cl), + !cl->dma_mapped || cl->status, mei_secs_to_jiffies(MEI_CL_CONNECT_TIMEOUT)); mutex_lock(&dev->device_lock); From 01faae5193d6190b7b3aa93dae43f514e866d652 Mon Sep 17 00:00:00 2001 From: Du Cheng Date: Fri, 12 Mar 2021 16:14:21 +0800 Subject: [PATCH 0355/1091] drivers: video: fbcon: fix NULL dereference in fbcon_cursor() add null-check on function pointer before dereference on ops->cursor Reported-by: syzbot+b67aaae8d3a927f68d20@syzkaller.appspotmail.com Cc: stable Signed-off-by: Du Cheng Link: https://lore.kernel.org/r/20210312081421.452405-1-ducheng2@gmail.com Signed-off-by: Greg Kroah-Hartman --- drivers/video/fbdev/core/fbcon.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/video/fbdev/core/fbcon.c b/drivers/video/fbdev/core/fbcon.c index 44a5cd2f54cc..3406067985b1 100644 --- a/drivers/video/fbdev/core/fbcon.c +++ b/drivers/video/fbdev/core/fbcon.c @@ -1333,6 +1333,9 @@ static void fbcon_cursor(struct vc_data *vc, int mode) ops->cursor_flash = (mode == CM_ERASE) ? 0 : 1; + if (!ops->cursor) + return; + ops->cursor(vc, info, mode, get_color(vc, info, c, 1), get_color(vc, info, c, 0)); } From dfb81e3b5f47aa0ea5e4832eeb720bc22f07d0c1 Mon Sep 17 00:00:00 2001 From: Kai Vehmanen Date: Mon, 22 Mar 2021 16:38:30 +0200 Subject: [PATCH 0356/1091] ASoC: SOF: Intel: hda: drop display power on/off in D0i3 flows Controller needs to ensure display power is enabled only for HDA controller reset. Drop the display power-up/down calls from D0i3 entry/exit paths. This was previously not possible as codec drivers could not resume the links, and instead controller kept the reference to display power. The state of display power had be maintained in the D0i3 entry/exit code. With commit 87fc20e4a0cb ("ASoC: SOF: Intel: hda: use hdac_ext fine-grained link management"), this is no longer needed and the code can be cleaned up. Signed-off-by: Kai Vehmanen Reviewed-by: Ranjani Sridharan Reviewed-by: Keyon Jie Link: https://lore.kernel.org/r/20210322143830.3880293-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dsp.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/sof/intel/hda-dsp.c b/sound/soc/sof/intel/hda-dsp.c index 6e24e1cb13f9..df4cb29b9a1b 100644 --- a/sound/soc/sof/intel/hda-dsp.c +++ b/sound/soc/sof/intel/hda-dsp.c @@ -727,8 +727,6 @@ int hda_dsp_resume(struct snd_sof_dev *sdev) /* resume from D0I3 */ if (sdev->dsp_power_state.state == SOF_DSP_PM_D0) { - hda_codec_i915_display_power(sdev, true); - #if IS_ENABLED(CONFIG_SND_SOC_SOF_HDA) /* power up links that were active before suspend */ list_for_each_entry(hlink, &bus->hlink_list, list) { @@ -839,9 +837,6 @@ int hda_dsp_suspend(struct snd_sof_dev *sdev, u32 target_state) cancel_delayed_work_sync(&hda->d0i3_work); if (target_state == SOF_DSP_PM_D0) { - /* we can't keep a wakeref to display driver at suspend */ - hda_codec_i915_display_power(sdev, false); - /* Set DSP power state */ ret = snd_sof_dsp_set_power_state(sdev, &target_dsp_state); if (ret < 0) { From daa58c8eec0a65ac8e2e77ff3ea8a233d8eec954 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 09:56:34 -0700 Subject: [PATCH 0357/1091] Input: i8042 - fix Pegatron C15B ID entry The Zenbook Flip entry that was added overwrites a previous one because of a typo: In file included from drivers/input/serio/i8042.h:23, from drivers/input/serio/i8042.c:131: drivers/input/serio/i8042-x86ia64io.h:591:28: error: initialized field overwritten [-Werror=override-init] 591 | .matches = { | ^ drivers/input/serio/i8042-x86ia64io.h:591:28: note: (near initialization for 'i8042_dmi_noselftest_table[0].matches') Add the missing separator between the two. Fixes: b5d6e7ab7fe7 ("Input: i8042 - add ASUS Zenbook Flip to noselftest list") Signed-off-by: Arnd Bergmann Reviewed-by: Hans de Goede Reviewed-by: Marcos Paulo de Souza Link: https://lore.kernel.org/r/20210323130623.2302402-1-arnd@kernel.org Cc: stable@vger.kernel.org Signed-off-by: Dmitry Torokhov --- drivers/input/serio/i8042-x86ia64io.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/input/serio/i8042-x86ia64io.h b/drivers/input/serio/i8042-x86ia64io.h index 9119e12a5778..a5a003553646 100644 --- a/drivers/input/serio/i8042-x86ia64io.h +++ b/drivers/input/serio/i8042-x86ia64io.h @@ -588,6 +588,7 @@ static const struct dmi_system_id i8042_dmi_noselftest_table[] = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_CHASSIS_TYPE, "10"), /* Notebook */ }, + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "ASUSTeK COMPUTER INC."), DMI_MATCH(DMI_CHASSIS_TYPE, "31"), /* Convertible Notebook */ From 69d5ff3e9e51e23d5d81bf48480aa5671be67a71 Mon Sep 17 00:00:00 2001 From: Fabian Vogt Date: Tue, 23 Mar 2021 10:45:55 -0700 Subject: [PATCH 0358/1091] Input: nspire-keypad - enable interrupts only when opened The driver registers an interrupt handler in _probe, but didn't configure them until later when the _open function is called. In between, the keypad can fire an IRQ due to touchpad activity, which the handler ignores. This causes the kernel to disable the interrupt, blocking the keypad from working. Fix this by disabling interrupts before registering the handler. Additionally, disable them in _close, so that they're only enabled while open. Fixes: fc4f31461892 ("Input: add TI-Nspire keypad support") Signed-off-by: Fabian Vogt Link: https://lore.kernel.org/r/3383725.iizBOSrK1V@linux-e202.suse.de Signed-off-by: Dmitry Torokhov --- drivers/input/keyboard/nspire-keypad.c | 56 ++++++++++++++------------ 1 file changed, 31 insertions(+), 25 deletions(-) diff --git a/drivers/input/keyboard/nspire-keypad.c b/drivers/input/keyboard/nspire-keypad.c index 63d5e488137d..e9fa1423f136 100644 --- a/drivers/input/keyboard/nspire-keypad.c +++ b/drivers/input/keyboard/nspire-keypad.c @@ -93,9 +93,15 @@ static irqreturn_t nspire_keypad_irq(int irq, void *dev_id) return IRQ_HANDLED; } -static int nspire_keypad_chip_init(struct nspire_keypad *keypad) +static int nspire_keypad_open(struct input_dev *input) { + struct nspire_keypad *keypad = input_get_drvdata(input); unsigned long val = 0, cycles_per_us, delay_cycles, row_delay_cycles; + int error; + + error = clk_prepare_enable(keypad->clk); + if (error) + return error; cycles_per_us = (clk_get_rate(keypad->clk) / 1000000); if (cycles_per_us == 0) @@ -121,30 +127,6 @@ static int nspire_keypad_chip_init(struct nspire_keypad *keypad) keypad->int_mask = 1 << 1; writel(keypad->int_mask, keypad->reg_base + KEYPAD_INTMSK); - /* Disable GPIO interrupts to prevent hanging on touchpad */ - /* Possibly used to detect touchpad events */ - writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT); - /* Acknowledge existing interrupts */ - writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS); - - return 0; -} - -static int nspire_keypad_open(struct input_dev *input) -{ - struct nspire_keypad *keypad = input_get_drvdata(input); - int error; - - error = clk_prepare_enable(keypad->clk); - if (error) - return error; - - error = nspire_keypad_chip_init(keypad); - if (error) { - clk_disable_unprepare(keypad->clk); - return error; - } - return 0; } @@ -152,6 +134,11 @@ static void nspire_keypad_close(struct input_dev *input) { struct nspire_keypad *keypad = input_get_drvdata(input); + /* Disable interrupts */ + writel(0, keypad->reg_base + KEYPAD_INTMSK); + /* Acknowledge existing interrupts */ + writel(~0, keypad->reg_base + KEYPAD_INT); + clk_disable_unprepare(keypad->clk); } @@ -210,6 +197,25 @@ static int nspire_keypad_probe(struct platform_device *pdev) return -ENOMEM; } + error = clk_prepare_enable(keypad->clk); + if (error) { + dev_err(&pdev->dev, "failed to enable clock\n"); + return error; + } + + /* Disable interrupts */ + writel(0, keypad->reg_base + KEYPAD_INTMSK); + /* Acknowledge existing interrupts */ + writel(~0, keypad->reg_base + KEYPAD_INT); + + /* Disable GPIO interrupts to prevent hanging on touchpad */ + /* Possibly used to detect touchpad events */ + writel(0, keypad->reg_base + KEYPAD_UNKNOWN_INT); + /* Acknowledge existing GPIO interrupts */ + writel(~0, keypad->reg_base + KEYPAD_UNKNOWN_INT_STS); + + clk_disable_unprepare(keypad->clk); + input_set_drvdata(input, keypad); input->id.bustype = BUS_HOST; From 68dc022d04eb0fd60a540e242dcb11ec1bee07e2 Mon Sep 17 00:00:00 2001 From: Xin Long Date: Fri, 19 Mar 2021 18:27:58 +0800 Subject: [PATCH 0359/1091] xfrm: BEET mode doesn't support fragments for inner packets BEET mode replaces the IP(6) Headers with new IP(6) Headers when sending packets. However, when it's a fragment before the replacement, currently kernel keeps the fragment flag and replace the address field then encaps it with ESP. It would cause in RX side the fragments to get reassembled before decapping with ESP, which is incorrect. In Xiumei's testing, these fragments went over an xfrm interface and got encapped with ESP in the device driver, and the traffic was broken. I don't have a good way to fix it, but only to warn this out in dmesg. Reported-by: Xiumei Mu Signed-off-by: Xin Long Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_output.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c index b81ca117dac7..e4cb0ff4dcf4 100644 --- a/net/xfrm/xfrm_output.c +++ b/net/xfrm/xfrm_output.c @@ -660,6 +660,12 @@ static int xfrm4_extract_output(struct xfrm_state *x, struct sk_buff *skb) { int err; + if (x->outer_mode.encap == XFRM_MODE_BEET && + ip_is_fragment(ip_hdr(skb))) { + net_warn_ratelimited("BEET mode doesn't support inner IPv4 fragments\n"); + return -EAFNOSUPPORT; + } + err = xfrm4_tunnel_check_size(skb); if (err) return err; @@ -705,8 +711,15 @@ out: static int xfrm6_extract_output(struct xfrm_state *x, struct sk_buff *skb) { #if IS_ENABLED(CONFIG_IPV6) + unsigned int ptr = 0; int err; + if (x->outer_mode.encap == XFRM_MODE_BEET && + ipv6_find_hdr(skb, &ptr, NEXTHDR_FRAGMENT, NULL, NULL) >= 0) { + net_warn_ratelimited("BEET mode doesn't support inner IPv6 fragments\n"); + return -EAFNOSUPPORT; + } + err = xfrm6_tunnel_check_size(skb); if (err) return err; From b1e3a5607034aa0a481c6f69a6893049406665fb Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Tue, 23 Mar 2021 09:26:44 +0100 Subject: [PATCH 0360/1091] xfrm: Fix NULL pointer dereference on policy lookup When xfrm interfaces are used in combination with namespaces and ESP offload, we get a dst_entry NULL pointer dereference. This is because we don't have a dst_entry attached in the ESP offloading case and we need to do a policy lookup before the namespace transition. Fix this by expicit checking of skb_dst(skb) before accessing it. Fixes: f203b76d78092 ("xfrm: Add virtual xfrm interfaces") Signed-off-by: Steffen Klassert --- include/net/xfrm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/net/xfrm.h b/include/net/xfrm.h index bfbc7810df94..c58a6d4eb610 100644 --- a/include/net/xfrm.h +++ b/include/net/xfrm.h @@ -1097,7 +1097,7 @@ static inline int __xfrm_policy_check2(struct sock *sk, int dir, return __xfrm_policy_check(sk, ndir, skb, family); return (!net->xfrm.policy_count[dir] && !secpath_exists(skb)) || - (skb_dst(skb)->flags & DST_NOPOLICY) || + (skb_dst(skb) && (skb_dst(skb)->flags & DST_NOPOLICY)) || __xfrm_policy_check(sk, ndir, skb, family); } From a3efe3f6d0eb64363f74af4b0e8ba6d19415cef2 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 24 Mar 2021 12:23:58 +0200 Subject: [PATCH 0361/1091] ARM: OMAP2+: Fix warning for omap_init_time_of() Fix warning: no previous prototype for 'omap_init_time_of'. Fixes: e69b4e1a7577 ("ARM: OMAP2+: Add omap_init_time_of()") Reported-by: kernel test robot Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/board-generic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/board-generic.c b/arch/arm/mach-omap2/board-generic.c index 7290f033fd2d..1610c567a6a3 100644 --- a/arch/arm/mach-omap2/board-generic.c +++ b/arch/arm/mach-omap2/board-generic.c @@ -33,7 +33,7 @@ static void __init __maybe_unused omap_generic_init(void) } /* Clocks are needed early, see drivers/clocksource for the rest */ -void __init __maybe_unused omap_init_time_of(void) +static void __init __maybe_unused omap_init_time_of(void) { omap_clk_init(); timer_probe(); From a1ebdb3741993f853865d1bd8f77881916ad53a7 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 24 Mar 2021 15:10:32 +0200 Subject: [PATCH 0362/1091] ARM: dts: Fix swapped mmc order for omap3 Also some omap3 devices like n900 seem to have eMMC and micro-sd swapped around with commit 21b2cec61c04 ("mmc: Set PROBE_PREFER_ASYNCHRONOUS for drivers that existed in v4.4"). Let's fix the issue with aliases as discussed on the mailing lists. While the mmc aliases should be board specific, let's first fix the issue with minimal changes. Cc: Aaro Koskinen Cc: Peter Ujfalusi Signed-off-by: Tony Lindgren --- arch/arm/boot/dts/omap3.dtsi | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/arm/boot/dts/omap3.dtsi b/arch/arm/boot/dts/omap3.dtsi index 9dcae1f2bc99..c5b9da0d7e6c 100644 --- a/arch/arm/boot/dts/omap3.dtsi +++ b/arch/arm/boot/dts/omap3.dtsi @@ -24,6 +24,9 @@ i2c0 = &i2c1; i2c1 = &i2c2; i2c2 = &i2c3; + mmc0 = &mmc1; + mmc1 = &mmc2; + mmc2 = &mmc3; serial0 = &uart1; serial1 = &uart2; serial2 = &uart3; From 1d676673d665fd2162e7e466dcfbe5373bfdb73e Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Mar 2021 12:06:29 +0000 Subject: [PATCH 0363/1091] KVM: arm64: Hide system instruction access to Trace registers Currently we advertise the ID_AA6DFR0_EL1.TRACEVER for the guest, when the trace register accesses are trapped (CPTR_EL2.TTA == 1). So, the guest will get an undefined instruction, if trusts the ID registers and access one of the trace registers. Lets be nice to the guest and hide the feature to avoid unexpected behavior. Even though this can be done at KVM sysreg emulation layer, we do this by removing the TRACEVER from the sanitised feature register field. This is fine as long as the ETM drivers can handle the individual trace units separately, even when there are differences among the CPUs. Cc: Will Deacon Cc: Catalin Marinas Cc: Mark Rutland Signed-off-by: Suzuki K Poulose Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20210323120647.454211-2-suzuki.poulose@arm.com --- arch/arm64/kernel/cpufeature.c | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c index 066030717a4c..a4698f09bf32 100644 --- a/arch/arm64/kernel/cpufeature.c +++ b/arch/arm64/kernel/cpufeature.c @@ -383,7 +383,6 @@ static const struct arm64_ftr_bits ftr_id_aa64dfr0[] = { * of support. */ S_ARM64_FTR_BITS(FTR_HIDDEN, FTR_NONSTRICT, FTR_EXACT, ID_AA64DFR0_PMUVER_SHIFT, 4, 0), - ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_TRACEVER_SHIFT, 4, 0), ARM64_FTR_BITS(FTR_HIDDEN, FTR_STRICT, FTR_EXACT, ID_AA64DFR0_DEBUGVER_SHIFT, 4, 0x6), ARM64_FTR_END, }; From a354a64d91eec3e0f8ef0eed575b480fd75b999c Mon Sep 17 00:00:00 2001 From: Suzuki K Poulose Date: Tue, 23 Mar 2021 12:06:30 +0000 Subject: [PATCH 0364/1091] KVM: arm64: Disable guest access to trace filter controls Disable guest access to the Trace Filter control registers. We do not advertise the Trace filter feature to the guest (ID_AA64DFR0_EL1: TRACE_FILT is cleared) already, but the guest can still access the TRFCR_EL1 unless we trap it. This will also make sure that the guest cannot fiddle with the filtering controls set by a nvhe host. Cc: Marc Zyngier Cc: Will Deacon Cc: Mark Rutland Cc: Catalin Marinas Signed-off-by: Suzuki K Poulose Signed-off-by: Marc Zyngier Link: https://lore.kernel.org/r/20210323120647.454211-3-suzuki.poulose@arm.com --- arch/arm64/include/asm/kvm_arm.h | 1 + arch/arm64/kvm/debug.c | 2 ++ 2 files changed, 3 insertions(+) diff --git a/arch/arm64/include/asm/kvm_arm.h b/arch/arm64/include/asm/kvm_arm.h index 4e90c2debf70..94d4025acc0b 100644 --- a/arch/arm64/include/asm/kvm_arm.h +++ b/arch/arm64/include/asm/kvm_arm.h @@ -278,6 +278,7 @@ #define CPTR_EL2_DEFAULT CPTR_EL2_RES1 /* Hyp Debug Configuration Register bits */ +#define MDCR_EL2_TTRF (1 << 19) #define MDCR_EL2_TPMS (1 << 14) #define MDCR_EL2_E2PB_MASK (UL(0x3)) #define MDCR_EL2_E2PB_SHIFT (UL(12)) diff --git a/arch/arm64/kvm/debug.c b/arch/arm64/kvm/debug.c index 7a7e425616b5..dbc890511631 100644 --- a/arch/arm64/kvm/debug.c +++ b/arch/arm64/kvm/debug.c @@ -89,6 +89,7 @@ void kvm_arm_reset_debug_ptr(struct kvm_vcpu *vcpu) * - Debug ROM Address (MDCR_EL2_TDRA) * - OS related registers (MDCR_EL2_TDOSA) * - Statistical profiler (MDCR_EL2_TPMS/MDCR_EL2_E2PB) + * - Self-hosted Trace Filter controls (MDCR_EL2_TTRF) * * Additionally, KVM only traps guest accesses to the debug registers if * the guest is not actively using them (see the KVM_ARM64_DEBUG_DIRTY @@ -112,6 +113,7 @@ void kvm_arm_setup_debug(struct kvm_vcpu *vcpu) vcpu->arch.mdcr_el2 = __this_cpu_read(mdcr_el2) & MDCR_EL2_HPMN_MASK; vcpu->arch.mdcr_el2 |= (MDCR_EL2_TPM | MDCR_EL2_TPMS | + MDCR_EL2_TTRF | MDCR_EL2_TPMCR | MDCR_EL2_TDRA | MDCR_EL2_TDOSA); From af22df997d71c32304d6835a8b690281063b8010 Mon Sep 17 00:00:00 2001 From: Marc Zyngier Date: Tue, 23 Mar 2021 16:08:18 +0000 Subject: [PATCH 0365/1091] KVM: arm64: Fix CPU interface MMIO compatibility detection In order to detect whether a GICv3 CPU interface is MMIO capable, we switch ICC_SRE_EL1.SRE to 0 and check whether it sticks. However, this is only possible if *ALL* of the HCR_EL2 interrupt overrides are set, and the CPU is perfectly allowed to ignore the write to ICC_SRE_EL1 otherwise. This leads KVM to pretend that a whole bunch of ARMv8.0 CPUs aren't MMIO-capable, and breaks VMs that should work correctly otherwise. Fix this by setting IMO/FMO/IMO before touching ICC_SRE_EL1, and clear them afterwards. This allows us to reliably detect the CPU interface capabilities. Tested-by: Shameerali Kolothum Thodi Fixes: 9739f6ef053f ("KVM: arm64: Workaround firmware wrongly advertising GICv2-on-v3 compatibility") Signed-off-by: Marc Zyngier --- arch/arm64/kvm/hyp/vgic-v3-sr.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/arch/arm64/kvm/hyp/vgic-v3-sr.c b/arch/arm64/kvm/hyp/vgic-v3-sr.c index ee3682b9873c..39f8f7f9227c 100644 --- a/arch/arm64/kvm/hyp/vgic-v3-sr.c +++ b/arch/arm64/kvm/hyp/vgic-v3-sr.c @@ -429,6 +429,13 @@ u64 __vgic_v3_get_gic_config(void) if (has_vhe()) flags = local_daif_save(); + /* + * Table 11-2 "Permitted ICC_SRE_ELx.SRE settings" indicates + * that to be able to set ICC_SRE_EL1.SRE to 0, all the + * interrupt overrides must be set. You've got to love this. + */ + sysreg_clear_set(hcr_el2, 0, HCR_AMO | HCR_FMO | HCR_IMO); + isb(); write_gicreg(0, ICC_SRE_EL1); isb(); @@ -436,6 +443,8 @@ u64 __vgic_v3_get_gic_config(void) write_gicreg(sre, ICC_SRE_EL1); isb(); + sysreg_clear_set(hcr_el2, HCR_AMO | HCR_FMO | HCR_IMO, 0); + isb(); if (has_vhe()) local_daif_restore(flags); From 203773e39347922b3923df6094324d430664466e Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Mar 2021 17:58:43 +0800 Subject: [PATCH 0366/1091] ASoC: fsl_esai: Don't use devm_regmap_init_mmio_clk When there is power domain bind with bus clock, The call flow: devm_regmap_init_mmio_clk - clk_prepare() - clk_pm_runtime_get() cause the power domain of clock always be enabled after regmap_init(). which impact the power consumption. So use devm_regmap_init_mmio instead of devm_regmap_init_mmio_clk,but explicitly enable clock when it is used. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1616579928-22428-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_esai.c | 48 ++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 12 deletions(-) diff --git a/sound/soc/fsl/fsl_esai.c b/sound/soc/fsl/fsl_esai.c index 41b154417b92..c0d4f3c5dbb1 100644 --- a/sound/soc/fsl/fsl_esai.c +++ b/sound/soc/fsl/fsl_esai.c @@ -945,6 +945,9 @@ static const struct regmap_config fsl_esai_regmap_config = { .cache_type = REGCACHE_FLAT, }; +static int fsl_esai_runtime_resume(struct device *dev); +static int fsl_esai_runtime_suspend(struct device *dev); + static int fsl_esai_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -969,8 +972,7 @@ static int fsl_esai_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - esai_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, - "core", regs, &fsl_esai_regmap_config); + esai_priv->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &fsl_esai_regmap_config); if (IS_ERR(esai_priv->regmap)) { dev_err(&pdev->dev, "failed to init regmap: %ld\n", PTR_ERR(esai_priv->regmap)); @@ -1039,11 +1041,23 @@ static int fsl_esai_probe(struct platform_device *pdev) } dev_set_drvdata(&pdev->dev, esai_priv); - spin_lock_init(&esai_priv->lock); + pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + ret = fsl_esai_runtime_resume(&pdev->dev); + if (ret) + goto err_pm_disable; + } + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); + goto err_pm_get_sync; + } + ret = fsl_esai_hw_init(esai_priv); if (ret) - return ret; + goto err_pm_get_sync; esai_priv->tx_mask = 0xFFFFFFFF; esai_priv->rx_mask = 0xFFFFFFFF; @@ -1054,24 +1068,33 @@ static int fsl_esai_probe(struct platform_device *pdev) regmap_write(esai_priv->regmap, REG_ESAI_RSMA, 0); regmap_write(esai_priv->regmap, REG_ESAI_RSMB, 0); + ret = pm_runtime_put_sync(&pdev->dev); + if (ret < 0) + goto err_pm_get_sync; + ret = devm_snd_soc_register_component(&pdev->dev, &fsl_esai_component, &fsl_esai_dai, 1); if (ret) { dev_err(&pdev->dev, "failed to register DAI: %d\n", ret); - return ret; + goto err_pm_get_sync; } INIT_WORK(&esai_priv->work, fsl_esai_hw_reset); - pm_runtime_enable(&pdev->dev); - - regcache_cache_only(esai_priv->regmap, true); - ret = imx_pcm_dma_init(pdev, IMX_ESAI_DMABUF_SIZE); - if (ret) + if (ret) { dev_err(&pdev->dev, "failed to init imx pcm dma: %d\n", ret); + goto err_pm_get_sync; + } return ret; + +err_pm_get_sync: + if (!pm_runtime_status_suspended(&pdev->dev)) + fsl_esai_runtime_suspend(&pdev->dev); +err_pm_disable: + pm_runtime_disable(&pdev->dev); + return ret; } static int fsl_esai_remove(struct platform_device *pdev) @@ -1079,6 +1102,9 @@ static int fsl_esai_remove(struct platform_device *pdev) struct fsl_esai *esai_priv = platform_get_drvdata(pdev); pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + fsl_esai_runtime_suspend(&pdev->dev); + cancel_work_sync(&esai_priv->work); return 0; @@ -1092,7 +1118,6 @@ static const struct of_device_id fsl_esai_dt_ids[] = { }; MODULE_DEVICE_TABLE(of, fsl_esai_dt_ids); -#ifdef CONFIG_PM static int fsl_esai_runtime_resume(struct device *dev) { struct fsl_esai *esai = dev_get_drvdata(dev); @@ -1160,7 +1185,6 @@ static int fsl_esai_runtime_suspend(struct device *dev) return 0; } -#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_esai_pm_ops = { SET_RUNTIME_PM_OPS(fsl_esai_runtime_suspend, From c2562572467a74fd637d2d22fb773b052512528c Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Mar 2021 17:58:44 +0800 Subject: [PATCH 0367/1091] ASoC: fsl_spdif: Don't use devm_regmap_init_mmio_clk When there is power domain bind with core clock, The call flow: devm_regmap_init_mmio_clk - clk_prepare() - clk_pm_runtime_get() cause the power domain of clock always be enabled after regmap_init(). which impact the power consumption. So use devm_regmap_init_mmio instead of devm_regmap_init_mmio_clk,but explicitly enable clock when it is used. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1616579928-22428-3-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_spdif.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_spdif.c b/sound/soc/fsl/fsl_spdif.c index 1cd3441d1c03..c631de325a6e 100644 --- a/sound/soc/fsl/fsl_spdif.c +++ b/sound/soc/fsl/fsl_spdif.c @@ -1294,8 +1294,7 @@ static int fsl_spdif_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - spdif_priv->regmap = devm_regmap_init_mmio_clk(&pdev->dev, - "core", regs, &fsl_spdif_regmap_config); + spdif_priv->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &fsl_spdif_regmap_config); if (IS_ERR(spdif_priv->regmap)) { dev_err(&pdev->dev, "regmap init failed\n"); return PTR_ERR(spdif_priv->regmap); From cab04ab5900fea6655f2a49d1f94c37200b63a59 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Mar 2021 17:58:45 +0800 Subject: [PATCH 0368/1091] ASoC: fsl_asrc: Don't use devm_regmap_init_mmio_clk When there is power domain bind with mem clock, The call flow: devm_regmap_init_mmio_clk - clk_prepare() - clk_pm_runtime_get() cause the power domain of clock always be enabled after regmap_init(). which impact the power consumption. So use devm_regmap_init_mmio instead of devm_regmap_init_mmio_clk,but explicitly enable clock when it is used. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1616579928-22428-4-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_asrc.c | 57 +++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 13 deletions(-) diff --git a/sound/soc/fsl/fsl_asrc.c b/sound/soc/fsl/fsl_asrc.c index 63d236ef5c4d..0e1ad8efebd3 100644 --- a/sound/soc/fsl/fsl_asrc.c +++ b/sound/soc/fsl/fsl_asrc.c @@ -1008,6 +1008,9 @@ static int fsl_asrc_get_fifo_addr(u8 dir, enum asrc_pair_index index) return REG_ASRDx(dir, index); } +static int fsl_asrc_runtime_resume(struct device *dev); +static int fsl_asrc_runtime_suspend(struct device *dev); + static int fsl_asrc_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; @@ -1039,8 +1042,7 @@ static int fsl_asrc_probe(struct platform_device *pdev) asrc->paddr = res->start; - asrc->regmap = devm_regmap_init_mmio_clk(&pdev->dev, "mem", regs, - &fsl_asrc_regmap_config); + asrc->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &fsl_asrc_regmap_config); if (IS_ERR(asrc->regmap)) { dev_err(&pdev->dev, "failed to init regmap\n"); return PTR_ERR(asrc->regmap); @@ -1117,12 +1119,6 @@ static int fsl_asrc_probe(struct platform_device *pdev) } } - ret = fsl_asrc_init(asrc); - if (ret) { - dev_err(&pdev->dev, "failed to init asrc %d\n", ret); - return ret; - } - asrc->channel_avail = 10; ret = of_property_read_u32(np, "fsl,asrc-rate", @@ -1161,21 +1157,56 @@ static int fsl_asrc_probe(struct platform_device *pdev) } platform_set_drvdata(pdev, asrc); - pm_runtime_enable(&pdev->dev); spin_lock_init(&asrc->lock); - regcache_cache_only(asrc->regmap, true); + pm_runtime_enable(&pdev->dev); + if (!pm_runtime_enabled(&pdev->dev)) { + ret = fsl_asrc_runtime_resume(&pdev->dev); + if (ret) + goto err_pm_disable; + } + + ret = pm_runtime_get_sync(&pdev->dev); + if (ret < 0) { + pm_runtime_put_noidle(&pdev->dev); + goto err_pm_get_sync; + } + + ret = fsl_asrc_init(asrc); + if (ret) { + dev_err(&pdev->dev, "failed to init asrc %d\n", ret); + goto err_pm_get_sync; + } + + ret = pm_runtime_put_sync(&pdev->dev); + if (ret < 0) + goto err_pm_get_sync; ret = devm_snd_soc_register_component(&pdev->dev, &fsl_asrc_component, &fsl_asrc_dai, 1); if (ret) { dev_err(&pdev->dev, "failed to register ASoC DAI\n"); - return ret; + goto err_pm_get_sync; } return 0; + +err_pm_get_sync: + if (!pm_runtime_status_suspended(&pdev->dev)) + fsl_asrc_runtime_suspend(&pdev->dev); +err_pm_disable: + pm_runtime_disable(&pdev->dev); + return ret; +} + +static int fsl_asrc_remove(struct platform_device *pdev) +{ + pm_runtime_disable(&pdev->dev); + if (!pm_runtime_status_suspended(&pdev->dev)) + fsl_asrc_runtime_suspend(&pdev->dev); + + return 0; } -#ifdef CONFIG_PM static int fsl_asrc_runtime_resume(struct device *dev) { struct fsl_asrc *asrc = dev_get_drvdata(dev); @@ -1252,7 +1283,6 @@ static int fsl_asrc_runtime_suspend(struct device *dev) return 0; } -#endif /* CONFIG_PM */ static const struct dev_pm_ops fsl_asrc_pm = { SET_RUNTIME_PM_OPS(fsl_asrc_runtime_suspend, fsl_asrc_runtime_resume, NULL) @@ -1291,6 +1321,7 @@ MODULE_DEVICE_TABLE(of, fsl_asrc_ids); static struct platform_driver fsl_asrc_driver = { .probe = fsl_asrc_probe, + .remove = fsl_asrc_remove, .driver = { .name = "fsl-asrc", .of_match_table = fsl_asrc_ids, From 069b24f22eb9dba2e0886b40ea3feaa98e3f4f9b Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Mar 2021 17:58:46 +0800 Subject: [PATCH 0369/1091] ASoC: fsl_easrc: Don't use devm_regmap_init_mmio_clk When there is power domain bind with mem clock, The call flow: devm_regmap_init_mmio_clk - clk_prepare() - clk_pm_runtime_get() cause the power domain of clock always be enabled after regmap_init(). which impact the power consumption. So use devm_regmap_init_mmio instead of devm_regmap_init_mmio_clk,but explicitly enable clock when it is used. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1616579928-22428-5-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_easrc.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 600e0d670ca6..5e33afe87c4a 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1896,8 +1896,7 @@ static int fsl_easrc_probe(struct platform_device *pdev) easrc->paddr = res->start; - easrc->regmap = devm_regmap_init_mmio_clk(dev, "mem", regs, - &fsl_easrc_regmap_config); + easrc->regmap = devm_regmap_init_mmio(dev, regs, &fsl_easrc_regmap_config); if (IS_ERR(easrc->regmap)) { dev_err(dev, "failed to init regmap"); return PTR_ERR(easrc->regmap); From 3feaba79d8f701a774815483aa0e7f4edb15c880 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Mar 2021 17:58:47 +0800 Subject: [PATCH 0370/1091] ASoC: fsl_audmix: Don't use devm_regmap_init_mmio_clk When there is power domain bind with ipg clock, The call flow: devm_regmap_init_mmio_clk - clk_prepare() - clk_pm_runtime_get() cause the power domain of clock always be enabled after regmap_init(). which impact the power consumption. So use devm_regmap_init_mmio instead of devm_regmap_init_mmio_clk,but explicitly enable clock when it is used. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1616579928-22428-6-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_audmix.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/fsl/fsl_audmix.c b/sound/soc/fsl/fsl_audmix.c index 8dc44dec7956..f931288e256c 100644 --- a/sound/soc/fsl/fsl_audmix.c +++ b/sound/soc/fsl/fsl_audmix.c @@ -476,8 +476,7 @@ static int fsl_audmix_probe(struct platform_device *pdev) if (IS_ERR(regs)) return PTR_ERR(regs); - priv->regmap = devm_regmap_init_mmio_clk(dev, "ipg", regs, - &fsl_audmix_regmap_config); + priv->regmap = devm_regmap_init_mmio(dev, regs, &fsl_audmix_regmap_config); if (IS_ERR(priv->regmap)) { dev_err(dev, "failed to init regmap\n"); return PTR_ERR(priv->regmap); From b5cf28f7a890f3554ca15a43edbbb86dd1b9663c Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 24 Mar 2021 17:58:48 +0800 Subject: [PATCH 0371/1091] ASoC: fsl_micfil: Don't use devm_regmap_init_mmio_clk When there is power domain bind with ipg_clk clock, The call flow: devm_regmap_init_mmio_clk - clk_prepare() - clk_pm_runtime_get() cause the power domain of clock always be enabled after regmap_init(). which impact the power consumption. So use devm_regmap_init_mmio instead of devm_regmap_init_mmio_clk,but explicitly enable clock when it is used. Signed-off-by: Shengjiu Wang Reviewed-by: Viorel Suman Link: https://lore.kernel.org/r/1616579928-22428-7-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_micfil.c | 25 ++++++++++++++++++++----- 1 file changed, 20 insertions(+), 5 deletions(-) diff --git a/sound/soc/fsl/fsl_micfil.c b/sound/soc/fsl/fsl_micfil.c index 2b9edd4bb94d..3cf789ed6cbe 100644 --- a/sound/soc/fsl/fsl_micfil.c +++ b/sound/soc/fsl/fsl_micfil.c @@ -31,6 +31,7 @@ struct fsl_micfil { struct platform_device *pdev; struct regmap *regmap; const struct fsl_micfil_soc_data *soc; + struct clk *busclk; struct clk *mclk; struct snd_dmaengine_dai_dma_data dma_params_rx; unsigned int dataline; @@ -660,16 +661,22 @@ static int fsl_micfil_probe(struct platform_device *pdev) return PTR_ERR(micfil->mclk); } + micfil->busclk = devm_clk_get(&pdev->dev, "ipg_clk"); + if (IS_ERR(micfil->busclk)) { + dev_err(&pdev->dev, "failed to get ipg clock: %ld\n", + PTR_ERR(micfil->busclk)); + return PTR_ERR(micfil->busclk); + } + /* init regmap */ res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); if (IS_ERR(regs)) return PTR_ERR(regs); - micfil->regmap = devm_regmap_init_mmio_clk(&pdev->dev, - "ipg_clk", - regs, - &fsl_micfil_regmap_config); + micfil->regmap = devm_regmap_init_mmio(&pdev->dev, + regs, + &fsl_micfil_regmap_config); if (IS_ERR(micfil->regmap)) { dev_err(&pdev->dev, "failed to init MICFIL regmap: %ld\n", PTR_ERR(micfil->regmap)); @@ -729,6 +736,7 @@ static int fsl_micfil_probe(struct platform_device *pdev) platform_set_drvdata(pdev, micfil); pm_runtime_enable(&pdev->dev); + regcache_cache_only(micfil->regmap, true); ret = devm_snd_soc_register_component(&pdev->dev, &fsl_micfil_component, &fsl_micfil_dai, 1); @@ -752,6 +760,7 @@ static int __maybe_unused fsl_micfil_runtime_suspend(struct device *dev) regcache_cache_only(micfil->regmap, true); clk_disable_unprepare(micfil->mclk); + clk_disable_unprepare(micfil->busclk); return 0; } @@ -761,10 +770,16 @@ static int __maybe_unused fsl_micfil_runtime_resume(struct device *dev) struct fsl_micfil *micfil = dev_get_drvdata(dev); int ret; - ret = clk_prepare_enable(micfil->mclk); + ret = clk_prepare_enable(micfil->busclk); if (ret < 0) return ret; + ret = clk_prepare_enable(micfil->mclk); + if (ret < 0) { + clk_disable_unprepare(micfil->busclk); + return ret; + } + regcache_cache_only(micfil->regmap, false); regcache_mark_dirty(micfil->regmap); regcache_sync(micfil->regmap); From bcda8cc4b868782c1a39d722d24f7d2598978389 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:01 +0100 Subject: [PATCH 0372/1091] ASoC: arizona-jack: Move jack-detect variables to struct arizona_priv Move all the jack-detect variables from struct arizona_extcon_info to struct arizona_priv. This is part of a patch series converting the arizona extcon driver into a helper library for letting the arizona codec-drivers directly report jack state through the standard sound/soc/soc-jack.c functions. Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307151807.35201-8-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/arizona-jack.c | 97 ++++++++++----------------------- sound/soc/codecs/arizona.h | 36 ++++++++++++ 2 files changed, 65 insertions(+), 68 deletions(-) diff --git a/sound/soc/codecs/arizona-jack.c b/sound/soc/codecs/arizona-jack.c index 56d2ce05de50..5b40316d0d75 100644 --- a/sound/soc/codecs/arizona-jack.c +++ b/sound/soc/codecs/arizona-jack.c @@ -27,6 +27,8 @@ #include #include +#include "arizona.h" + #define ARIZONA_MAX_MICD_RANGE 8 #define ARIZONA_MICD_CLAMP_MODE_JDL 0x4 @@ -61,47 +63,6 @@ #define MICD_LVL_0_TO_8 (MICD_LVL_0_TO_7 | ARIZONA_MICD_LVL_8) -struct arizona_extcon_info { - struct device *dev; - struct arizona *arizona; - struct mutex lock; - struct regulator *micvdd; - struct input_dev *input; - - u16 last_jackdet; - - int micd_mode; - const struct arizona_micd_config *micd_modes; - int micd_num_modes; - - const struct arizona_micd_range *micd_ranges; - int num_micd_ranges; - - bool micd_reva; - bool micd_clamp; - - struct delayed_work hpdet_work; - struct delayed_work micd_detect_work; - struct delayed_work micd_timeout_work; - - bool hpdet_active; - bool hpdet_done; - bool hpdet_retried; - - int num_hpdet_res; - unsigned int hpdet_res[3]; - - bool mic; - bool detecting; - int jack_flips; - - int hpdet_ip_version; - - struct extcon_dev *edev; - - struct gpio_desc *micd_pol_gpio; -}; - static const struct arizona_micd_config micd_default_modes[] = { { ARIZONA_ACCDET_SRC, 1, 0 }, { 0, 2, 1 }, @@ -135,9 +96,9 @@ static const unsigned int arizona_cable[] = { EXTCON_NONE, }; -static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info); +static void arizona_start_hpdet_acc_id(struct arizona_priv *info); -static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, +static void arizona_extcon_hp_clamp(struct arizona_priv *info, bool clamp) { struct arizona *arizona = info->arizona; @@ -222,7 +183,7 @@ static void arizona_extcon_hp_clamp(struct arizona_extcon_info *info, snd_soc_dapm_mutex_unlock(arizona->dapm); } -static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) +static void arizona_extcon_set_mode(struct arizona_priv *info, int mode) { struct arizona *arizona = info->arizona; @@ -243,7 +204,7 @@ static void arizona_extcon_set_mode(struct arizona_extcon_info *info, int mode) dev_dbg(arizona->dev, "Set jack polarity to %d\n", mode); } -static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info) +static const char *arizona_extcon_get_micbias(struct arizona_priv *info) { switch (info->micd_modes[0].bias) { case 1: @@ -257,7 +218,7 @@ static const char *arizona_extcon_get_micbias(struct arizona_extcon_info *info) } } -static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info) +static void arizona_extcon_pulse_micbias(struct arizona_priv *info) { struct arizona *arizona = info->arizona; const char *widget = arizona_extcon_get_micbias(info); @@ -282,7 +243,7 @@ static void arizona_extcon_pulse_micbias(struct arizona_extcon_info *info) } } -static void arizona_start_mic(struct arizona_extcon_info *info) +static void arizona_start_mic(struct arizona_priv *info) { struct arizona *arizona = info->arizona; bool change; @@ -339,7 +300,7 @@ static void arizona_start_mic(struct arizona_extcon_info *info) } } -static void arizona_stop_mic(struct arizona_extcon_info *info) +static void arizona_stop_mic(struct arizona_priv *info) { struct arizona *arizona = info->arizona; const char *widget = arizona_extcon_get_micbias(info); @@ -407,7 +368,7 @@ static struct { { 1000, 10000 }, }; -static int arizona_hpdet_read(struct arizona_extcon_info *info) +static int arizona_hpdet_read(struct arizona_priv *info) { struct arizona *arizona = info->arizona; unsigned int val, range; @@ -527,7 +488,7 @@ static int arizona_hpdet_read(struct arizona_extcon_info *info) return val; } -static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading, +static int arizona_hpdet_do_id(struct arizona_priv *info, int *reading, bool *mic) { struct arizona *arizona = info->arizona; @@ -597,7 +558,7 @@ static int arizona_hpdet_do_id(struct arizona_extcon_info *info, int *reading, static irqreturn_t arizona_hpdet_irq(int irq, void *data) { - struct arizona_extcon_info *info = data; + struct arizona_priv *info = data; struct arizona *arizona = info->arizona; int id_gpio = arizona->pdata.hpdet_id_gpio; unsigned int report = EXTCON_JACK_HEADPHONE; @@ -684,7 +645,7 @@ out: return IRQ_HANDLED; } -static void arizona_identify_headphone(struct arizona_extcon_info *info) +static void arizona_identify_headphone(struct arizona_priv *info) { struct arizona *arizona = info->arizona; int ret; @@ -737,7 +698,7 @@ err: info->hpdet_active = false; } -static void arizona_start_hpdet_acc_id(struct arizona_extcon_info *info) +static void arizona_start_hpdet_acc_id(struct arizona_priv *info) { struct arizona *arizona = info->arizona; int hp_reading = 32; @@ -790,8 +751,8 @@ err: static void arizona_micd_timeout_work(struct work_struct *work) { - struct arizona_extcon_info *info = container_of(work, - struct arizona_extcon_info, + struct arizona_priv *info = container_of(work, + struct arizona_priv, micd_timeout_work.work); mutex_lock(&info->lock); @@ -805,7 +766,7 @@ static void arizona_micd_timeout_work(struct work_struct *work) mutex_unlock(&info->lock); } -static int arizona_micd_adc_read(struct arizona_extcon_info *info) +static int arizona_micd_adc_read(struct arizona_priv *info) { struct arizona *arizona = info->arizona; unsigned int val; @@ -842,7 +803,7 @@ static int arizona_micd_adc_read(struct arizona_extcon_info *info) return val; } -static int arizona_micd_read(struct arizona_extcon_info *info) +static int arizona_micd_read(struct arizona_priv *info) { struct arizona *arizona = info->arizona; unsigned int val = 0; @@ -875,7 +836,7 @@ static int arizona_micd_read(struct arizona_extcon_info *info) static int arizona_micdet_reading(void *priv) { - struct arizona_extcon_info *info = priv; + struct arizona_priv *info = priv; struct arizona *arizona = info->arizona; int ret, val; @@ -969,7 +930,7 @@ static int arizona_micdet_reading(void *priv) static int arizona_button_reading(void *priv) { - struct arizona_extcon_info *info = priv; + struct arizona_priv *info = priv; struct arizona *arizona = info->arizona; int val, key, lvl, i; @@ -1017,8 +978,8 @@ static int arizona_button_reading(void *priv) static void arizona_micd_detect(struct work_struct *work) { - struct arizona_extcon_info *info = container_of(work, - struct arizona_extcon_info, + struct arizona_priv *info = container_of(work, + struct arizona_priv, micd_detect_work.work); struct arizona *arizona = info->arizona; int ret; @@ -1051,7 +1012,7 @@ static void arizona_micd_detect(struct work_struct *work) static irqreturn_t arizona_micdet(int irq, void *data) { - struct arizona_extcon_info *info = data; + struct arizona_priv *info = data; struct arizona *arizona = info->arizona; int debounce = arizona->pdata.micd_detect_debounce; @@ -1075,8 +1036,8 @@ static irqreturn_t arizona_micdet(int irq, void *data) static void arizona_hpdet_work(struct work_struct *work) { - struct arizona_extcon_info *info = container_of(work, - struct arizona_extcon_info, + struct arizona_priv *info = container_of(work, + struct arizona_priv, hpdet_work.work); mutex_lock(&info->lock); @@ -1084,7 +1045,7 @@ static void arizona_hpdet_work(struct work_struct *work) mutex_unlock(&info->lock); } -static int arizona_hpdet_wait(struct arizona_extcon_info *info) +static int arizona_hpdet_wait(struct arizona_priv *info) { struct arizona *arizona = info->arizona; unsigned int val; @@ -1120,7 +1081,7 @@ static int arizona_hpdet_wait(struct arizona_extcon_info *info) static irqreturn_t arizona_jackdet(int irq, void *data) { - struct arizona_extcon_info *info = data; + struct arizona_priv *info = data; struct arizona *arizona = info->arizona; unsigned int val, present, mask; bool cancelled_hp, cancelled_mic; @@ -1380,7 +1341,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) { struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); struct arizona_pdata *pdata = &arizona->pdata; - struct arizona_extcon_info *info; + struct arizona_priv *info; unsigned int val; unsigned int clamp_mode; int jack_irq_fall, jack_irq_rise; @@ -1754,7 +1715,7 @@ err_gpio: static int arizona_extcon_remove(struct platform_device *pdev) { - struct arizona_extcon_info *info = platform_get_drvdata(pdev); + struct arizona_priv *info = platform_get_drvdata(pdev); struct arizona *arizona = info->arizona; int jack_irq_rise, jack_irq_fall; bool change; diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index b3abbe80f11d..fdd19dd9896d 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -91,6 +91,42 @@ struct arizona_priv { unsigned int dvfs_reqs; struct mutex dvfs_lock; bool dvfs_cached; + + /* Variables used by arizona-jack.c code */ + struct device *dev; + struct mutex lock; + struct delayed_work hpdet_work; + struct delayed_work micd_detect_work; + struct delayed_work micd_timeout_work; + struct regulator *micvdd; + struct input_dev *input; + struct extcon_dev *edev; + struct gpio_desc *micd_pol_gpio; + + u16 last_jackdet; + + int micd_mode; + const struct arizona_micd_config *micd_modes; + int micd_num_modes; + + const struct arizona_micd_range *micd_ranges; + int num_micd_ranges; + + bool micd_reva; + bool micd_clamp; + + bool hpdet_active; + bool hpdet_done; + bool hpdet_retried; + + bool mic; + bool detecting; + + int num_hpdet_res; + unsigned int hpdet_res[3]; + + int jack_flips; + int hpdet_ip_version; }; struct arizona_voice_trigger_info { From 688c8461a425623ca6f679e6ba8965719a98def5 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:02 +0100 Subject: [PATCH 0373/1091] ASoC: arizona-jack: Use arizona->dev for runtime-pm Drivers for MFD child-devices such as the arizona codec drivers and the arizona-extcon driver can choose to either make runtime_pm_get/_put calls on their own child-device, which will then be propagated to their parent; or they can make them directly on their MFD parent-device. The arizona-extcon code was using runtime_pm_get/_put calls on its own child-device where as the codec drivers are using runtime_pm_get/_put calls on their parent. The arizona-extcon MFD cell/child-device has been removed and this commit is part of refactoring the arizona-extcon code into a library to be used directly from the codec drivers. Specifically this commit moves the code over to make runtime_pm_get/_put calls on the parent device (on arizona->dev) bringing the code inline with how the codec drivers do this. Note this also removes the pm_runtime_enable/_disable calls as pm_runtime support has already been enabled on the parent-device by the arizona MFD driver. This is part of a patch series converting the arizona extcon driver into a helper library for letting the arizona codec-drivers directly report jack state through the standard sound/soc/soc-jack.c functions. Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307151807.35201-9-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/arizona-jack.c | 42 ++++++++++++++------------------- sound/soc/codecs/arizona.h | 1 - 2 files changed, 18 insertions(+), 25 deletions(-) diff --git a/sound/soc/codecs/arizona-jack.c b/sound/soc/codecs/arizona-jack.c index 5b40316d0d75..a6e8071f84ab 100644 --- a/sound/soc/codecs/arizona-jack.c +++ b/sound/soc/codecs/arizona-jack.c @@ -251,7 +251,7 @@ static void arizona_start_mic(struct arizona_priv *info) unsigned int mode; /* Microphone detection can't use idle mode */ - pm_runtime_get_sync(info->dev); + pm_runtime_get_sync(arizona->dev); if (info->detecting) { ret = regulator_allow_bypass(info->micvdd, false); @@ -296,7 +296,7 @@ static void arizona_start_mic(struct arizona_priv *info) dev_err(arizona->dev, "Failed to enable micd: %d\n", ret); } else if (!change) { regulator_disable(info->micvdd); - pm_runtime_put_autosuspend(info->dev); + pm_runtime_put_autosuspend(arizona->dev); } } @@ -341,8 +341,8 @@ static void arizona_stop_mic(struct arizona_priv *info) if (change) { regulator_disable(info->micvdd); - pm_runtime_mark_last_busy(info->dev); - pm_runtime_put_autosuspend(info->dev); + pm_runtime_mark_last_busy(arizona->dev); + pm_runtime_put_autosuspend(arizona->dev); } } @@ -534,7 +534,7 @@ static int arizona_hpdet_do_id(struct arizona_priv *info, int *reading, info->num_hpdet_res = 0; info->hpdet_retried = true; arizona_start_hpdet_acc_id(info); - pm_runtime_put(info->dev); + pm_runtime_put(arizona->dev); return -EAGAIN; } @@ -631,7 +631,7 @@ done: arizona_start_mic(info); if (info->hpdet_active) { - pm_runtime_put_autosuspend(info->dev); + pm_runtime_put_autosuspend(arizona->dev); info->hpdet_active = false; } @@ -656,7 +656,7 @@ static void arizona_identify_headphone(struct arizona_priv *info) dev_dbg(arizona->dev, "Starting HPDET\n"); /* Make sure we keep the device enabled during the measurement */ - pm_runtime_get_sync(info->dev); + pm_runtime_get_sync(arizona->dev); info->hpdet_active = true; @@ -685,7 +685,7 @@ static void arizona_identify_headphone(struct arizona_priv *info) err: arizona_extcon_hp_clamp(info, false); - pm_runtime_put_autosuspend(info->dev); + pm_runtime_put_autosuspend(arizona->dev); /* Just report headphone */ ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); @@ -708,7 +708,7 @@ static void arizona_start_hpdet_acc_id(struct arizona_priv *info) dev_dbg(arizona->dev, "Starting identification via HPDET\n"); /* Make sure we keep the device enabled during the measurement */ - pm_runtime_get_sync(info->dev); + pm_runtime_get_sync(arizona->dev); info->hpdet_active = true; @@ -1006,7 +1006,7 @@ static void arizona_micd_detect(struct work_struct *work) else arizona_button_reading(info); - pm_runtime_mark_last_busy(info->dev); + pm_runtime_mark_last_busy(arizona->dev); mutex_unlock(&info->lock); } @@ -1090,7 +1090,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) cancelled_hp = cancel_delayed_work_sync(&info->hpdet_work); cancelled_mic = cancel_delayed_work_sync(&info->micd_timeout_work); - pm_runtime_get_sync(info->dev); + pm_runtime_get_sync(arizona->dev); mutex_lock(&info->lock); @@ -1110,7 +1110,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) dev_err(arizona->dev, "Failed to read jackdet status: %d\n", ret); mutex_unlock(&info->lock); - pm_runtime_put_autosuspend(info->dev); + pm_runtime_put_autosuspend(arizona->dev); return IRQ_NONE; } @@ -1210,8 +1210,8 @@ out: mutex_unlock(&info->lock); - pm_runtime_mark_last_busy(info->dev); - pm_runtime_put_autosuspend(info->dev); + pm_runtime_mark_last_busy(arizona->dev); + pm_runtime_put_autosuspend(arizona->dev); return IRQ_HANDLED; } @@ -1366,7 +1366,6 @@ static int arizona_extcon_probe(struct platform_device *pdev) mutex_init(&info->lock); info->arizona = arizona; - info->dev = &pdev->dev; info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS); INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work); INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect); @@ -1617,9 +1616,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) arizona_extcon_set_mode(info, 0); - pm_runtime_enable(&pdev->dev); - pm_runtime_idle(&pdev->dev); - pm_runtime_get_sync(&pdev->dev); + pm_runtime_get_sync(arizona->dev); if (info->micd_clamp) { jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; @@ -1689,7 +1686,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) goto err_hpdet; } - pm_runtime_put(&pdev->dev); + pm_runtime_put(arizona->dev); return 0; @@ -1706,8 +1703,7 @@ err_rise_wake: err_rise: arizona_free_irq(arizona, jack_irq_rise, info); err_pm: - pm_runtime_put(&pdev->dev); - pm_runtime_disable(&pdev->dev); + pm_runtime_put(arizona->dev); err_gpio: gpiod_put(info->micd_pol_gpio); return ret; @@ -1747,7 +1743,7 @@ static int arizona_extcon_remove(struct platform_device *pdev) ret); } else if (change) { regulator_disable(info->micvdd); - pm_runtime_put(info->dev); + pm_runtime_put(arizona->dev); } regmap_update_bits(arizona->regmap, @@ -1759,8 +1755,6 @@ static int arizona_extcon_remove(struct platform_device *pdev) gpiod_put(info->micd_pol_gpio); - pm_runtime_disable(&pdev->dev); - return 0; } diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index fdd19dd9896d..afc34e13d33c 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -93,7 +93,6 @@ struct arizona_priv { bool dvfs_cached; /* Variables used by arizona-jack.c code */ - struct device *dev; struct mutex lock; struct delayed_work hpdet_work; struct delayed_work micd_detect_work; From ffcc84b9e814c8654e15e08816d0078d521a2724 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:03 +0100 Subject: [PATCH 0374/1091] ASoC: arizona-jack: convert into a helper library for codec drivers Convert the arizona extcon driver into a helper library for direct use from the arizona codec-drivers, rather then being bound to a separate MFD cell. Note the probe (and remove) sequence is split into 2 parts: 1. The arizona_jack_codec_dev_probe() function inits a bunch of jack-detect specific variables in struct arizona_priv and tries to get a number of resources where getting them may fail with -EPROBE_DEFER. 2. Then once the machine driver has create a snd_sock_jack through snd_soc_card_jack_new() it calls snd_soc_component_set_jack() on the codec component, which will call the new arizona_jack_set_jack(), which sets up jack-detection and requests the IRQs. This split is necessary, because the IRQ handlers need access to the arizona->dapm pointer and the snd_sock_jack which are not available when the codec-driver's probe function runs. Note this requires that machine-drivers for codecs which are converted to use the new helper functions from arizona-jack.c are modified to create a snd_soc_jack through snd_soc_card_jack_new() and register this jack with the codec through snd_soc_component_set_jack(). Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307151807.35201-10-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/Makefile | 2 +- sound/soc/codecs/arizona-jack.c | 125 +++++++++++++++----------------- sound/soc/codecs/arizona.h | 6 ++ 3 files changed, 65 insertions(+), 68 deletions(-) diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index edff5c5b92d3..a710dfea7876 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -43,7 +43,7 @@ snd-soc-ak4642-objs := ak4642.o snd-soc-ak4671-objs := ak4671.o snd-soc-ak5386-objs := ak5386.o snd-soc-ak5558-objs := ak5558.o -snd-soc-arizona-objs := arizona.o +snd-soc-arizona-objs := arizona.o arizona-jack.o snd-soc-bd28623-objs := bd28623.o snd-soc-bt-sco-objs := bt-sco.o snd-soc-cpcap-objs := cpcap.o diff --git a/sound/soc/codecs/arizona-jack.c b/sound/soc/codecs/arizona-jack.c index a6e8071f84ab..e121490eb379 100644 --- a/sound/soc/codecs/arizona-jack.c +++ b/sound/soc/codecs/arizona-jack.c @@ -7,14 +7,12 @@ #include #include -#include #include #include #include #include #include #include -#include #include #include #include @@ -1337,27 +1335,16 @@ static int arizona_extcon_device_get_pdata(struct device *dev, return 0; } -static int arizona_extcon_probe(struct platform_device *pdev) +int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev) { - struct arizona *arizona = dev_get_drvdata(pdev->dev.parent); + struct arizona *arizona = info->arizona; struct arizona_pdata *pdata = &arizona->pdata; - struct arizona_priv *info; - unsigned int val; - unsigned int clamp_mode; - int jack_irq_fall, jack_irq_rise; - int ret, mode, i, j; - - if (!arizona->dapm || !arizona->dapm->card) - return -EPROBE_DEFER; - - info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); - if (!info) - return -ENOMEM; + int ret, mode; if (!dev_get_platdata(arizona->dev)) - arizona_extcon_device_get_pdata(&pdev->dev, arizona); + arizona_extcon_device_get_pdata(dev, arizona); - info->micvdd = devm_regulator_get(&pdev->dev, "MICVDD"); + info->micvdd = devm_regulator_get(dev, "MICVDD"); if (IS_ERR(info->micvdd)) { ret = PTR_ERR(info->micvdd); dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); @@ -1365,12 +1352,10 @@ static int arizona_extcon_probe(struct platform_device *pdev) } mutex_init(&info->lock); - info->arizona = arizona; info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS); INIT_DELAYED_WORK(&info->hpdet_work, arizona_hpdet_work); INIT_DELAYED_WORK(&info->micd_detect_work, arizona_micd_detect); INIT_DELAYED_WORK(&info->micd_timeout_work, arizona_micd_timeout_work); - platform_set_drvdata(pdev, info); switch (arizona->type) { case WM5102: @@ -1404,20 +1389,20 @@ static int arizona_extcon_probe(struct platform_device *pdev) break; } - info->edev = devm_extcon_dev_allocate(&pdev->dev, arizona_cable); + info->edev = devm_extcon_dev_allocate(dev, arizona_cable); if (IS_ERR(info->edev)) { - dev_err(&pdev->dev, "failed to allocate extcon device\n"); + dev_err(arizona->dev, "failed to allocate extcon device\n"); return -ENOMEM; } - ret = devm_extcon_dev_register(&pdev->dev, info->edev); + ret = devm_extcon_dev_register(dev, info->edev); if (ret < 0) { dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", ret); return ret; } - info->input = devm_input_allocate_device(&pdev->dev); + info->input = devm_input_allocate_device(dev); if (!info->input) { dev_err(arizona->dev, "Can't allocate input dev\n"); ret = -ENOMEM; @@ -1448,7 +1433,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) else mode = GPIOF_OUT_INIT_LOW; - ret = devm_gpio_request_one(&pdev->dev, pdata->micd_pol_gpio, + ret = devm_gpio_request_one(dev, pdata->micd_pol_gpio, mode, "MICD polarity"); if (ret != 0) { dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", @@ -1481,17 +1466,38 @@ static int arizona_extcon_probe(struct platform_device *pdev) } if (arizona->pdata.hpdet_id_gpio > 0) { - ret = devm_gpio_request_one(&pdev->dev, - arizona->pdata.hpdet_id_gpio, + ret = devm_gpio_request_one(dev, arizona->pdata.hpdet_id_gpio, GPIOF_OUT_INIT_LOW, "HPDET"); if (ret != 0) { dev_err(arizona->dev, "Failed to request GPIO%d: %d\n", arizona->pdata.hpdet_id_gpio, ret); - goto err_gpio; + gpiod_put(info->micd_pol_gpio); + return ret; } } + return 0; +} +EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_probe); + +int arizona_jack_codec_dev_remove(struct arizona_priv *info) +{ + gpiod_put(info->micd_pol_gpio); + return 0; +} +EXPORT_SYMBOL_GPL(arizona_jack_codec_dev_remove); + +static int arizona_jack_enable_jack_detect(struct arizona_priv *info, + struct snd_soc_jack *jack) +{ + struct arizona *arizona = info->arizona; + struct arizona_pdata *pdata = &arizona->pdata; + unsigned int val; + unsigned int clamp_mode; + int jack_irq_fall, jack_irq_rise; + int ret, i, j; + if (arizona->pdata.micd_bias_start_time) regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_1, ARIZONA_MICD_BIAS_STARTTIME_MASK, @@ -1532,16 +1538,15 @@ static int arizona_extcon_probe(struct platform_device *pdev) if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) { dev_err(arizona->dev, "Too many MICD ranges: %d\n", arizona->pdata.num_micd_ranges); + return -EINVAL; } if (info->num_micd_ranges > 1) { for (i = 1; i < info->num_micd_ranges; i++) { if (info->micd_ranges[i - 1].max > info->micd_ranges[i].max) { - dev_err(arizona->dev, - "MICD ranges must be sorted\n"); - ret = -EINVAL; - goto err_gpio; + dev_err(arizona->dev, "MICD ranges must be sorted\n"); + return -EINVAL; } } } @@ -1559,8 +1564,7 @@ static int arizona_extcon_probe(struct platform_device *pdev) if (j == ARIZONA_NUM_MICD_BUTTON_LEVELS) { dev_err(arizona->dev, "Unsupported MICD level %d\n", info->micd_ranges[i].max); - ret = -EINVAL; - goto err_gpio; + return -EINVAL; } dev_dbg(arizona->dev, "%d ohms for MICD threshold %d\n", @@ -1629,43 +1633,40 @@ static int arizona_extcon_probe(struct platform_device *pdev) ret = arizona_request_irq(arizona, jack_irq_rise, "JACKDET rise", arizona_jackdet, info); if (ret != 0) { - dev_err(&pdev->dev, "Failed to get JACKDET rise IRQ: %d\n", - ret); + dev_err(arizona->dev, "Failed to get JACKDET rise IRQ: %d\n", ret); goto err_pm; } ret = arizona_set_irq_wake(arizona, jack_irq_rise, 1); if (ret != 0) { - dev_err(&pdev->dev, "Failed to set JD rise IRQ wake: %d\n", - ret); + dev_err(arizona->dev, "Failed to set JD rise IRQ wake: %d\n", ret); goto err_rise; } ret = arizona_request_irq(arizona, jack_irq_fall, "JACKDET fall", arizona_jackdet, info); if (ret != 0) { - dev_err(&pdev->dev, "Failed to get JD fall IRQ: %d\n", ret); + dev_err(arizona->dev, "Failed to get JD fall IRQ: %d\n", ret); goto err_rise_wake; } ret = arizona_set_irq_wake(arizona, jack_irq_fall, 1); if (ret != 0) { - dev_err(&pdev->dev, "Failed to set JD fall IRQ wake: %d\n", - ret); + dev_err(arizona->dev, "Failed to set JD fall IRQ wake: %d\n", ret); goto err_fall; } ret = arizona_request_irq(arizona, ARIZONA_IRQ_MICDET, "MICDET", arizona_micdet, info); if (ret != 0) { - dev_err(&pdev->dev, "Failed to get MICDET IRQ: %d\n", ret); + dev_err(arizona->dev, "Failed to get MICDET IRQ: %d\n", ret); goto err_fall_wake; } ret = arizona_request_irq(arizona, ARIZONA_IRQ_HPDET, "HPDET", arizona_hpdet_irq, info); if (ret != 0) { - dev_err(&pdev->dev, "Failed to get HPDET IRQ: %d\n", ret); + dev_err(arizona->dev, "Failed to get HPDET IRQ: %d\n", ret); goto err_micdet; } @@ -1677,12 +1678,11 @@ static int arizona_extcon_probe(struct platform_device *pdev) ret = regulator_allow_bypass(info->micvdd, true); if (ret != 0) - dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", - ret); + dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret); ret = input_register_device(info->input); if (ret) { - dev_err(&pdev->dev, "Can't register input device: %d\n", ret); + dev_err(arizona->dev, "Can't register input device: %d\n", ret); goto err_hpdet; } @@ -1704,14 +1704,11 @@ err_rise: arizona_free_irq(arizona, jack_irq_rise, info); err_pm: pm_runtime_put(arizona->dev); -err_gpio: - gpiod_put(info->micd_pol_gpio); return ret; } -static int arizona_extcon_remove(struct platform_device *pdev) +static int arizona_jack_disable_jack_detect(struct arizona_priv *info) { - struct arizona_priv *info = platform_get_drvdata(pdev); struct arizona *arizona = info->arizona; int jack_irq_rise, jack_irq_fall; bool change; @@ -1739,8 +1736,7 @@ static int arizona_extcon_remove(struct platform_device *pdev) ARIZONA_MICD_ENA, 0, &change); if (ret < 0) { - dev_err(&pdev->dev, "Failed to disable micd on remove: %d\n", - ret); + dev_err(arizona->dev, "Failed to disable micd on remove: %d\n", ret); } else if (change) { regulator_disable(info->micvdd); pm_runtime_put(arizona->dev); @@ -1753,22 +1749,17 @@ static int arizona_extcon_remove(struct platform_device *pdev) ARIZONA_JD1_ENA, 0); arizona_clk32k_disable(arizona); - gpiod_put(info->micd_pol_gpio); - return 0; } -static struct platform_driver arizona_extcon_driver = { - .driver = { - .name = "arizona-extcon", - }, - .probe = arizona_extcon_probe, - .remove = arizona_extcon_remove, -}; +int arizona_jack_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data) +{ + struct arizona_priv *info = snd_soc_component_get_drvdata(component); -module_platform_driver(arizona_extcon_driver); - -MODULE_DESCRIPTION("Arizona Extcon driver"); -MODULE_AUTHOR("Mark Brown "); -MODULE_LICENSE("GPL"); -MODULE_ALIAS("platform:extcon-arizona"); + if (jack) + return arizona_jack_enable_jack_detect(info, jack); + else + return arizona_jack_disable_jack_detect(info); +} +EXPORT_SYMBOL_GPL(arizona_jack_set_jack); diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index afc34e13d33c..f02012438e15 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -386,4 +386,10 @@ static inline int arizona_unregister_notifier(struct snd_soc_component *componen int arizona_of_get_audio_pdata(struct arizona *arizona); +int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev); +int arizona_jack_codec_dev_remove(struct arizona_priv *info); + +int arizona_jack_set_jack(struct snd_soc_component *component, + struct snd_soc_jack *jack, void *data); + #endif From 236b7285e95af5cb5a8b63283e573f433fb9b305 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:04 +0100 Subject: [PATCH 0375/1091] ASoC: arizona-jack: Use snd_soc_jack to report jack events Use the snd_soc_jack code to report jack events, instead of using extcon for reporting the cable-type + an input_dev for reporting the button presses. The snd_soc_jack code will report the cable-type through both input_dev events and through ALSA controls and the button-presses through input_dev events. Note that this means that when the codec drivers are moved over to use the new arizona-jack.c library code instead of having a separate MFD extcon cell with the extcon-arizona.c driver, we will no longer report extcon events to userspace for cable-type changes. This should not be a problem since "standard" Linux distro userspace does not (and has never) used the extcon class interface for this. Android does have support for the extcon class interface, but that was introduced in the same release as support for input_dev cable-type events, so this should not be a problem for Android either. Note this also reduces ARIZONA_MAX_MICD_RANGE from 8 to 6, this is ok to do since this info is always provided through pdata (or defaults) and cannot be overridden from devicetree. All in-kernel users of the pdata (and the fallback defaults) define 6 or less buttons/ranges. Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307151807.35201-11-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/arizona-jack.c | 149 +++++++++----------------------- sound/soc/codecs/arizona.h | 7 +- 2 files changed, 47 insertions(+), 109 deletions(-) diff --git a/sound/soc/codecs/arizona-jack.c b/sound/soc/codecs/arizona-jack.c index e121490eb379..268d2a44d891 100644 --- a/sound/soc/codecs/arizona-jack.c +++ b/sound/soc/codecs/arizona-jack.c @@ -16,8 +16,8 @@ #include #include #include -#include +#include #include #include @@ -29,6 +29,12 @@ #define ARIZONA_MAX_MICD_RANGE 8 +/* + * The hardware supports 8 ranges / buttons, but the snd-jack interface + * only supports 6 buttons (button 0-5). + */ +#define ARIZONA_MAX_MICD_BUTTONS 6 + #define ARIZONA_MICD_CLAMP_MODE_JDL 0x4 #define ARIZONA_MICD_CLAMP_MODE_JDH 0x5 #define ARIZONA_MICD_CLAMP_MODE_JDL_GP5H 0x9 @@ -86,14 +92,6 @@ static const int arizona_micd_levels[] = { 1257, 30000, }; -static const unsigned int arizona_cable[] = { - EXTCON_MECHANICAL, - EXTCON_JACK_MICROPHONE, - EXTCON_JACK_HEADPHONE, - EXTCON_JACK_LINE_OUT, - EXTCON_NONE, -}; - static void arizona_start_hpdet_acc_id(struct arizona_priv *info); static void arizona_extcon_hp_clamp(struct arizona_priv *info, @@ -559,8 +557,7 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) struct arizona_priv *info = data; struct arizona *arizona = info->arizona; int id_gpio = arizona->pdata.hpdet_id_gpio; - unsigned int report = EXTCON_JACK_HEADPHONE; - int ret, reading, state; + int ret, reading, state, report; bool mic = false; mutex_lock(&info->lock); @@ -573,11 +570,8 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) } /* If the cable was removed while measuring ignore the result */ - state = extcon_get_state(info->edev, EXTCON_MECHANICAL); - if (state < 0) { - dev_err(arizona->dev, "Failed to check cable state: %d\n", state); - goto out; - } else if (!state) { + state = info->jack->status & SND_JACK_MECHANICAL; + if (!state) { dev_dbg(arizona->dev, "Ignoring HPDET for removed cable\n"); goto done; } @@ -603,14 +597,11 @@ static irqreturn_t arizona_hpdet_irq(int irq, void *data) /* Report high impedence cables as line outputs */ if (reading >= 5000) - report = EXTCON_JACK_LINE_OUT; + report = SND_JACK_LINEOUT; else - report = EXTCON_JACK_HEADPHONE; + report = SND_JACK_HEADPHONE; - ret = extcon_set_state_sync(info->edev, report, true); - if (ret != 0) - dev_err(arizona->dev, "Failed to report HP/line: %d\n", - ret); + snd_soc_jack_report(info->jack, report, SND_JACK_LINEOUT | SND_JACK_HEADPHONE); done: /* Reset back to starting range */ @@ -686,9 +677,8 @@ err: pm_runtime_put_autosuspend(arizona->dev); /* Just report headphone */ - ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); - if (ret != 0) - dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); + snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE, + SND_JACK_LINEOUT | SND_JACK_HEADPHONE); if (info->mic) arizona_start_mic(info); @@ -740,9 +730,8 @@ static void arizona_start_hpdet_acc_id(struct arizona_priv *info) err: /* Just report headphone */ - ret = extcon_set_state_sync(info->edev, EXTCON_JACK_HEADPHONE, true); - if (ret != 0) - dev_err(arizona->dev, "Failed to report headphone: %d\n", ret); + snd_soc_jack_report(info->jack, SND_JACK_HEADPHONE, + SND_JACK_LINEOUT | SND_JACK_HEADPHONE); info->hpdet_active = false; } @@ -863,11 +852,7 @@ static int arizona_micdet_reading(void *priv) arizona_identify_headphone(info); - ret = extcon_set_state_sync(info->edev, - EXTCON_JACK_MICROPHONE, true); - if (ret != 0) - dev_err(arizona->dev, "Headset report failed: %d\n", - ret); + snd_soc_jack_report(info->jack, SND_JACK_MICROPHONE, SND_JACK_MICROPHONE); /* Don't need to regulate for button detection */ ret = regulator_allow_bypass(info->micvdd, true); @@ -930,7 +915,7 @@ static int arizona_button_reading(void *priv) { struct arizona_priv *info = priv; struct arizona *arizona = info->arizona; - int val, key, lvl, i; + int val, key, lvl; val = arizona_micd_read(info); if (val < 0) @@ -947,14 +932,11 @@ static int arizona_button_reading(void *priv) lvl = val & ARIZONA_MICD_LVL_MASK; lvl >>= ARIZONA_MICD_LVL_SHIFT; - for (i = 0; i < info->num_micd_ranges; i++) - input_report_key(info->input, - info->micd_ranges[i].key, 0); - if (lvl && ffs(lvl) - 1 < info->num_micd_ranges) { - key = info->micd_ranges[ffs(lvl) - 1].key; - input_report_key(info->input, key, 1); - input_sync(info->input); + key = ffs(lvl) - 1; + snd_soc_jack_report(info->jack, + SND_JACK_BTN_0 >> key, + info->micd_button_mask); } else { dev_err(arizona->dev, "Button out of range\n"); } @@ -964,10 +946,7 @@ static int arizona_button_reading(void *priv) } } else { dev_dbg(arizona->dev, "Mic button released\n"); - for (i = 0; i < info->num_micd_ranges; i++) - input_report_key(info->input, - info->micd_ranges[i].key, 0); - input_sync(info->input); + snd_soc_jack_report(info->jack, 0, info->micd_button_mask); arizona_extcon_pulse_micbias(info); } @@ -980,20 +959,13 @@ static void arizona_micd_detect(struct work_struct *work) struct arizona_priv, micd_detect_work.work); struct arizona *arizona = info->arizona; - int ret; cancel_delayed_work_sync(&info->micd_timeout_work); mutex_lock(&info->lock); /* If the cable was removed while measuring ignore the result */ - ret = extcon_get_state(info->edev, EXTCON_MECHANICAL); - if (ret < 0) { - dev_err(arizona->dev, "Failed to check cable state: %d\n", - ret); - mutex_unlock(&info->lock); - return; - } else if (!ret) { + if (!(info->jack->status & SND_JACK_MECHANICAL)) { dev_dbg(arizona->dev, "Ignoring MICDET for removed cable\n"); mutex_unlock(&info->lock); return; @@ -1134,12 +1106,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) if (info->last_jackdet == present) { dev_dbg(arizona->dev, "Detected jack\n"); - ret = extcon_set_state_sync(info->edev, - EXTCON_MECHANICAL, true); - - if (ret != 0) - dev_err(arizona->dev, "Mechanical report failed: %d\n", - ret); + snd_soc_jack_report(info->jack, SND_JACK_MECHANICAL, SND_JACK_MECHANICAL); info->detecting = true; info->mic = false; @@ -1170,18 +1137,7 @@ static irqreturn_t arizona_jackdet(int irq, void *data) info->hpdet_done = false; info->hpdet_retried = false; - for (i = 0; i < info->num_micd_ranges; i++) - input_report_key(info->input, - info->micd_ranges[i].key, 0); - input_sync(info->input); - - for (i = 0; i < ARRAY_SIZE(arizona_cable) - 1; i++) { - ret = extcon_set_state_sync(info->edev, - arizona_cable[i], false); - if (ret != 0) - dev_err(arizona->dev, - "Removal report failed: %d\n", ret); - } + snd_soc_jack_report(info->jack, 0, ARIZONA_JACK_MASK | info->micd_button_mask); /* * If the jack was removed during a headphone detection we @@ -1389,29 +1345,6 @@ int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev) break; } - info->edev = devm_extcon_dev_allocate(dev, arizona_cable); - if (IS_ERR(info->edev)) { - dev_err(arizona->dev, "failed to allocate extcon device\n"); - return -ENOMEM; - } - - ret = devm_extcon_dev_register(dev, info->edev); - if (ret < 0) { - dev_err(arizona->dev, "extcon_dev_register() failed: %d\n", - ret); - return ret; - } - - info->input = devm_input_allocate_device(dev); - if (!info->input) { - dev_err(arizona->dev, "Can't allocate input dev\n"); - ret = -ENOMEM; - return ret; - } - - info->input->name = "Headset"; - info->input->phys = "arizona/extcon"; - if (!pdata->micd_timeout) pdata->micd_timeout = DEFAULT_MICD_TIMEOUT; @@ -1535,9 +1468,9 @@ static int arizona_jack_enable_jack_detect(struct arizona_priv *info, info->num_micd_ranges = ARRAY_SIZE(micd_default_ranges); } - if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_RANGE) { - dev_err(arizona->dev, "Too many MICD ranges: %d\n", - arizona->pdata.num_micd_ranges); + if (arizona->pdata.num_micd_ranges > ARIZONA_MAX_MICD_BUTTONS) { + dev_err(arizona->dev, "Too many MICD ranges: %d > %d\n", + arizona->pdata.num_micd_ranges, ARIZONA_MAX_MICD_BUTTONS); return -EINVAL; } @@ -1571,8 +1504,11 @@ static int arizona_jack_enable_jack_detect(struct arizona_priv *info, arizona_micd_levels[j], i); arizona_micd_set_level(arizona, i, j); - input_set_capability(info->input, EV_KEY, - info->micd_ranges[i].key); + + /* SND_JACK_BTN_# masks start with the most significant bit */ + info->micd_button_mask |= SND_JACK_BTN_0 >> i; + snd_jack_set_key(jack->jack, SND_JACK_BTN_0 >> i, + info->micd_ranges[i].key); /* Enable reporting of that range */ regmap_update_bits(arizona->regmap, ARIZONA_MIC_DETECT_2, @@ -1620,6 +1556,8 @@ static int arizona_jack_enable_jack_detect(struct arizona_priv *info, arizona_extcon_set_mode(info, 0); + info->jack = jack; + pm_runtime_get_sync(arizona->dev); if (info->micd_clamp) { @@ -1680,18 +1618,10 @@ static int arizona_jack_enable_jack_detect(struct arizona_priv *info, if (ret != 0) dev_warn(arizona->dev, "Failed to set MICVDD to bypass: %d\n", ret); - ret = input_register_device(info->input); - if (ret) { - dev_err(arizona->dev, "Can't register input device: %d\n", ret); - goto err_hpdet; - } - pm_runtime_put(arizona->dev); return 0; -err_hpdet: - arizona_free_irq(arizona, ARIZONA_IRQ_HPDET, info); err_micdet: arizona_free_irq(arizona, ARIZONA_IRQ_MICDET, info); err_fall_wake: @@ -1704,6 +1634,7 @@ err_rise: arizona_free_irq(arizona, jack_irq_rise, info); err_pm: pm_runtime_put(arizona->dev); + info->jack = NULL; return ret; } @@ -1714,6 +1645,9 @@ static int arizona_jack_disable_jack_detect(struct arizona_priv *info) bool change; int ret; + if (!info->jack) + return 0; + if (info->micd_clamp) { jack_irq_rise = ARIZONA_IRQ_MICD_CLAMP_RISE; jack_irq_fall = ARIZONA_IRQ_MICD_CLAMP_FALL; @@ -1748,6 +1682,7 @@ static int arizona_jack_disable_jack_detect(struct arizona_priv *info) regmap_update_bits(arizona->regmap, ARIZONA_JACK_DETECT_ANALOGUE, ARIZONA_JD1_ENA, 0); arizona_clk32k_disable(arizona); + info->jack = NULL; return 0; } diff --git a/sound/soc/codecs/arizona.h b/sound/soc/codecs/arizona.h index f02012438e15..ecd8890eefc1 100644 --- a/sound/soc/codecs/arizona.h +++ b/sound/soc/codecs/arizona.h @@ -97,9 +97,8 @@ struct arizona_priv { struct delayed_work hpdet_work; struct delayed_work micd_detect_work; struct delayed_work micd_timeout_work; + struct snd_soc_jack *jack; struct regulator *micvdd; - struct input_dev *input; - struct extcon_dev *edev; struct gpio_desc *micd_pol_gpio; u16 last_jackdet; @@ -108,6 +107,7 @@ struct arizona_priv { const struct arizona_micd_config *micd_modes; int micd_num_modes; + int micd_button_mask; const struct arizona_micd_range *micd_ranges; int num_micd_ranges; @@ -257,6 +257,9 @@ extern unsigned int arizona_mixer_values[ARIZONA_NUM_MIXER_INPUTS]; #define ARIZONA_RATE_ENUM_SIZE 4 #define ARIZONA_SAMPLE_RATE_ENUM_SIZE 14 +/* SND_JACK_* mask for supported cable/switch types */ +#define ARIZONA_JACK_MASK (SND_JACK_HEADSET | SND_JACK_LINEOUT | SND_JACK_MECHANICAL) + extern const char * const arizona_rate_text[ARIZONA_RATE_ENUM_SIZE]; extern const unsigned int arizona_rate_val[ARIZONA_RATE_ENUM_SIZE]; extern const char * const arizona_sample_rate_text[ARIZONA_SAMPLE_RATE_ENUM_SIZE]; From 69c58eb61e9b649096a0ab8cbc3c6f8521efd303 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:05 +0100 Subject: [PATCH 0376/1091] ASoC: arizona-jack: Cleanup logging Cleanup the use of dev_foo functions used for logging: 1. Many of these are unnecessarily split over multiple lines 2. Use dev_err_probe() in cases where we might get a -EPROBE_DEFER return value Suggested-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307151807.35201-12-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/arizona-jack.c | 145 +++++++++++--------------------- 1 file changed, 51 insertions(+), 94 deletions(-) diff --git a/sound/soc/codecs/arizona-jack.c b/sound/soc/codecs/arizona-jack.c index 268d2a44d891..9c15ddba6008 100644 --- a/sound/soc/codecs/arizona-jack.c +++ b/sound/soc/codecs/arizona-jack.c @@ -123,9 +123,8 @@ static void arizona_extcon_hp_clamp(struct arizona_priv *info, ARIZONA_HP_TEST_CTRL_1, ARIZONA_HP1_TST_CAP_SEL_MASK, cap_sel); - if (ret != 0) - dev_warn(arizona->dev, - "Failed to set TST_CAP_SEL: %d\n", ret); + if (ret) + dev_warn(arizona->dev, "Failed to set TST_CAP_SEL: %d\n", ret); break; default: mask = ARIZONA_RMV_SHRT_HP1L; @@ -144,24 +143,20 @@ static void arizona_extcon_hp_clamp(struct arizona_priv *info, ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA, 0); - if (ret != 0) - dev_warn(arizona->dev, - "Failed to disable headphone outputs: %d\n", - ret); + if (ret) + dev_warn(arizona->dev, "Failed to disable headphone outputs: %d\n", ret); } if (mask) { ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1L, mask, val); - if (ret != 0) - dev_warn(arizona->dev, "Failed to do clamp: %d\n", - ret); + if (ret) + dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret); ret = regmap_update_bits(arizona->regmap, ARIZONA_HP_CTRL_1R, mask, val); - if (ret != 0) - dev_warn(arizona->dev, "Failed to do clamp: %d\n", - ret); + if (ret) + dev_warn(arizona->dev, "Failed to do clamp: %d\n", ret); } /* Restore the desired state while not doing the clamp */ @@ -170,10 +165,8 @@ static void arizona_extcon_hp_clamp(struct arizona_priv *info, ARIZONA_OUTPUT_ENABLES_1, ARIZONA_OUT1L_ENA | ARIZONA_OUT1R_ENA, arizona->hp_ena); - if (ret != 0) - dev_warn(arizona->dev, - "Failed to restore headphone outputs: %d\n", - ret); + if (ret) + dev_warn(arizona->dev, "Failed to restore headphone outputs: %d\n", ret); } snd_soc_dapm_mutex_unlock(arizona->dapm); @@ -223,17 +216,15 @@ static void arizona_extcon_pulse_micbias(struct arizona_priv *info) int ret; ret = snd_soc_component_force_enable_pin(component, widget); - if (ret != 0) - dev_warn(arizona->dev, "Failed to enable %s: %d\n", - widget, ret); + if (ret) + dev_warn(arizona->dev, "Failed to enable %s: %d\n", widget, ret); snd_soc_dapm_sync(dapm); if (!arizona->pdata.micd_force_micbias) { ret = snd_soc_component_disable_pin(component, widget); - if (ret != 0) - dev_warn(arizona->dev, "Failed to disable %s: %d\n", - widget, ret); + if (ret) + dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret); snd_soc_dapm_sync(dapm); } @@ -251,18 +242,13 @@ static void arizona_start_mic(struct arizona_priv *info) if (info->detecting) { ret = regulator_allow_bypass(info->micvdd, false); - if (ret != 0) { - dev_err(arizona->dev, - "Failed to regulate MICVDD: %d\n", - ret); - } + if (ret) + dev_err(arizona->dev, "Failed to regulate MICVDD: %d\n", ret); } ret = regulator_enable(info->micvdd); - if (ret != 0) { - dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", - ret); - } + if (ret) + dev_err(arizona->dev, "Failed to enable MICVDD: %d\n", ret); if (info->micd_reva) { const struct reg_sequence reva[] = { @@ -312,10 +298,8 @@ static void arizona_stop_mic(struct arizona_priv *info) dev_err(arizona->dev, "Failed to disable micd: %d\n", ret); ret = snd_soc_component_disable_pin(component, widget); - if (ret != 0) - dev_warn(arizona->dev, - "Failed to disable %s: %d\n", - widget, ret); + if (ret) + dev_warn(arizona->dev, "Failed to disable %s: %d\n", widget, ret); snd_soc_dapm_sync(dapm); @@ -330,10 +314,8 @@ static void arizona_stop_mic(struct arizona_priv *info) } ret = regulator_allow_bypass(info->micvdd, true); - if (ret != 0) { - dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", - ret); - } + if (ret) + dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret); if (change) { regulator_disable(info->micvdd); @@ -371,17 +353,15 @@ static int arizona_hpdet_read(struct arizona_priv *info) int ret; ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val); - if (ret != 0) { - dev_err(arizona->dev, "Failed to read HPDET status: %d\n", - ret); + if (ret) { + dev_err(arizona->dev, "Failed to read HPDET status: %d\n", ret); return ret; } switch (info->hpdet_ip_version) { case 0: if (!(val & ARIZONA_HP_DONE)) { - dev_err(arizona->dev, "HPDET did not complete: %x\n", - val); + dev_err(arizona->dev, "HPDET did not complete: %x\n", val); return -EAGAIN; } @@ -390,15 +370,13 @@ static int arizona_hpdet_read(struct arizona_priv *info) case 1: if (!(val & ARIZONA_HP_DONE_B)) { - dev_err(arizona->dev, "HPDET did not complete: %x\n", - val); + dev_err(arizona->dev, "HPDET did not complete: %x\n", val); return -EAGAIN; } ret = regmap_read(arizona->regmap, ARIZONA_HP_DACVAL, &val); - if (ret != 0) { - dev_err(arizona->dev, "Failed to read HP value: %d\n", - ret); + if (ret) { + dev_err(arizona->dev, "Failed to read HP value: %d\n", ret); return -EAGAIN; } @@ -411,8 +389,7 @@ static int arizona_hpdet_read(struct arizona_priv *info) (val < arizona_hpdet_b_ranges[range].threshold || val >= ARIZONA_HPDET_B_RANGE_MAX)) { range++; - dev_dbg(arizona->dev, "Moving to HPDET range %d\n", - range); + dev_dbg(arizona->dev, "Moving to HPDET range %d\n", range); regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, ARIZONA_HP_IMPEDANCE_RANGE_MASK, @@ -428,8 +405,7 @@ static int arizona_hpdet_read(struct arizona_priv *info) return ARIZONA_HPDET_MAX; } - dev_dbg(arizona->dev, "HPDET read %d in range %d\n", - val, range); + dev_dbg(arizona->dev, "HPDET read %d in range %d\n", val, range); val = arizona_hpdet_b_ranges[range].factor_b / ((val * 100) - @@ -438,8 +414,7 @@ static int arizona_hpdet_read(struct arizona_priv *info) case 2: if (!(val & ARIZONA_HP_DONE_B)) { - dev_err(arizona->dev, "HPDET did not complete: %x\n", - val); + dev_err(arizona->dev, "HPDET did not complete: %x\n", val); return -EAGAIN; } @@ -475,8 +450,7 @@ static int arizona_hpdet_read(struct arizona_priv *info) break; default: - dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", - info->hpdet_ip_version); + dev_warn(arizona->dev, "Unknown HPDET IP revision %d\n", info->hpdet_ip_version); return -EINVAL; } @@ -664,9 +638,8 @@ static void arizona_identify_headphone(struct arizona_priv *info) ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, ARIZONA_HP_POLL, ARIZONA_HP_POLL); - if (ret != 0) { - dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", - ret); + if (ret) { + dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret); goto err; } @@ -716,10 +689,8 @@ static void arizona_start_hpdet_acc_id(struct arizona_priv *info) ret = regmap_update_bits(arizona->regmap, ARIZONA_HEADPHONE_DETECT_1, ARIZONA_HP_POLL, ARIZONA_HP_POLL); - if (ret != 0) { - dev_err(arizona->dev, - "Can't start HPDETL measurement: %d\n", - ret); + if (ret) { + dev_err(arizona->dev, "Can't start HPDETL measurement: %d\n", ret); goto err; } } else { @@ -764,9 +735,8 @@ static int arizona_micd_adc_read(struct arizona_priv *info) ARIZONA_MICD_ENA, 0); ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_4, &val); - if (ret != 0) { - dev_err(arizona->dev, - "Failed to read MICDET_ADCVAL: %d\n", ret); + if (ret) { + dev_err(arizona->dev, "Failed to read MICDET_ADCVAL: %d\n", ret); return ret; } @@ -798,17 +768,15 @@ static int arizona_micd_read(struct arizona_priv *info) for (i = 0; i < 10 && !(val & MICD_LVL_0_TO_8); i++) { ret = regmap_read(arizona->regmap, ARIZONA_MIC_DETECT_3, &val); - if (ret != 0) { - dev_err(arizona->dev, - "Failed to read MICDET: %d\n", ret); + if (ret) { + dev_err(arizona->dev, "Failed to read MICDET: %d\n", ret); return ret; } dev_dbg(arizona->dev, "MICDET: %x\n", val); if (!(val & ARIZONA_MICD_VALID)) { - dev_warn(arizona->dev, - "Microphone detection state invalid\n"); + dev_warn(arizona->dev, "Microphone detection state invalid\n"); return -EINVAL; } } @@ -856,10 +824,8 @@ static int arizona_micdet_reading(void *priv) /* Don't need to regulate for button detection */ ret = regulator_allow_bypass(info->micvdd, true); - if (ret != 0) { - dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", - ret); - } + if (ret) + dev_err(arizona->dev, "Failed to bypass MICVDD: %d\n", ret); return 0; } @@ -941,8 +907,7 @@ static int arizona_button_reading(void *priv) dev_err(arizona->dev, "Button out of range\n"); } } else { - dev_warn(arizona->dev, "Button with no mic: %x\n", - val); + dev_warn(arizona->dev, "Button with no mic: %x\n", val); } } else { dev_dbg(arizona->dev, "Mic button released\n"); @@ -1025,8 +990,7 @@ static int arizona_hpdet_wait(struct arizona_priv *info) ret = regmap_read(arizona->regmap, ARIZONA_HEADPHONE_DETECT_2, &val); if (ret) { - dev_err(arizona->dev, - "Failed to read HPDET state: %d\n", ret); + dev_err(arizona->dev, "Failed to read HPDET state: %d\n", ret); return ret; } @@ -1076,9 +1040,8 @@ static irqreturn_t arizona_jackdet(int irq, void *data) } ret = regmap_read(arizona->regmap, ARIZONA_AOD_IRQ_RAW_STATUS, &val); - if (ret != 0) { - dev_err(arizona->dev, "Failed to read jackdet status: %d\n", - ret); + if (ret) { + dev_err(arizona->dev, "Failed to read jackdet status: %d\n", ret); mutex_unlock(&info->lock); pm_runtime_put_autosuspend(arizona->dev); return IRQ_NONE; @@ -1248,8 +1211,7 @@ static int arizona_extcon_device_get_pdata(struct device *dev, pdata->hpdet_channel = val; break; default: - dev_err(arizona->dev, - "Wrong wlf,hpdet-channel DT value %d\n", val); + dev_err(arizona->dev, "Wrong wlf,hpdet-channel DT value %d\n", val); pdata->hpdet_channel = ARIZONA_ACCDET_MODE_HPL; } @@ -1301,11 +1263,8 @@ int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev) arizona_extcon_device_get_pdata(dev, arizona); info->micvdd = devm_regulator_get(dev, "MICVDD"); - if (IS_ERR(info->micvdd)) { - ret = PTR_ERR(info->micvdd); - dev_err(arizona->dev, "Failed to get MICVDD: %d\n", ret); - return ret; - } + if (IS_ERR(info->micvdd)) + return dev_err_probe(arizona->dev, PTR_ERR(info->micvdd), "getting MICVDD\n"); mutex_init(&info->lock); info->last_jackdet = ~(ARIZONA_MICD_CLAMP_STS | ARIZONA_JD1_STS); @@ -1391,9 +1350,7 @@ int arizona_jack_codec_dev_probe(struct arizona_priv *info, struct device *dev) mode); if (IS_ERR(info->micd_pol_gpio)) { ret = PTR_ERR(info->micd_pol_gpio); - dev_err(arizona->dev, - "Failed to get microphone polarity GPIO: %d\n", - ret); + dev_err_probe(arizona->dev, ret, "getting microphone polarity GPIO\n"); return ret; } } From 37dbabf14ff65510fa5aeecc1707ca390e608e00 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:06 +0100 Subject: [PATCH 0377/1091] ASoC: arizona: Make the wm5102, wm5110, wm8997 and wm8998 drivers use the new jack library Make all arizona codec drivers for which drivers/mfd/arizona-core.c used to instantiate a "arizona-extcon" child-device use the new arizona-jack.c library for jack-detection. This has been tested on a Lenovo Yoga Tablet 2 1051L with a WM5102 codec. Reviewed-by: Andy Shevchenko Acked-by: Charles Keepax Tested-by: Charles Keepax Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307151807.35201-13-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm5102.c | 12 +++++++++++- sound/soc/codecs/wm5110.c | 12 +++++++++++- sound/soc/codecs/wm8997.c | 14 ++++++++++++-- sound/soc/codecs/wm8998.c | 9 +++++++++ 4 files changed, 43 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/wm5102.c b/sound/soc/codecs/wm5102.c index fe33f2d88f55..34b665895bdf 100644 --- a/sound/soc/codecs/wm5102.c +++ b/sound/soc/codecs/wm5102.c @@ -2004,6 +2004,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm5102 = { .remove = wm5102_component_remove, .set_sysclk = arizona_set_sysclk, .set_pll = wm5102_set_fll, + .set_jack = arizona_jack_set_jack, .name = DRV_NAME, .compress_ops = &wm5102_compress_ops, .controls = wm5102_snd_controls, @@ -2057,6 +2058,11 @@ static int wm5102_probe(struct platform_device *pdev) if (ret != 0) return ret; + /* This may return -EPROBE_DEFER, so do this early on */ + ret = arizona_jack_codec_dev_probe(&wm5102->core, &pdev->dev); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(wm5102->fll); i++) wm5102->fll[i].vco_mult = 1; @@ -2089,7 +2095,7 @@ static int wm5102_probe(struct platform_device *pdev) wm5102); if (ret != 0) { dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); - return ret; + goto err_jack_codec_dev; } ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1); @@ -2123,6 +2129,8 @@ err_spk_irqs: err_dsp_irq: arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); +err_jack_codec_dev: + arizona_jack_codec_dev_remove(&wm5102->core); return ret; } @@ -2141,6 +2149,8 @@ static int wm5102_remove(struct platform_device *pdev) arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5102); + arizona_jack_codec_dev_remove(&wm5102->core); + return 0; } diff --git a/sound/soc/codecs/wm5110.c b/sound/soc/codecs/wm5110.c index 52c0a575cc4f..76efca0fe515 100644 --- a/sound/soc/codecs/wm5110.c +++ b/sound/soc/codecs/wm5110.c @@ -2370,6 +2370,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm5110 = { .remove = wm5110_component_remove, .set_sysclk = arizona_set_sysclk, .set_pll = wm5110_set_fll, + .set_jack = arizona_jack_set_jack, .name = DRV_NAME, .compress_ops = &wm5110_compress_ops, .controls = wm5110_snd_controls, @@ -2424,6 +2425,11 @@ static int wm5110_probe(struct platform_device *pdev) return ret; } + /* This may return -EPROBE_DEFER, so do this early on */ + ret = arizona_jack_codec_dev_probe(&wm5110->core, &pdev->dev); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(wm5110->fll); i++) wm5110->fll[i].vco_mult = 3; @@ -2456,7 +2462,7 @@ static int wm5110_probe(struct platform_device *pdev) wm5110); if (ret != 0) { dev_err(&pdev->dev, "Failed to request DSP IRQ: %d\n", ret); - return ret; + goto err_jack_codec_dev; } ret = arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 1); @@ -2490,6 +2496,8 @@ err_spk_irqs: err_dsp_irq: arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110); +err_jack_codec_dev: + arizona_jack_codec_dev_remove(&wm5110->core); return ret; } @@ -2510,6 +2518,8 @@ static int wm5110_remove(struct platform_device *pdev) arizona_set_irq_wake(arizona, ARIZONA_IRQ_DSP_IRQ1, 0); arizona_free_irq(arizona, ARIZONA_IRQ_DSP_IRQ1, wm5110); + arizona_jack_codec_dev_remove(&wm5110->core); + return 0; } diff --git a/sound/soc/codecs/wm8997.c b/sound/soc/codecs/wm8997.c index 99c3ebae6ba6..38ef631d1a1f 100644 --- a/sound/soc/codecs/wm8997.c +++ b/sound/soc/codecs/wm8997.c @@ -1096,6 +1096,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm8997 = { .remove = wm8997_component_remove, .set_sysclk = arizona_set_sysclk, .set_pll = wm8997_set_fll, + .set_jack = arizona_jack_set_jack, .controls = wm8997_snd_controls, .num_controls = ARRAY_SIZE(wm8997_snd_controls), .dapm_widgets = wm8997_dapm_widgets, @@ -1132,6 +1133,11 @@ static int wm8997_probe(struct platform_device *pdev) arizona_init_dvfs(&wm8997->core); + /* This may return -EPROBE_DEFER, so do this early on */ + ret = arizona_jack_codec_dev_probe(&wm8997->core, &pdev->dev); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(wm8997->fll); i++) wm8997->fll[i].vco_mult = 1; @@ -1163,10 +1169,10 @@ static int wm8997_probe(struct platform_device *pdev) ret = arizona_init_vol_limit(arizona); if (ret < 0) - return ret; + goto err_jack_codec_dev; ret = arizona_init_spk_irqs(arizona); if (ret < 0) - return ret; + goto err_jack_codec_dev; ret = devm_snd_soc_register_component(&pdev->dev, &soc_component_dev_wm8997, @@ -1181,6 +1187,8 @@ static int wm8997_probe(struct platform_device *pdev) err_spk_irqs: arizona_free_spk_irqs(arizona); +err_jack_codec_dev: + arizona_jack_codec_dev_remove(&wm8997->core); return ret; } @@ -1194,6 +1202,8 @@ static int wm8997_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); + arizona_jack_codec_dev_remove(&wm8997->core); + return 0; } diff --git a/sound/soc/codecs/wm8998.c b/sound/soc/codecs/wm8998.c index b6f717aa5478..00b59fc9b1fe 100644 --- a/sound/soc/codecs/wm8998.c +++ b/sound/soc/codecs/wm8998.c @@ -1316,6 +1316,7 @@ static const struct snd_soc_component_driver soc_component_dev_wm8998 = { .remove = wm8998_component_remove, .set_sysclk = arizona_set_sysclk, .set_pll = wm8998_set_fll, + .set_jack = arizona_jack_set_jack, .controls = wm8998_snd_controls, .num_controls = ARRAY_SIZE(wm8998_snd_controls), .dapm_widgets = wm8998_dapm_widgets, @@ -1350,6 +1351,11 @@ static int wm8998_probe(struct platform_device *pdev) wm8998->core.arizona = arizona; wm8998->core.num_inputs = 3; /* IN1L, IN1R, IN2 */ + /* This may return -EPROBE_DEFER, so do this early on */ + ret = arizona_jack_codec_dev_probe(&wm8998->core, &pdev->dev); + if (ret) + return ret; + for (i = 0; i < ARRAY_SIZE(wm8998->fll); i++) wm8998->fll[i].vco_mult = 1; @@ -1392,6 +1398,7 @@ err_spk_irqs: arizona_free_spk_irqs(arizona); err_pm_disable: pm_runtime_disable(&pdev->dev); + arizona_jack_codec_dev_remove(&wm8998->core); return ret; } @@ -1405,6 +1412,8 @@ static int wm8998_remove(struct platform_device *pdev) arizona_free_spk_irqs(arizona); + arizona_jack_codec_dev_remove(&wm8998->core); + return 0; } From ecd77d494ec995fb07102b408954c94f38374084 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 7 Mar 2021 16:18:07 +0100 Subject: [PATCH 0378/1091] ASoC: Intel: bytcr_wm5102: Add jack detect support Add jack detect support by creating a jack and calling snd_soc_component_set_jack to register the created jack with the codec. Reviewed-by: Andy Shevchenko Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210307151807.35201-14-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_wm5102.c | 28 ++++++++++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/sound/soc/intel/boards/bytcr_wm5102.c b/sound/soc/intel/boards/bytcr_wm5102.c index fd584e380340..8d8ab9be256f 100644 --- a/sound/soc/intel/boards/bytcr_wm5102.c +++ b/sound/soc/intel/boards/bytcr_wm5102.c @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -31,6 +32,7 @@ #define WM5102_MAX_SYSCLK_11025 45158400 /* max sysclk for 11.025K family */ struct byt_wm5102_private { + struct snd_soc_jack jack; struct clk *mclk; struct gpio_desc *spkvdd_en_gpio; }; @@ -177,11 +179,23 @@ static const struct snd_kcontrol_new byt_wm5102_controls[] = { SOC_DAPM_PIN_SWITCH("Speaker"), }; +static struct snd_soc_jack_pin byt_wm5102_pins[] = { + { + .pin = "Headphone", + .mask = SND_JACK_HEADPHONE, + }, + { + .pin = "Headset Mic", + .mask = SND_JACK_MICROPHONE, + }, +}; + static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) { struct snd_soc_card *card = runtime->card; struct byt_wm5102_private *priv = snd_soc_card_get_drvdata(card); - int ret; + struct snd_soc_component *component = asoc_rtd_to_codec(runtime, 0)->component; + int ret, jack_type; card->dapm.idle_bias_off = true; @@ -210,6 +224,18 @@ static int byt_wm5102_init(struct snd_soc_pcm_runtime *runtime) return ret; } + jack_type = ARIZONA_JACK_MASK | SND_JACK_BTN_0 | SND_JACK_BTN_1 | + SND_JACK_BTN_2 | SND_JACK_BTN_3; + ret = snd_soc_card_jack_new(card, "Headset", jack_type, + &priv->jack, byt_wm5102_pins, + ARRAY_SIZE(byt_wm5102_pins)); + if (ret) { + dev_err(card->dev, "Error creating jack: %d\n", ret); + return ret; + } + + snd_soc_component_set_jack(component, &priv->jack, NULL); + return 0; } From 69c3ed7282a143439bbc2d03dc00d49c68fcb629 Mon Sep 17 00:00:00 2001 From: Pan Bian Date: Wed, 20 Jan 2021 01:16:08 -0800 Subject: [PATCH 0379/1091] drm/imx: fix memory leak when fails to init Put DRM device on initialization failure path rather than directly return error code. Fixes: a67d5088ceb8 ("drm/imx: drop explicit drm_mode_config_cleanup") Signed-off-by: Pan Bian Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-drm-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/imx-drm-core.c b/drivers/gpu/drm/imx/imx-drm-core.c index d1a9841adeed..e6a88c8cbd69 100644 --- a/drivers/gpu/drm/imx/imx-drm-core.c +++ b/drivers/gpu/drm/imx/imx-drm-core.c @@ -215,7 +215,7 @@ static int imx_drm_bind(struct device *dev) ret = drmm_mode_config_init(drm); if (ret) - return ret; + goto err_kms; ret = drm_vblank_init(drm, MAX_CRTC); if (ret) From 12d0ca80bffdad9e9b2a7a68784bfca54c8cf1a1 Mon Sep 17 00:00:00 2001 From: Liu Ying Date: Mon, 22 Mar 2021 10:56:40 +0800 Subject: [PATCH 0380/1091] drm/imx: imx-ldb: Register LDB channel1 when it is the only channel to be used LDB channel1 should be registered if it is the only channel to be used. Without this patch, imx_ldb_bind() would skip registering LDB channel1 if LDB channel0 is not used, no matter LDB channel1 needs to be used or not. Fixes: 8767f4711b2b (drm/imx: imx-ldb: move initialization into probe) Signed-off-by: Liu Ying Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-ldb.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index dbfe39e2f7f6..b794ed448ea3 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -583,7 +583,7 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data) struct imx_ldb_channel *channel = &imx_ldb->channel[i]; if (!channel->ldb) - break; + continue; ret = imx_ldb_register(drm, channel); if (ret) From 33ce7f2f95cabb5834cf0906308a5cb6103976da Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Wed, 24 Mar 2021 17:47:41 +0100 Subject: [PATCH 0381/1091] drm/imx: imx-ldb: fix out of bounds array access warning When CONFIG_OF is disabled, building with 'make W=1' produces warnings about out of bounds array access: drivers/gpu/drm/imx/imx-ldb.c: In function 'imx_ldb_set_clock.constprop': drivers/gpu/drm/imx/imx-ldb.c:186:8: error: array subscript -22 is below array bounds of 'struct clk *[4]' [-Werror=array-bounds] Add an error check before the index is used, which helps with the warning, as well as any possible other error condition that may be triggered at runtime. The warning could be fixed by adding a Kconfig depedency on CONFIG_OF, but Liu Ying points out that the driver may hit the out-of-bounds problem at runtime anyway. Signed-off-by: Arnd Bergmann Reviewed-by: Liu Ying Signed-off-by: Philipp Zabel --- drivers/gpu/drm/imx/imx-ldb.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/drivers/gpu/drm/imx/imx-ldb.c b/drivers/gpu/drm/imx/imx-ldb.c index b794ed448ea3..ffdc492c5bc5 100644 --- a/drivers/gpu/drm/imx/imx-ldb.c +++ b/drivers/gpu/drm/imx/imx-ldb.c @@ -197,6 +197,11 @@ static void imx_ldb_encoder_enable(struct drm_encoder *encoder) int dual = ldb->ldb_ctrl & LDB_SPLIT_MODE_EN; int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder); + if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { + dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); + return; + } + drm_panel_prepare(imx_ldb_ch->panel); if (dual) { @@ -255,6 +260,11 @@ imx_ldb_encoder_atomic_mode_set(struct drm_encoder *encoder, int mux = drm_of_encoder_active_port_id(imx_ldb_ch->child, encoder); u32 bus_format = imx_ldb_ch->bus_format; + if (mux < 0 || mux >= ARRAY_SIZE(ldb->clk_sel)) { + dev_warn(ldb->dev, "%s: invalid mux %d\n", __func__, mux); + return; + } + if (mode->clock > 170000) { dev_warn(ldb->dev, "%s: mode exceeds 170 MHz pixel clock\n", __func__); From 58b5ada8c465b5f1300bc021ebd3d3b8149124b4 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 14:17:13 +0100 Subject: [PATCH 0382/1091] pinctrl: qcom: fix unintentional string concatenation clang is clearly correct to point out a typo in a silly array of strings: drivers/pinctrl/qcom/pinctrl-sdx55.c:426:61: error: suspicious concatenation of string literals in an array initialization; did you mean to separate the elements with a comma? [-Werror,-Wstring-concatenation] "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19" "gpio20", "gpio21", "gpio22", ^ Add the missing comma that must have accidentally been removed. Fixes: ac43c44a7a37 ("pinctrl: qcom: Add SDX55 pincontrol driver") Signed-off-by: Arnd Bergmann Reviewed-by: Bjorn Andersson Reviewed-by: Nathan Chancellor Link: https://lore.kernel.org/r/20210323131728.2702789-1-arnd@kernel.org Signed-off-by: Linus Walleij --- drivers/pinctrl/qcom/pinctrl-sdx55.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/pinctrl/qcom/pinctrl-sdx55.c b/drivers/pinctrl/qcom/pinctrl-sdx55.c index 2b5b0e2b03ad..5aaf57b40407 100644 --- a/drivers/pinctrl/qcom/pinctrl-sdx55.c +++ b/drivers/pinctrl/qcom/pinctrl-sdx55.c @@ -423,7 +423,7 @@ static const char * const gpio_groups[] = { static const char * const qdss_stm_groups[] = { "gpio0", "gpio1", "gpio2", "gpio3", "gpio4", "gpio5", "gpio6", "gpio7", "gpio12", "gpio13", - "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19" "gpio20", "gpio21", "gpio22", + "gpio14", "gpio15", "gpio16", "gpio17", "gpio18", "gpio19", "gpio20", "gpio21", "gpio22", "gpio23", "gpio44", "gpio45", "gpio52", "gpio53", "gpio56", "gpio57", "gpio61", "gpio62", "gpio63", "gpio64", "gpio65", "gpio66", }; From d624833f5984d484c5e3196f34b926f9e71dafee Mon Sep 17 00:00:00 2001 From: Ard Biesheuvel Date: Wed, 17 Feb 2021 20:26:23 +0100 Subject: [PATCH 0383/1091] ARM: 9063/1: mm: reduce maximum number of CPUs if DEBUG_KMAP_LOCAL is enabled The debugging code for kmap_local() doubles the number of per-CPU fixmap slots allocated for kmap_local(), in order to use half of them as guard regions. This causes the fixmap region to grow downwards beyond the start of its reserved window if the supported number of CPUs is large, and collide with the newly added virtual DT mapping right below it, which is obviously not good. One manifestation of this is EFI boot on a kernel built with NR_CPUS=32 and CONFIG_DEBUG_KMAP_LOCAL=y, which may pass the FDT in highmem, resulting in block entries below the fixmap region that the fixmap code misidentifies as fixmap table entries, and subsequently tries to dereference using a phys-to-virt translation that is only valid for lowmem. This results in a cryptic splat such as the one below. ftrace: allocating 45548 entries in 89 pages 8<--- cut here --- Unable to handle kernel paging request at virtual address fc6006f0 pgd = (ptrval) [fc6006f0] *pgd=80000040207003, *pmd=00000000 Internal error: Oops: a06 [#1] SMP ARM Modules linked in: CPU: 0 PID: 0 Comm: swapper Not tainted 5.11.0+ #382 Hardware name: Generic DT based system PC is at cpu_ca15_set_pte_ext+0x24/0x30 LR is at __set_fixmap+0xe4/0x118 pc : [] lr : [] psr: 400000d3 sp : c1601ed8 ip : 00400000 fp : 00800000 r10: 0000071f r9 : 00421000 r8 : 00c00000 r7 : 00c00000 r6 : 0000071f r5 : ffade000 r4 : 4040171f r3 : 00c00000 r2 : 4040171f r1 : c041ac78 r0 : fc6006f0 Flags: nZcv IRQs off FIQs off Mode SVC_32 ISA ARM Segment none Control: 30c5387d Table: 40203000 DAC: 00000001 Process swapper (pid: 0, stack limit = 0x(ptrval)) So let's limit CONFIG_NR_CPUS to 16 when CONFIG_DEBUG_KMAP_LOCAL=y. Also, fix the BUILD_BUG_ON() check that was supposed to catch this, by checking whether the region grows below the start address rather than above the end address. Fixes: 2a15ba82fa6ca3f3 ("ARM: highmem: Switch to generic kmap atomic") Reported-by: Peter Robinson Tested-by: Peter Robinson Signed-off-by: Ard Biesheuvel Acked-by: Thomas Gleixner Reviewed-by: Linus Walleij Signed-off-by: Russell King --- arch/arm/Kconfig | 8 +++++++- arch/arm/mm/mmu.c | 3 +-- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig index 853aab5ab327..becc6d684051 100644 --- a/arch/arm/Kconfig +++ b/arch/arm/Kconfig @@ -1292,9 +1292,15 @@ config KASAN_SHADOW_OFFSET config NR_CPUS int "Maximum number of CPUs (2-32)" - range 2 32 + range 2 16 if DEBUG_KMAP_LOCAL + range 2 32 if !DEBUG_KMAP_LOCAL depends on SMP default "4" + help + The maximum number of CPUs that the kernel can support. + Up to 32 CPUs can be supported, or up to 16 if kmap_local() + debugging is enabled, which uses half of the per-CPU fixmap + slots as guard regions. config HOTPLUG_CPU bool "Support for hot-pluggable CPUs" diff --git a/arch/arm/mm/mmu.c b/arch/arm/mm/mmu.c index a25b660c3017..c1e12aab67b8 100644 --- a/arch/arm/mm/mmu.c +++ b/arch/arm/mm/mmu.c @@ -387,8 +387,7 @@ void __set_fixmap(enum fixed_addresses idx, phys_addr_t phys, pgprot_t prot) pte_t *pte = pte_offset_fixmap(pmd_off_k(vaddr), vaddr); /* Make sure fixmap region does not exceed available allocation. */ - BUILD_BUG_ON(FIXADDR_START + (__end_of_fixed_addresses * PAGE_SIZE) > - FIXADDR_END); + BUILD_BUG_ON(__fix_to_virt(__end_of_fixed_addresses) < FIXADDR_START); BUG_ON(idx >= __end_of_fixed_addresses); /* we only support device mappings until pgprot_kernel has been set */ From 45c2f70cba3a7eff34574103b2e2b901a5f771aa Mon Sep 17 00:00:00 2001 From: Vladimir Murzin Date: Thu, 11 Mar 2021 13:32:16 +0100 Subject: [PATCH 0384/1091] ARM: 9069/1: NOMMU: Fix conversion for_each_membock() to for_each_mem_range() for_each_mem_range() uses a loop variable, yet looking into code it is not just iteration counter but more complex entity which encodes information about memblock. Thus condition i == 0 looks fragile. Indeed, it broke boot of R-class platforms since it never took i == 0 path (due to i was set to 1). Fix that with restoring original flag check. Fixes: b10d6bca8720 ("arch, drivers: replace for_each_membock() with for_each_mem_range()") Signed-off-by: Vladimir Murzin Acked-by: Mike Rapoport Signed-off-by: Russell King --- arch/arm/mm/pmsa-v7.c | 4 +++- arch/arm/mm/pmsa-v8.c | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mm/pmsa-v7.c b/arch/arm/mm/pmsa-v7.c index 88950e41a3a9..59d916ccdf25 100644 --- a/arch/arm/mm/pmsa-v7.c +++ b/arch/arm/mm/pmsa-v7.c @@ -235,6 +235,7 @@ void __init pmsav7_adjust_lowmem_bounds(void) phys_addr_t mem_end; phys_addr_t reg_start, reg_end; unsigned int mem_max_regions; + bool first = true; int num; u64 i; @@ -263,7 +264,7 @@ void __init pmsav7_adjust_lowmem_bounds(void) #endif for_each_mem_range(i, ®_start, ®_end) { - if (i == 0) { + if (first) { phys_addr_t phys_offset = PHYS_OFFSET; /* @@ -275,6 +276,7 @@ void __init pmsav7_adjust_lowmem_bounds(void) mem_start = reg_start; mem_end = reg_end; specified_mem_size = mem_end - mem_start; + first = false; } else { /* * memblock auto merges contiguous blocks, remove diff --git a/arch/arm/mm/pmsa-v8.c b/arch/arm/mm/pmsa-v8.c index 2de019f7503e..8359748a19a1 100644 --- a/arch/arm/mm/pmsa-v8.c +++ b/arch/arm/mm/pmsa-v8.c @@ -95,10 +95,11 @@ void __init pmsav8_adjust_lowmem_bounds(void) { phys_addr_t mem_end; phys_addr_t reg_start, reg_end; + bool first = true; u64 i; for_each_mem_range(i, ®_start, ®_end) { - if (i == 0) { + if (first) { phys_addr_t phys_offset = PHYS_OFFSET; /* @@ -107,6 +108,7 @@ void __init pmsav8_adjust_lowmem_bounds(void) if (reg_start != phys_offset) panic("First memory bank must be contiguous from PHYS_OFFSET"); mem_end = reg_end; + first = false; } else { /* * memblock auto merges contiguous blocks, remove From 30e3b4f256b4e366a61658c294f6a21b8626dda7 Mon Sep 17 00:00:00 2001 From: Russell King Date: Thu, 25 Mar 2021 10:26:21 +0000 Subject: [PATCH 0385/1091] ARM: footbridge: fix PCI interrupt mapping Since commit 30fdfb929e82 ("PCI: Add a call to pci_assign_irq() in pci_device_probe()"), the PCI code will call the IRQ mapping function whenever a PCI driver is probed. If these are marked as __init, this causes an oops if a PCI driver is loaded or bound after the kernel has initialised. Fixes: 30fdfb929e82 ("PCI: Add a call to pci_assign_irq() in pci_device_probe()") Signed-off-by: Russell King --- arch/arm/mach-footbridge/cats-pci.c | 4 ++-- arch/arm/mach-footbridge/ebsa285-pci.c | 4 ++-- arch/arm/mach-footbridge/netwinder-pci.c | 2 +- arch/arm/mach-footbridge/personal-pci.c | 5 ++--- 4 files changed, 7 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-footbridge/cats-pci.c b/arch/arm/mach-footbridge/cats-pci.c index 0b2fd7e2e9b4..90b1e9be430e 100644 --- a/arch/arm/mach-footbridge/cats-pci.c +++ b/arch/arm/mach-footbridge/cats-pci.c @@ -15,14 +15,14 @@ #include /* cats host-specific stuff */ -static int irqmap_cats[] __initdata = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; +static int irqmap_cats[] = { IRQ_PCI, IRQ_IN0, IRQ_IN1, IRQ_IN3 }; static u8 cats_no_swizzle(struct pci_dev *dev, u8 *pin) { return 0; } -static int __init cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int cats_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { if (dev->irq >= 255) return -1; /* not a valid interrupt. */ diff --git a/arch/arm/mach-footbridge/ebsa285-pci.c b/arch/arm/mach-footbridge/ebsa285-pci.c index 6f28aaa9ca79..c3f280d08fa7 100644 --- a/arch/arm/mach-footbridge/ebsa285-pci.c +++ b/arch/arm/mach-footbridge/ebsa285-pci.c @@ -14,9 +14,9 @@ #include #include -static int irqmap_ebsa285[] __initdata = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI }; +static int irqmap_ebsa285[] = { IRQ_IN3, IRQ_IN1, IRQ_IN0, IRQ_PCI }; -static int __init ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int ebsa285_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { if (dev->vendor == PCI_VENDOR_ID_CONTAQ && dev->device == PCI_DEVICE_ID_CONTAQ_82C693) diff --git a/arch/arm/mach-footbridge/netwinder-pci.c b/arch/arm/mach-footbridge/netwinder-pci.c index 9473aa0305e5..e8304392074b 100644 --- a/arch/arm/mach-footbridge/netwinder-pci.c +++ b/arch/arm/mach-footbridge/netwinder-pci.c @@ -18,7 +18,7 @@ * We now use the slot ID instead of the device identifiers to select * which interrupt is routed where. */ -static int __init netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) +static int netwinder_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { switch (slot) { case 0: /* host bridge */ diff --git a/arch/arm/mach-footbridge/personal-pci.c b/arch/arm/mach-footbridge/personal-pci.c index 4391e433a4b2..9d19aa98a663 100644 --- a/arch/arm/mach-footbridge/personal-pci.c +++ b/arch/arm/mach-footbridge/personal-pci.c @@ -14,13 +14,12 @@ #include #include -static int irqmap_personal_server[] __initdata = { +static int irqmap_personal_server[] = { IRQ_IN0, IRQ_IN1, IRQ_IN2, IRQ_IN3, 0, 0, 0, IRQ_DOORBELLHOST, IRQ_DMA1, IRQ_DMA2, IRQ_PCI }; -static int __init personal_server_map_irq(const struct pci_dev *dev, u8 slot, - u8 pin) +static int personal_server_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) { unsigned char line; From 39c1f1bd8adf29840ef52225ce95f390e3d7b2cf Mon Sep 17 00:00:00 2001 From: Roger Pau Monne Date: Thu, 25 Mar 2021 10:09:47 +0100 Subject: [PATCH 0386/1091] pinctrl: intel: check REVID register value for device presence MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the value read from the REVID register in order to check for the presence of the device. A read of all ones is treated as if the device is not present, and hence probing is ended. This fixes an issue when running as a Xen PVH dom0, where the ACPI DSDT table is provided unmodified to dom0 and hence contains the pinctrl devices, but the MMIO region(s) containing the device registers might not be mapped in the guest physical memory map if such region(s) are not exposed on a PCI device BAR or marked as reserved in the host memory map. Fixes: 91d898e51e60 ("pinctrl: intel: Convert capability list to features") Suggested-by: Andy Shevchenko Signed-off-by: Roger Pau Monné Signed-off-by: Andy Shevchenko --- drivers/pinctrl/intel/pinctrl-intel.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/drivers/pinctrl/intel/pinctrl-intel.c b/drivers/pinctrl/intel/pinctrl-intel.c index 7283203861ae..9f3361c13ded 100644 --- a/drivers/pinctrl/intel/pinctrl-intel.c +++ b/drivers/pinctrl/intel/pinctrl-intel.c @@ -1493,8 +1493,13 @@ static int intel_pinctrl_probe(struct platform_device *pdev, if (IS_ERR(regs)) return PTR_ERR(regs); - /* Determine community features based on the revision */ + /* + * Determine community features based on the revision. + * A value of all ones means the device is not present. + */ value = readl(regs + REVID); + if (value == ~0u) + return -ENODEV; if (((value & REVID_MASK) >> REVID_SHIFT) >= 0x94) { community->features |= PINCTRL_FEATURE_DEBOUNCE; community->features |= PINCTRL_FEATURE_1K_PD; From 37df9f3fedb6aeaff5564145e8162aab912c9284 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Wed, 24 Mar 2021 03:37:24 -0700 Subject: [PATCH 0387/1091] video: hyperv_fb: Fix a double free in hvfb_probe Function hvfb_probe() calls hvfb_getmem(), expecting upon return that info->apertures is either NULL or points to memory that should be freed by framebuffer_release(). But hvfb_getmem() is freeing the memory and leaving the pointer non-NULL, resulting in a double free if an error occurs or later if hvfb_remove() is called. Fix this by removing all kfree(info->apertures) calls in hvfb_getmem(). This will allow framebuffer_release() to free the memory, which follows the pattern of other fbdev drivers. Fixes: 3a6fb6c4255c ("video: hyperv: hyperv_fb: Use physical memory for fb on HyperV Gen 1 VMs.") Signed-off-by: Lv Yunlong Reviewed-by: Michael Kelley Link: https://lore.kernel.org/r/20210324103724.4189-1-lyl2019@mail.ustc.edu.cn Signed-off-by: Wei Liu --- drivers/video/fbdev/hyperv_fb.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/video/fbdev/hyperv_fb.c b/drivers/video/fbdev/hyperv_fb.c index c8b0ae676809..4dc9077dd2ac 100644 --- a/drivers/video/fbdev/hyperv_fb.c +++ b/drivers/video/fbdev/hyperv_fb.c @@ -1031,7 +1031,6 @@ static int hvfb_getmem(struct hv_device *hdev, struct fb_info *info) PCI_DEVICE_ID_HYPERV_VIDEO, NULL); if (!pdev) { pr_err("Unable to find PCI Hyper-V video\n"); - kfree(info->apertures); return -ENODEV; } @@ -1129,7 +1128,6 @@ getmem_done: } else { pci_dev_put(pdev); } - kfree(info->apertures); return 0; @@ -1141,7 +1139,6 @@ err2: err1: if (!gen2vm) pci_dev_put(pdev); - kfree(info->apertures); return -ENOMEM; } From 8bdfc0455e3a59e2c1207a56be22e910fae0e0d5 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 12 Mar 2021 10:38:40 +0800 Subject: [PATCH 0388/1091] ASoC: soc-component: Add snd_soc_pcm_component_ack Add snd_soc_pcm_component_ack back, which can be used to get an updated buffer pointer in the platform driver. On Asymmetric multiprocessor, this pointer can be sent to Cortex-M core for audio processing. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615516725-4975-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 3 +++ sound/soc/soc-component.c | 14 ++++++++++++++ sound/soc/soc-pcm.c | 2 ++ 3 files changed, 19 insertions(+) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 7dc75b39287f..722cfab28d29 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -146,6 +146,8 @@ struct snd_soc_component_driver { int (*mmap)(struct snd_soc_component *component, struct snd_pcm_substream *substream, struct vm_area_struct *vma); + int (*ack)(struct snd_soc_component *component, + struct snd_pcm_substream *substream); const struct snd_compress_ops *compress_ops; @@ -498,5 +500,6 @@ int snd_soc_pcm_component_pm_runtime_get(struct snd_soc_pcm_runtime *rtd, void *stream); void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd, void *stream, int rollback); +int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream); #endif /* __SOC_COMPONENT_H */ diff --git a/sound/soc/soc-component.c b/sound/soc/soc-component.c index 8415e9bd2932..3a5e84e16a87 100644 --- a/sound/soc/soc-component.c +++ b/sound/soc/soc-component.c @@ -1212,3 +1212,17 @@ void snd_soc_pcm_component_pm_runtime_put(struct snd_soc_pcm_runtime *rtd, soc_component_mark_pop(component, stream, pm); } } + +int snd_soc_pcm_component_ack(struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component; + int i; + + /* FIXME: use 1st pointer */ + for_each_rtd_components(rtd, i, component) + if (component->driver->ack) + return component->driver->ack(component, substream); + + return 0; +} diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 2df70ab851ea..02968a4e52b4 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -2772,6 +2772,8 @@ int soc_new_pcm(struct snd_soc_pcm_runtime *rtd, int num) rtd->ops.page = snd_soc_pcm_component_page; if (drv->mmap) rtd->ops.mmap = snd_soc_pcm_component_mmap; + if (drv->ack) + rtd->ops.ack = snd_soc_pcm_component_ack; } if (playback) From b73d9e6225e86492f6a901223a34ecfa7b55c178 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 12 Mar 2021 10:38:41 +0800 Subject: [PATCH 0389/1091] ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg This is a cpu dai driver for rpmsg audio use case, which is mainly used for getting the user's configuration from devicetree and configure the clocks which is used by Cortex-M core. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615516725-4975-3-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 10 ++ sound/soc/fsl/Makefile | 2 + sound/soc/fsl/fsl_rpmsg.c | 279 ++++++++++++++++++++++++++++++++++++++ sound/soc/fsl/fsl_rpmsg.h | 35 +++++ 4 files changed, 326 insertions(+) create mode 100644 sound/soc/fsl/fsl_rpmsg.c create mode 100644 sound/soc/fsl/fsl_rpmsg.h diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d7f30036d434..3326f30e28f6 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -115,6 +115,16 @@ config SND_SOC_FSL_AUD2HTX config SND_SOC_FSL_UTILS tristate +config SND_SOC_FSL_RPMSG + tristate "NXP Audio Base On RPMSG support" + depends on COMMON_CLK + depends on RPMSG + select SND_SOC_IMX_RPMSG if SND_IMX_SOC != n + help + Say Y if you want to add rpmsg audio support for the Freescale CPUs. + This option is only useful for out-of-tree drivers since + in-tree drivers select it automatically. + config SND_SOC_IMX_PCM_DMA tristate select SND_SOC_GENERIC_DMAENGINE_PCM diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index 8c5fa8a859c0..b63802f345cc 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -27,6 +27,7 @@ snd-soc-fsl-mqs-objs := fsl_mqs.o snd-soc-fsl-easrc-objs := fsl_easrc.o snd-soc-fsl-xcvr-objs := fsl_xcvr.o snd-soc-fsl-aud2htx-objs := fsl_aud2htx.o +snd-soc-fsl-rpmsg-objs := fsl_rpmsg.o obj-$(CONFIG_SND_SOC_FSL_AUDMIX) += snd-soc-fsl-audmix.o obj-$(CONFIG_SND_SOC_FSL_ASOC_CARD) += snd-soc-fsl-asoc-card.o @@ -42,6 +43,7 @@ obj-$(CONFIG_SND_SOC_FSL_EASRC) += snd-soc-fsl-easrc.o obj-$(CONFIG_SND_SOC_POWERPC_DMA) += snd-soc-fsl-dma.o obj-$(CONFIG_SND_SOC_FSL_XCVR) += snd-soc-fsl-xcvr.o obj-$(CONFIG_SND_SOC_FSL_AUD2HTX) += snd-soc-fsl-aud2htx.o +obj-$(CONFIG_SND_SOC_FSL_RPMSG) += snd-soc-fsl-rpmsg.o # MPC5200 Platform Support obj-$(CONFIG_SND_MPC52xx_DMA) += mpc5200_dma.o diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c new file mode 100644 index 000000000000..2d09d8850e2c --- /dev/null +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -0,0 +1,279 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright 2018-2021 NXP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "fsl_rpmsg.h" +#include "imx-pcm.h" + +#define FSL_RPMSG_RATES (SNDRV_PCM_RATE_8000 | \ + SNDRV_PCM_RATE_16000 | \ + SNDRV_PCM_RATE_48000) +#define FSL_RPMSG_FORMATS SNDRV_PCM_FMTBIT_S16_LE + +/* 192kHz/32bit/2ch/60s size is 0x574e00 */ +#define LPA_LARGE_BUFFER_SIZE (0x6000000) + +static const unsigned int fsl_rpmsg_rates[] = { + 8000, 11025, 16000, 22050, 44100, + 32000, 48000, 96000, 88200, 176400, 192000, + 352800, 384000, 705600, 768000, 1411200, 2822400, +}; + +static const struct snd_pcm_hw_constraint_list fsl_rpmsg_rate_constraints = { + .count = ARRAY_SIZE(fsl_rpmsg_rates), + .list = fsl_rpmsg_rates, +}; + +static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai); + struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0; + u64 rate = params_rate(params); + int ret = 0; + + /* Get current pll parent */ + while (p && rpmsg->pll8k && rpmsg->pll11k) { + struct clk *pp = clk_get_parent(p); + + if (clk_is_match(pp, rpmsg->pll8k) || + clk_is_match(pp, rpmsg->pll11k)) { + pll = pp; + break; + } + p = pp; + } + + /* Switch to another pll parent if needed. */ + if (pll) { + npll = (do_div(rate, 8000) ? rpmsg->pll11k : rpmsg->pll8k); + if (!clk_is_match(pll, npll)) { + ret = clk_set_parent(p, npll); + if (ret < 0) + dev_warn(dai->dev, "failed to set parent %s: %d\n", + __clk_get_name(npll), ret); + } + } + + if (!(rpmsg->mclk_streams & BIT(substream->stream))) { + ret = clk_prepare_enable(rpmsg->mclk); + if (ret) { + dev_err(dai->dev, "failed to enable mclk: %d\n", ret); + return ret; + } + + rpmsg->mclk_streams |= BIT(substream->stream); + } + + return ret; +} + +static int fsl_rpmsg_hw_free(struct snd_pcm_substream *substream, + struct snd_soc_dai *dai) +{ + struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai); + + if (rpmsg->mclk_streams & BIT(substream->stream)) { + clk_disable_unprepare(rpmsg->mclk); + rpmsg->mclk_streams &= ~BIT(substream->stream); + } + + return 0; +} + +static int fsl_rpmsg_startup(struct snd_pcm_substream *substream, + struct snd_soc_dai *cpu_dai) +{ + int ret; + + ret = snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &fsl_rpmsg_rate_constraints); + + return ret; +} + +static const struct snd_soc_dai_ops fsl_rpmsg_dai_ops = { + .startup = fsl_rpmsg_startup, + .hw_params = fsl_rpmsg_hw_params, + .hw_free = fsl_rpmsg_hw_free, +}; + +static struct snd_soc_dai_driver fsl_rpmsg_dai = { + .playback = { + .stream_name = "CPU-Playback", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = FSL_RPMSG_FORMATS, + }, + .capture = { + .stream_name = "CPU-Capture", + .channels_min = 2, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = FSL_RPMSG_FORMATS, + }, + .symmetric_rate = 1, + .symmetric_channels = 1, + .symmetric_sample_bits = 1, + .ops = &fsl_rpmsg_dai_ops, +}; + +static const struct snd_soc_component_driver fsl_component = { + .name = "fsl-rpmsg", +}; + +static const struct of_device_id fsl_rpmsg_ids[] = { + { .compatible = "fsl,imx7ulp-rpmsg-audio"}, + { .compatible = "fsl,imx8mm-rpmsg-audio"}, + { .compatible = "fsl,imx8mn-rpmsg-audio"}, + { .compatible = "fsl,imx8mp-rpmsg-audio"}, + { /* sentinel */ } +}; +MODULE_DEVICE_TABLE(of, fsl_rpmsg_ids); + +static int fsl_rpmsg_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + struct fsl_rpmsg *rpmsg; + int ret; + + rpmsg = devm_kzalloc(&pdev->dev, sizeof(struct fsl_rpmsg), GFP_KERNEL); + if (!rpmsg) + return -ENOMEM; + + if (of_property_read_bool(np, "fsl,enable-lpa")) { + rpmsg->enable_lpa = 1; + rpmsg->buffer_size = LPA_LARGE_BUFFER_SIZE; + } else { + rpmsg->buffer_size = IMX_DEFAULT_DMABUF_SIZE; + } + + /* Get the optional clocks */ + rpmsg->ipg = devm_clk_get(&pdev->dev, "ipg"); + if (IS_ERR(rpmsg->ipg)) + rpmsg->ipg = NULL; + + rpmsg->mclk = devm_clk_get(&pdev->dev, "mclk"); + if (IS_ERR(rpmsg->mclk)) + rpmsg->mclk = NULL; + + rpmsg->dma = devm_clk_get(&pdev->dev, "dma"); + if (IS_ERR(rpmsg->dma)) + rpmsg->dma = NULL; + + rpmsg->pll8k = devm_clk_get(&pdev->dev, "pll8k"); + if (IS_ERR(rpmsg->pll8k)) + rpmsg->pll8k = NULL; + + rpmsg->pll11k = devm_clk_get(&pdev->dev, "pll11k"); + if (IS_ERR(rpmsg->pll11k)) + rpmsg->pll11k = NULL; + + platform_set_drvdata(pdev, rpmsg); + pm_runtime_enable(&pdev->dev); + + ret = devm_snd_soc_register_component(&pdev->dev, &fsl_component, + &fsl_rpmsg_dai, 1); + if (ret) + return ret; + + rpmsg->card_pdev = platform_device_register_data(&pdev->dev, + "imx-audio-rpmsg", + PLATFORM_DEVID_NONE, + NULL, + 0); + if (IS_ERR(rpmsg->card_pdev)) { + dev_err(&pdev->dev, "failed to register rpmsg card\n"); + ret = PTR_ERR(rpmsg->card_pdev); + return ret; + } + + return 0; +} + +static int fsl_rpmsg_remove(struct platform_device *pdev) +{ + struct fsl_rpmsg *rpmsg = platform_get_drvdata(pdev); + + if (rpmsg->card_pdev) + platform_device_unregister(rpmsg->card_pdev); + + return 0; +} + +#ifdef CONFIG_PM +static int fsl_rpmsg_runtime_resume(struct device *dev) +{ + struct fsl_rpmsg *rpmsg = dev_get_drvdata(dev); + int ret; + + ret = clk_prepare_enable(rpmsg->ipg); + if (ret) { + dev_err(dev, "failed to enable ipg clock: %d\n", ret); + goto ipg_err; + } + + ret = clk_prepare_enable(rpmsg->dma); + if (ret) { + dev_err(dev, "Failed to enable dma clock %d\n", ret); + goto dma_err; + } + + return 0; + +dma_err: + clk_disable_unprepare(rpmsg->ipg); +ipg_err: + return ret; +} + +static int fsl_rpmsg_runtime_suspend(struct device *dev) +{ + struct fsl_rpmsg *rpmsg = dev_get_drvdata(dev); + + clk_disable_unprepare(rpmsg->dma); + clk_disable_unprepare(rpmsg->ipg); + + return 0; +} +#endif + +static const struct dev_pm_ops fsl_rpmsg_pm_ops = { + SET_RUNTIME_PM_OPS(fsl_rpmsg_runtime_suspend, + fsl_rpmsg_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, + pm_runtime_force_resume) +}; + +static struct platform_driver fsl_rpmsg_driver = { + .probe = fsl_rpmsg_probe, + .remove = fsl_rpmsg_remove, + .driver = { + .name = "fsl_rpmsg", + .pm = &fsl_rpmsg_pm_ops, + .of_match_table = fsl_rpmsg_ids, + }, +}; +module_platform_driver(fsl_rpmsg_driver); + +MODULE_DESCRIPTION("Freescale SoC Audio PRMSG CPU Interface"); +MODULE_AUTHOR("Shengjiu Wang "); +MODULE_ALIAS("platform:fsl_rpmsg"); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/fsl/fsl_rpmsg.h b/sound/soc/fsl/fsl_rpmsg.h new file mode 100644 index 000000000000..4f5b49eb18d8 --- /dev/null +++ b/sound/soc/fsl/fsl_rpmsg.h @@ -0,0 +1,35 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright 2017-2021 NXP + */ + +#ifndef __FSL_RPMSG_H +#define __FSL_RPMSG_H + +/* + * struct fsl_rpmsg - rpmsg private data + * + * @ipg: ipg clock for cpu dai (SAI) + * @mclk: master clock for cpu dai (SAI) + * @dma: clock for dma device + * @pll8k: parent clock for multiple of 8kHz frequency + * @pll11k: parent clock for multiple of 11kHz frequency + * @card_pdev: Platform_device pointer to register a sound card + * @mclk_streams: Active streams that are using baudclk + * @force_lpa: force enable low power audio routine if condition satisfy + * @enable_lpa: enable low power audio routine according to dts setting + * @buffer_size: pre allocated dma buffer size + */ +struct fsl_rpmsg { + struct clk *ipg; + struct clk *mclk; + struct clk *dma; + struct clk *pll8k; + struct clk *pll11k; + struct platform_device *card_pdev; + unsigned int mclk_streams; + int force_lpa; + int enable_lpa; + int buffer_size; +}; +#endif /* __FSL_RPMSG_H */ From 49c6bf62498344fa8f8af2314231f3eb37e0e150 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 12 Mar 2021 10:38:42 +0800 Subject: [PATCH 0390/1091] ASoC: dt-bindings: fsl_rpmsg: Add binding doc for rpmsg audio device fsl_rpmsg is a virtual audio device. Mapping to real hardware devices are SAI, DMA controlled by Cortex M core. What we see from Linux side is a device which provides audio service by rpmsg channel. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615516725-4975-4-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/fsl,rpmsg.yaml | 108 ++++++++++++++++++ 1 file changed, 108 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml diff --git a/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml new file mode 100644 index 000000000000..b4c190bddd84 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/fsl,rpmsg.yaml @@ -0,0 +1,108 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/fsl,rpmsg.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: NXP Audio RPMSG CPU DAI Controller + +maintainers: + - Shengjiu Wang + +description: | + fsl_rpmsg is a virtual audio device. Mapping to real hardware devices + are SAI, DMA controlled by Cortex M core. What we see from Linux + side is a device which provides audio service by rpmsg channel. + +properties: + compatible: + enum: + - fsl,imx7ulp-rpmsg-audio + - fsl,imx8mn-rpmsg-audio + - fsl,imx8mm-rpmsg-audio + - fsl,imx8mp-rpmsg-audio + + model: + $ref: /schemas/types.yaml#/definitions/string + description: User specified audio sound card name + + clocks: + items: + - description: Peripheral clock for register access + - description: Master clock + - description: DMA clock for DMA register access + - description: Parent clock for multiple of 8kHz sample rates + - description: Parent clock for multiple of 11kHz sample rates + + clock-names: + items: + - const: ipg + - const: mclk + - const: dma + - const: pll8k + - const: pll11k + + power-domains: + description: + List of phandle and PM domain specifier as documented in + Documentation/devicetree/bindings/power/power_domain.txt + maxItems: 1 + + memory-region: + $ref: /schemas/types.yaml#/definitions/phandle + description: + phandle to a node describing reserved memory (System RAM memory) + The M core can't access all the DDR memory space on some platform, + So reserved a specific memory for dma buffer which M core can + access. + (see bindings/reserved-memory/reserved-memory.txt) + + audio-codec: + $ref: /schemas/types.yaml#/definitions/phandle + description: The phandle to a node of audio codec + + 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. + + fsl,enable-lpa: + $ref: /schemas/types.yaml#/definitions/flag + description: enable low power audio path. + + fsl,rpmsg-out: + $ref: /schemas/types.yaml#/definitions/flag + description: | + This is a boolean property. If present, the transmitting function + will be enabled. + + fsl,rpmsg-in: + $ref: /schemas/types.yaml#/definitions/flag + description: | + This is a boolean property. If present, the receiving function + will be enabled. + +required: + - compatible + - model + +additionalProperties: false + +examples: + - | + #include + + rpmsg_audio: rpmsg_audio { + compatible = "fsl,imx8mn-rpmsg-audio"; + model = "wm8524-audio"; + fsl,enable-lpa; + fsl,rpmsg-out; + clocks = <&clk IMX8MN_CLK_SAI3_IPG>, + <&clk IMX8MN_CLK_SAI3_ROOT>, + <&clk IMX8MN_CLK_SDMA3_ROOT>, + <&clk IMX8MN_AUDIO_PLL1_OUT>, + <&clk IMX8MN_AUDIO_PLL2_OUT>; + clock-names = "ipg", "mclk", "dma", "pll8k", "pll11k"; + }; From 1935050de0b6c6c961e9de51d5b5d05642f861f1 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 12 Mar 2021 10:38:43 +0800 Subject: [PATCH 0391/1091] ASoC: imx-audio-rpmsg: Add rpmsg_driver for audio channel This driver is used to accept the message from rpmsg audio channel, and if this driver is probed, it will help to register the platform driver, the platform driver will use this audio channel to send and receive messages to and from Cortex-M core. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615516725-4975-5-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 4 + sound/soc/fsl/Makefile | 1 + sound/soc/fsl/imx-audio-rpmsg.c | 140 ++++++++++++++++++++++++++++++++ 3 files changed, 145 insertions(+) create mode 100644 sound/soc/fsl/imx-audio-rpmsg.c diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3326f30e28f6..8dbdc0c5ba58 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -129,6 +129,10 @@ config SND_SOC_IMX_PCM_DMA tristate select SND_SOC_GENERIC_DMAENGINE_PCM +config SND_SOC_IMX_AUDIO_RPMSG + tristate + depends on RPMSG + config SND_SOC_IMX_AUDMUX tristate "Digital Audio Mux module support" help diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index b63802f345cc..f08f3cd07ff5 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -60,6 +60,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o +obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/fsl/imx-audio-rpmsg.c b/sound/soc/fsl/imx-audio-rpmsg.c new file mode 100644 index 000000000000..50099bcaa9cd --- /dev/null +++ b/sound/soc/fsl/imx-audio-rpmsg.c @@ -0,0 +1,140 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright 2017-2020 NXP + +#include +#include +#include "imx-pcm-rpmsg.h" + +/* + * struct imx_audio_rpmsg: private data + * + * @rpmsg_pdev: pointer of platform device + */ +struct imx_audio_rpmsg { + struct platform_device *rpmsg_pdev; +}; + +static int imx_audio_rpmsg_cb(struct rpmsg_device *rpdev, void *data, int len, + void *priv, u32 src) +{ + struct imx_audio_rpmsg *rpmsg = dev_get_drvdata(&rpdev->dev); + struct rpmsg_r_msg *r_msg = (struct rpmsg_r_msg *)data; + struct rpmsg_info *info; + struct rpmsg_msg *msg; + unsigned long flags; + + if (!rpmsg->rpmsg_pdev) + return 0; + + info = platform_get_drvdata(rpmsg->rpmsg_pdev); + + dev_dbg(&rpdev->dev, "get from%d: cmd:%d. %d\n", + src, r_msg->header.cmd, r_msg->param.resp); + + switch (r_msg->header.type) { + case MSG_TYPE_C: + /* TYPE C is notification from M core */ + switch (r_msg->header.cmd) { + case TX_PERIOD_DONE: + spin_lock_irqsave(&info->lock[TX], flags); + msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM]; + msg->r_msg.param.buffer_tail = + r_msg->param.buffer_tail; + msg->r_msg.param.buffer_tail %= info->num_period[TX]; + spin_unlock_irqrestore(&info->lock[TX], flags); + info->callback[TX](info->callback_param[TX]); + break; + case RX_PERIOD_DONE: + spin_lock_irqsave(&info->lock[RX], flags); + msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM]; + msg->r_msg.param.buffer_tail = + r_msg->param.buffer_tail; + msg->r_msg.param.buffer_tail %= info->num_period[1]; + spin_unlock_irqrestore(&info->lock[RX], flags); + info->callback[RX](info->callback_param[RX]); + break; + default: + dev_warn(&rpdev->dev, "unknown msg command\n"); + break; + } + break; + case MSG_TYPE_B: + /* TYPE B is response msg */ + memcpy(&info->r_msg, r_msg, sizeof(struct rpmsg_r_msg)); + complete(&info->cmd_complete); + break; + default: + dev_warn(&rpdev->dev, "unknown msg type\n"); + break; + } + + return 0; +} + +static int imx_audio_rpmsg_probe(struct rpmsg_device *rpdev) +{ + struct imx_audio_rpmsg *data; + int ret = 0; + + dev_info(&rpdev->dev, "new channel: 0x%x -> 0x%x!\n", + rpdev->src, rpdev->dst); + + data = devm_kzalloc(&rpdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) + return -ENOMEM; + + dev_set_drvdata(&rpdev->dev, data); + + /* Register platform driver for rpmsg routine */ + data->rpmsg_pdev = platform_device_register_data(&rpdev->dev, + IMX_PCM_DRV_NAME, + PLATFORM_DEVID_NONE, + NULL, 0); + if (IS_ERR(data->rpmsg_pdev)) { + dev_err(&rpdev->dev, "failed to register rpmsg platform.\n"); + ret = PTR_ERR(data->rpmsg_pdev); + } + + return ret; +} + +static void imx_audio_rpmsg_remove(struct rpmsg_device *rpdev) +{ + struct imx_audio_rpmsg *data = dev_get_drvdata(&rpdev->dev); + + if (data->rpmsg_pdev) + platform_device_unregister(data->rpmsg_pdev); + + dev_info(&rpdev->dev, "audio rpmsg driver is removed\n"); +} + +static struct rpmsg_device_id imx_audio_rpmsg_id_table[] = { + { .name = "rpmsg-audio-channel" }, + { }, +}; + +static struct rpmsg_driver imx_audio_rpmsg_driver = { + .drv.name = "imx_audio_rpmsg", + .drv.owner = THIS_MODULE, + .id_table = imx_audio_rpmsg_id_table, + .probe = imx_audio_rpmsg_probe, + .callback = imx_audio_rpmsg_cb, + .remove = imx_audio_rpmsg_remove, +}; + +static int __init imx_audio_rpmsg_init(void) +{ + return register_rpmsg_driver(&imx_audio_rpmsg_driver); +} + +static void __exit imx_audio_rpmsg_exit(void) +{ + unregister_rpmsg_driver(&imx_audio_rpmsg_driver); +} +module_init(imx_audio_rpmsg_init); +module_exit(imx_audio_rpmsg_exit); + +MODULE_DESCRIPTION("Freescale SoC Audio RPMSG interface"); +MODULE_AUTHOR("Shengjiu Wang "); +MODULE_ALIAS("platform:imx_audio_rpmsg"); +MODULE_LICENSE("GPL v2"); From 3c00eceb2a5391ed1ca6703b71cad35ab8cd4352 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 12 Mar 2021 10:38:44 +0800 Subject: [PATCH 0392/1091] ASoC: imx-pcm-rpmsg: Add platform driver for audio base on rpmsg Platform driver based on rpmsg is the interface for sending and receiving rpmsg to and from M core. It will tell the Cortex-M core sound format/rate/channel, where is the data buffer, where is the period size, when to start, when to stop and when suspend or resume happen, each this behavior there is defined rpmsg command. Especially we designed the low power audio case, that is to allocate a large buffer and fill the data, then Cortex-A core can go to sleep mode, Cortex-M core continue to play the sound, when the buffer is consumed, Cortex-M core will trigger the Cortex-A core to wake up. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615516725-4975-6-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 5 + sound/soc/fsl/Makefile | 1 + sound/soc/fsl/imx-pcm-rpmsg.c | 918 ++++++++++++++++++++++++++++++++++ sound/soc/fsl/imx-pcm-rpmsg.h | 512 +++++++++++++++++++ 4 files changed, 1436 insertions(+) create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.c create mode 100644 sound/soc/fsl/imx-pcm-rpmsg.h diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 8dbdc0c5ba58..3d3d14f3793e 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -133,6 +133,11 @@ config SND_SOC_IMX_AUDIO_RPMSG tristate depends on RPMSG +config SND_SOC_IMX_PCM_RPMSG + tristate + depends on SND_SOC_IMX_AUDIO_RPMSG + select SND_SOC_GENERIC_DMAENGINE_PCM + config SND_SOC_IMX_AUDMUX tristate "Digital Audio Mux module support" help diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index f08f3cd07ff5..ce4f4324c3a2 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -61,6 +61,7 @@ obj-$(CONFIG_SND_SOC_IMX_AUDMUX) += snd-soc-imx-audmux.o obj-$(CONFIG_SND_SOC_IMX_PCM_FIQ) += imx-pcm-fiq.o obj-$(CONFIG_SND_SOC_IMX_PCM_DMA) += imx-pcm-dma.o obj-$(CONFIG_SND_SOC_IMX_AUDIO_RPMSG) += imx-audio-rpmsg.o +obj-$(CONFIG_SND_SOC_IMX_PCM_RPMSG) += imx-pcm-rpmsg.o # i.MX Machine Support snd-soc-eukrea-tlv320-objs := eukrea-tlv320.o diff --git a/sound/soc/fsl/imx-pcm-rpmsg.c b/sound/soc/fsl/imx-pcm-rpmsg.c new file mode 100644 index 000000000000..875c0d6df339 --- /dev/null +++ b/sound/soc/fsl/imx-pcm-rpmsg.c @@ -0,0 +1,918 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright 2017-2021 NXP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "imx-pcm.h" +#include "fsl_rpmsg.h" +#include "imx-pcm-rpmsg.h" + +static struct snd_pcm_hardware imx_rpmsg_pcm_hardware = { + .info = SNDRV_PCM_INFO_INTERLEAVED | + SNDRV_PCM_INFO_BLOCK_TRANSFER | + SNDRV_PCM_INFO_MMAP | + SNDRV_PCM_INFO_MMAP_VALID | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP | + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_RESUME, + .buffer_bytes_max = IMX_DEFAULT_DMABUF_SIZE, + .period_bytes_min = 512, + .period_bytes_max = 65536, + .periods_min = 2, + .periods_max = 6000, + .fifo_size = 0, +}; + +static int imx_rpmsg_pcm_send_message(struct rpmsg_msg *msg, + struct rpmsg_info *info) +{ + struct rpmsg_device *rpdev = info->rpdev; + int ret = 0; + + mutex_lock(&info->msg_lock); + if (!rpdev) { + dev_err(info->dev, "rpmsg channel not ready\n"); + mutex_unlock(&info->msg_lock); + return -EINVAL; + } + + dev_dbg(&rpdev->dev, "send cmd %d\n", msg->s_msg.header.cmd); + + if (!(msg->s_msg.header.type == MSG_TYPE_C)) + reinit_completion(&info->cmd_complete); + + ret = rpmsg_send(rpdev->ept, (void *)&msg->s_msg, + sizeof(struct rpmsg_s_msg)); + if (ret) { + dev_err(&rpdev->dev, "rpmsg_send failed: %d\n", ret); + mutex_unlock(&info->msg_lock); + return ret; + } + + /* No receive msg for TYPE_C command */ + if (msg->s_msg.header.type == MSG_TYPE_C) { + mutex_unlock(&info->msg_lock); + return 0; + } + + /* wait response from rpmsg */ + ret = wait_for_completion_timeout(&info->cmd_complete, + msecs_to_jiffies(RPMSG_TIMEOUT)); + if (!ret) { + dev_err(&rpdev->dev, "rpmsg_send cmd %d timeout!\n", + msg->s_msg.header.cmd); + mutex_unlock(&info->msg_lock); + return -ETIMEDOUT; + } + + memcpy(&msg->r_msg, &info->r_msg, sizeof(struct rpmsg_r_msg)); + memcpy(&info->msg[msg->r_msg.header.cmd].r_msg, + &msg->r_msg, sizeof(struct rpmsg_r_msg)); + + /* + * Reset the buffer pointer to be zero, actully we have + * set the buffer pointer to be zero in imx_rpmsg_terminate_all + * But if there is timer task queued in queue, after it is + * executed the buffer pointer will be changed, so need to + * reset it again with TERMINATE command. + */ + switch (msg->s_msg.header.cmd) { + case TX_TERMINATE: + info->msg[TX_POINTER].r_msg.param.buffer_offset = 0; + break; + case RX_TERMINATE: + info->msg[RX_POINTER].r_msg.param.buffer_offset = 0; + break; + default: + break; + } + + dev_dbg(&rpdev->dev, "cmd:%d, resp %d\n", msg->s_msg.header.cmd, + info->r_msg.param.resp); + + mutex_unlock(&info->msg_lock); + + return 0; +} + +static int imx_rpmsg_insert_workqueue(struct snd_pcm_substream *substream, + struct rpmsg_msg *msg, + struct rpmsg_info *info) +{ + unsigned long flags; + int ret = 0; + + /* + * Queue the work to workqueue. + * If the queue is full, drop the message. + */ + spin_lock_irqsave(&info->wq_lock, flags); + if (info->work_write_index != info->work_read_index) { + int index = info->work_write_index; + + memcpy(&info->work_list[index].msg, msg, + sizeof(struct rpmsg_s_msg)); + + queue_work(info->rpmsg_wq, &info->work_list[index].work); + info->work_write_index++; + info->work_write_index %= WORK_MAX_NUM; + } else { + info->msg_drop_count[substream->stream]++; + ret = -EPIPE; + } + spin_unlock_irqrestore(&info->wq_lock, flags); + + return ret; +} + +static int imx_rpmsg_pcm_hw_params(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct snd_pcm_runtime *runtime = substream->runtime; + struct rpmsg_msg *msg; + int ret = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_HW_PARAM]; + msg->s_msg.header.cmd = TX_HW_PARAM; + } else { + msg = &info->msg[RX_HW_PARAM]; + msg->s_msg.header.cmd = RX_HW_PARAM; + } + + msg->s_msg.param.rate = params_rate(params); + + switch (params_format(params)) { + case SNDRV_PCM_FORMAT_S16_LE: + msg->s_msg.param.format = RPMSG_S16_LE; + break; + case SNDRV_PCM_FORMAT_S24_LE: + msg->s_msg.param.format = RPMSG_S24_LE; + break; + case SNDRV_PCM_FORMAT_DSD_U16_LE: + msg->s_msg.param.format = SNDRV_PCM_FORMAT_DSD_U16_LE; + break; + case SNDRV_PCM_FORMAT_DSD_U32_LE: + msg->s_msg.param.format = SNDRV_PCM_FORMAT_DSD_U32_LE; + break; + default: + msg->s_msg.param.format = RPMSG_S32_LE; + break; + } + + switch (params_channels(params)) { + case 1: + msg->s_msg.param.channels = RPMSG_CH_LEFT; + break; + case 2: + msg->s_msg.param.channels = RPMSG_CH_STEREO; + break; + default: + ret = -EINVAL; + break; + } + + snd_pcm_set_runtime_buffer(substream, &substream->dma_buffer); + runtime->dma_bytes = params_buffer_bytes(params); + + info->send_message(msg, info); + + return ret; +} + +static int imx_rpmsg_pcm_hw_free(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + snd_pcm_set_runtime_buffer(substream, NULL); + return 0; +} + +static snd_pcm_uframes_t imx_rpmsg_pcm_pointer(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + unsigned int pos = 0; + int buffer_tail = 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM]; + else + msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM]; + + buffer_tail = msg->r_msg.param.buffer_tail; + pos = buffer_tail * snd_pcm_lib_period_bytes(substream); + + return bytes_to_frames(substream->runtime, pos); +} + +static void imx_rpmsg_timer_callback(struct timer_list *t) +{ + struct stream_timer *stream_timer = + from_timer(stream_timer, t, timer); + struct snd_pcm_substream *substream = stream_timer->substream; + struct rpmsg_info *info = stream_timer->info; + struct rpmsg_msg *msg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM]; + msg->s_msg.header.cmd = TX_PERIOD_DONE; + } else { + msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM]; + msg->s_msg.header.cmd = RX_PERIOD_DONE; + } + + imx_rpmsg_insert_workqueue(substream, msg, info); +} + +static int imx_rpmsg_pcm_open(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + int ret = 0; + int cmd; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_OPEN]; + msg->s_msg.header.cmd = TX_OPEN; + + /* reinitialize buffer counter*/ + cmd = TX_PERIOD_DONE + MSG_TYPE_A_NUM; + info->msg[cmd].s_msg.param.buffer_tail = 0; + info->msg[cmd].r_msg.param.buffer_tail = 0; + info->msg[TX_POINTER].r_msg.param.buffer_offset = 0; + + } else { + msg = &info->msg[RX_OPEN]; + msg->s_msg.header.cmd = RX_OPEN; + + /* reinitialize buffer counter*/ + cmd = RX_PERIOD_DONE + MSG_TYPE_A_NUM; + info->msg[cmd].s_msg.param.buffer_tail = 0; + info->msg[cmd].r_msg.param.buffer_tail = 0; + info->msg[RX_POINTER].r_msg.param.buffer_offset = 0; + } + + info->send_message(msg, info); + + imx_rpmsg_pcm_hardware.period_bytes_max = + imx_rpmsg_pcm_hardware.buffer_bytes_max / 2; + + snd_soc_set_runtime_hwparams(substream, &imx_rpmsg_pcm_hardware); + + ret = snd_pcm_hw_constraint_integer(substream->runtime, + SNDRV_PCM_HW_PARAM_PERIODS); + if (ret < 0) + return ret; + + info->msg_drop_count[substream->stream] = 0; + + /* Create timer*/ + info->stream_timer[substream->stream].info = info; + info->stream_timer[substream->stream].substream = substream; + timer_setup(&info->stream_timer[substream->stream].timer, + imx_rpmsg_timer_callback, 0); + return ret; +} + +static int imx_rpmsg_pcm_close(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + int ret = 0; + + /* Flush work in workqueue to make TX_CLOSE is the last message */ + flush_workqueue(info->rpmsg_wq); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_CLOSE]; + msg->s_msg.header.cmd = TX_CLOSE; + } else { + msg = &info->msg[RX_CLOSE]; + msg->s_msg.header.cmd = RX_CLOSE; + } + + info->send_message(msg, info); + + del_timer(&info->stream_timer[substream->stream].timer); + + rtd->dai_link->ignore_suspend = 0; + + if (info->msg_drop_count[substream->stream]) + dev_warn(rtd->dev, "Msg is dropped!, number is %d\n", + info->msg_drop_count[substream->stream]); + + return ret; +} + +static int imx_rpmsg_pcm_prepare(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev); + + /* + * NON-MMAP mode, NONBLOCK, Version 2, enable lpa in dts + * four conditions to determine the lpa is enabled. + */ + if ((runtime->access == SNDRV_PCM_ACCESS_RW_INTERLEAVED || + runtime->access == SNDRV_PCM_ACCESS_RW_NONINTERLEAVED) && + rpmsg->enable_lpa) { + /* + * Ignore suspend operation in low power mode + * M core will continue playback music on A core suspend. + */ + rtd->dai_link->ignore_suspend = 1; + rpmsg->force_lpa = 1; + } else { + rpmsg->force_lpa = 0; + } + + return 0; +} + +static int imx_rpmsg_pcm_mmap(struct snd_soc_component *component, + struct snd_pcm_substream *substream, + struct vm_area_struct *vma) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + return dma_mmap_wc(substream->pcm->card->dev, vma, + runtime->dma_area, + runtime->dma_addr, + runtime->dma_bytes); +} + +static void imx_rpmsg_pcm_dma_complete(void *arg) +{ + struct snd_pcm_substream *substream = arg; + + snd_pcm_period_elapsed(substream); +} + +static int imx_rpmsg_prepare_and_submit(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_BUFFER]; + msg->s_msg.header.cmd = TX_BUFFER; + } else { + msg = &info->msg[RX_BUFFER]; + msg->s_msg.header.cmd = RX_BUFFER; + } + + /* Send buffer address and buffer size */ + msg->s_msg.param.buffer_addr = substream->runtime->dma_addr; + msg->s_msg.param.buffer_size = snd_pcm_lib_buffer_bytes(substream); + msg->s_msg.param.period_size = snd_pcm_lib_period_bytes(substream); + msg->s_msg.param.buffer_tail = 0; + + info->num_period[substream->stream] = msg->s_msg.param.buffer_size / + msg->s_msg.param.period_size; + + info->callback[substream->stream] = imx_rpmsg_pcm_dma_complete; + info->callback_param[substream->stream] = substream; + + return imx_rpmsg_insert_workqueue(substream, msg, info); +} + +static int imx_rpmsg_async_issue_pending(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_START]; + msg->s_msg.header.cmd = TX_START; + } else { + msg = &info->msg[RX_START]; + msg->s_msg.header.cmd = RX_START; + } + + return imx_rpmsg_insert_workqueue(substream, msg, info); +} + +static int imx_rpmsg_restart(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_RESTART]; + msg->s_msg.header.cmd = TX_RESTART; + } else { + msg = &info->msg[RX_RESTART]; + msg->s_msg.header.cmd = RX_RESTART; + } + + return imx_rpmsg_insert_workqueue(substream, msg, info); +} + +static int imx_rpmsg_pause(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_PAUSE]; + msg->s_msg.header.cmd = TX_PAUSE; + } else { + msg = &info->msg[RX_PAUSE]; + msg->s_msg.header.cmd = RX_PAUSE; + } + + return imx_rpmsg_insert_workqueue(substream, msg, info); +} + +static int imx_rpmsg_terminate_all(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct rpmsg_info *info = dev_get_drvdata(component->dev); + struct rpmsg_msg *msg; + int cmd; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_TERMINATE]; + msg->s_msg.header.cmd = TX_TERMINATE; + /* Clear buffer count*/ + cmd = TX_PERIOD_DONE + MSG_TYPE_A_NUM; + info->msg[cmd].s_msg.param.buffer_tail = 0; + info->msg[cmd].r_msg.param.buffer_tail = 0; + info->msg[TX_POINTER].r_msg.param.buffer_offset = 0; + } else { + msg = &info->msg[RX_TERMINATE]; + msg->s_msg.header.cmd = RX_TERMINATE; + /* Clear buffer count*/ + cmd = RX_PERIOD_DONE + MSG_TYPE_A_NUM; + info->msg[cmd].s_msg.param.buffer_tail = 0; + info->msg[cmd].r_msg.param.buffer_tail = 0; + info->msg[RX_POINTER].r_msg.param.buffer_offset = 0; + } + + del_timer(&info->stream_timer[substream->stream].timer); + + return imx_rpmsg_insert_workqueue(substream, msg, info); +} + +static int imx_rpmsg_pcm_trigger(struct snd_soc_component *component, + struct snd_pcm_substream *substream, int cmd) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev); + int ret = 0; + + switch (cmd) { + case SNDRV_PCM_TRIGGER_START: + ret = imx_rpmsg_prepare_and_submit(component, substream); + if (ret) + return ret; + ret = imx_rpmsg_async_issue_pending(component, substream); + break; + case SNDRV_PCM_TRIGGER_RESUME: + if (rpmsg->force_lpa) + break; + fallthrough; + case SNDRV_PCM_TRIGGER_PAUSE_RELEASE: + ret = imx_rpmsg_restart(component, substream); + break; + case SNDRV_PCM_TRIGGER_SUSPEND: + if (!rpmsg->force_lpa) { + if (runtime->info & SNDRV_PCM_INFO_PAUSE) + ret = imx_rpmsg_pause(component, substream); + else + ret = imx_rpmsg_terminate_all(component, substream); + } + break; + case SNDRV_PCM_TRIGGER_PAUSE_PUSH: + ret = imx_rpmsg_pause(component, substream); + break; + case SNDRV_PCM_TRIGGER_STOP: + ret = imx_rpmsg_terminate_all(component, substream); + break; + default: + return -EINVAL; + } + + if (ret) + return ret; + + return 0; +} + +/* + * imx_rpmsg_pcm_ack + * + * Send the period index to M core through rpmsg, but not send + * all the period index to M core, reduce some unnessesary msg + * to reduce the pressure of rpmsg bandwidth. + */ +static int imx_rpmsg_pcm_ack(struct snd_soc_component *component, + struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + struct snd_soc_pcm_runtime *rtd = substream->private_data; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev); + struct rpmsg_info *info = dev_get_drvdata(component->dev); + snd_pcm_uframes_t period_size = runtime->period_size; + snd_pcm_sframes_t avail; + struct timer_list *timer; + struct rpmsg_msg *msg; + unsigned long flags; + int buffer_tail = 0; + int written_num = 0; + + if (!rpmsg->force_lpa) + return 0; + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) { + msg = &info->msg[TX_PERIOD_DONE + MSG_TYPE_A_NUM]; + msg->s_msg.header.cmd = TX_PERIOD_DONE; + } else { + msg = &info->msg[RX_PERIOD_DONE + MSG_TYPE_A_NUM]; + msg->s_msg.header.cmd = RX_PERIOD_DONE; + } + + msg->s_msg.header.type = MSG_TYPE_C; + + buffer_tail = (frames_to_bytes(runtime, runtime->control->appl_ptr) % + snd_pcm_lib_buffer_bytes(substream)); + buffer_tail = buffer_tail / snd_pcm_lib_period_bytes(substream); + + /* There is update for period index */ + if (buffer_tail != msg->s_msg.param.buffer_tail) { + written_num = buffer_tail - msg->s_msg.param.buffer_tail; + if (written_num < 0) + written_num += runtime->periods; + + msg->s_msg.param.buffer_tail = buffer_tail; + + /* The notification message is updated to latest */ + spin_lock_irqsave(&info->lock[substream->stream], flags); + memcpy(&info->notify[substream->stream], msg, + sizeof(struct rpmsg_s_msg)); + info->notify_updated[substream->stream] = true; + spin_unlock_irqrestore(&info->lock[substream->stream], flags); + + if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) + avail = snd_pcm_playback_hw_avail(runtime); + else + avail = snd_pcm_capture_hw_avail(runtime); + + timer = &info->stream_timer[substream->stream].timer; + /* + * If the data in the buffer is less than one period before + * this fill, which means the data may not enough on M + * core side, we need to send message immediately to let + * M core know the pointer is updated. + * if there is more than one period data in the buffer before + * this fill, which means the data is enough on M core side, + * we can delay one period (using timer) to send the message + * for reduce the message number in workqueue, because the + * pointer may be updated by ack function later, we can + * send latest pointer to M core side. + */ + if ((avail - written_num * period_size) <= period_size) { + imx_rpmsg_insert_workqueue(substream, msg, info); + } else if (rpmsg->force_lpa && !timer_pending(timer)) { + int time_msec; + + time_msec = (int)(runtime->period_size * 1000 / runtime->rate); + mod_timer(timer, jiffies + msecs_to_jiffies(time_msec)); + } + } + + return 0; +} + +static int imx_rpmsg_pcm_preallocate_dma_buffer(struct snd_pcm *pcm, + int stream, int size) +{ + struct snd_pcm_substream *substream = pcm->streams[stream].substream; + struct snd_dma_buffer *buf = &substream->dma_buffer; + + buf->dev.type = SNDRV_DMA_TYPE_DEV; + buf->dev.dev = pcm->card->dev; + buf->private_data = NULL; + buf->area = dma_alloc_wc(pcm->card->dev, size, + &buf->addr, GFP_KERNEL); + if (!buf->area) + return -ENOMEM; + + buf->bytes = size; + return 0; +} + +static void imx_rpmsg_pcm_free_dma_buffers(struct snd_soc_component *component, + struct snd_pcm *pcm) +{ + struct snd_pcm_substream *substream; + struct snd_dma_buffer *buf; + int stream; + + for (stream = SNDRV_PCM_STREAM_PLAYBACK; + stream < SNDRV_PCM_STREAM_LAST; stream++) { + substream = pcm->streams[stream].substream; + if (!substream) + continue; + + buf = &substream->dma_buffer; + if (!buf->area) + continue; + + dma_free_wc(pcm->card->dev, buf->bytes, + buf->area, buf->addr); + buf->area = NULL; + } +} + +static int imx_rpmsg_pcm_new(struct snd_soc_component *component, + struct snd_soc_pcm_runtime *rtd) +{ + struct snd_card *card = rtd->card->snd_card; + struct snd_pcm *pcm = rtd->pcm; + struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct fsl_rpmsg *rpmsg = dev_get_drvdata(cpu_dai->dev); + int ret; + + ret = dma_coerce_mask_and_coherent(card->dev, DMA_BIT_MASK(32)); + if (ret) + return ret; + + if (pcm->streams[SNDRV_PCM_STREAM_PLAYBACK].substream) { + ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_PLAYBACK, + rpmsg->buffer_size); + if (ret) + goto out; + } + + if (pcm->streams[SNDRV_PCM_STREAM_CAPTURE].substream) { + ret = imx_rpmsg_pcm_preallocate_dma_buffer(pcm, SNDRV_PCM_STREAM_CAPTURE, + rpmsg->buffer_size); + if (ret) + goto out; + } + + imx_rpmsg_pcm_hardware.buffer_bytes_max = rpmsg->buffer_size; +out: + /* free preallocated buffers in case of error */ + if (ret) + imx_rpmsg_pcm_free_dma_buffers(component, pcm); + + return ret; +} + +static const struct snd_soc_component_driver imx_rpmsg_soc_component = { + .name = IMX_PCM_DRV_NAME, + .pcm_construct = imx_rpmsg_pcm_new, + .pcm_destruct = imx_rpmsg_pcm_free_dma_buffers, + .open = imx_rpmsg_pcm_open, + .close = imx_rpmsg_pcm_close, + .hw_params = imx_rpmsg_pcm_hw_params, + .hw_free = imx_rpmsg_pcm_hw_free, + .trigger = imx_rpmsg_pcm_trigger, + .pointer = imx_rpmsg_pcm_pointer, + .mmap = imx_rpmsg_pcm_mmap, + .ack = imx_rpmsg_pcm_ack, + .prepare = imx_rpmsg_pcm_prepare, +}; + +static void imx_rpmsg_pcm_work(struct work_struct *work) +{ + struct work_of_rpmsg *work_of_rpmsg; + bool is_notification = false; + struct rpmsg_info *info; + struct rpmsg_msg msg; + unsigned long flags; + + work_of_rpmsg = container_of(work, struct work_of_rpmsg, work); + info = work_of_rpmsg->info; + + /* + * Every work in the work queue, first we check if there + * is update for period is filled, because there may be not + * enough data in M core side, need to let M core know + * data is updated immediately. + */ + spin_lock_irqsave(&info->lock[TX], flags); + if (info->notify_updated[TX]) { + memcpy(&msg, &info->notify[TX], sizeof(struct rpmsg_s_msg)); + info->notify_updated[TX] = false; + spin_unlock_irqrestore(&info->lock[TX], flags); + info->send_message(&msg, info); + } else { + spin_unlock_irqrestore(&info->lock[TX], flags); + } + + spin_lock_irqsave(&info->lock[RX], flags); + if (info->notify_updated[RX]) { + memcpy(&msg, &info->notify[RX], sizeof(struct rpmsg_s_msg)); + info->notify_updated[RX] = false; + spin_unlock_irqrestore(&info->lock[RX], flags); + info->send_message(&msg, info); + } else { + spin_unlock_irqrestore(&info->lock[RX], flags); + } + + /* Skip the notification message for it has been processed above */ + if (work_of_rpmsg->msg.s_msg.header.type == MSG_TYPE_C && + (work_of_rpmsg->msg.s_msg.header.cmd == TX_PERIOD_DONE || + work_of_rpmsg->msg.s_msg.header.cmd == RX_PERIOD_DONE)) + is_notification = true; + + if (!is_notification) + info->send_message(&work_of_rpmsg->msg, info); + + /* update read index */ + spin_lock_irqsave(&info->wq_lock, flags); + info->work_read_index++; + info->work_read_index %= WORK_MAX_NUM; + spin_unlock_irqrestore(&info->wq_lock, flags); +} + +static int imx_rpmsg_pcm_probe(struct platform_device *pdev) +{ + struct snd_soc_component *component; + struct rpmsg_info *info; + int ret, i; + + info = devm_kzalloc(&pdev->dev, sizeof(*info), GFP_KERNEL); + if (!info) + return -ENOMEM; + + platform_set_drvdata(pdev, info); + + info->rpdev = container_of(pdev->dev.parent, struct rpmsg_device, dev); + info->dev = &pdev->dev; + /* Setup work queue */ + info->rpmsg_wq = alloc_ordered_workqueue("rpmsg_audio", + WQ_HIGHPRI | + WQ_UNBOUND | + WQ_FREEZABLE); + if (!info->rpmsg_wq) { + dev_err(&pdev->dev, "workqueue create failed\n"); + return -ENOMEM; + } + + /* Write index initialize 1, make it differ with the read index */ + info->work_write_index = 1; + info->send_message = imx_rpmsg_pcm_send_message; + + for (i = 0; i < WORK_MAX_NUM; i++) { + INIT_WORK(&info->work_list[i].work, imx_rpmsg_pcm_work); + info->work_list[i].info = info; + } + + /* Initialize msg */ + for (i = 0; i < MSG_MAX_NUM; i++) { + info->msg[i].s_msg.header.cate = IMX_RPMSG_AUDIO; + info->msg[i].s_msg.header.major = IMX_RMPSG_MAJOR; + info->msg[i].s_msg.header.minor = IMX_RMPSG_MINOR; + info->msg[i].s_msg.header.type = MSG_TYPE_A; + info->msg[i].s_msg.param.audioindex = 0; + } + + init_completion(&info->cmd_complete); + mutex_init(&info->msg_lock); + spin_lock_init(&info->lock[TX]); + spin_lock_init(&info->lock[RX]); + spin_lock_init(&info->wq_lock); + + ret = devm_snd_soc_register_component(&pdev->dev, + &imx_rpmsg_soc_component, + NULL, 0); + if (ret) + goto fail; + + component = snd_soc_lookup_component(&pdev->dev, IMX_PCM_DRV_NAME); + if (!component) { + ret = -EINVAL; + goto fail; + } +#ifdef CONFIG_DEBUG_FS + component->debugfs_prefix = "rpmsg"; +#endif + + return 0; + +fail: + if (info->rpmsg_wq) + destroy_workqueue(info->rpmsg_wq); + + return ret; +} + +static int imx_rpmsg_pcm_remove(struct platform_device *pdev) +{ + struct rpmsg_info *info = platform_get_drvdata(pdev); + + if (info->rpmsg_wq) + destroy_workqueue(info->rpmsg_wq); + + return 0; +} + +#ifdef CONFIG_PM +static int imx_rpmsg_pcm_runtime_resume(struct device *dev) +{ + struct rpmsg_info *info = dev_get_drvdata(dev); + + cpu_latency_qos_add_request(&info->pm_qos_req, 0); + + return 0; +} + +static int imx_rpmsg_pcm_runtime_suspend(struct device *dev) +{ + struct rpmsg_info *info = dev_get_drvdata(dev); + + cpu_latency_qos_remove_request(&info->pm_qos_req); + + return 0; +} +#endif + +#ifdef CONFIG_PM_SLEEP +static int imx_rpmsg_pcm_suspend(struct device *dev) +{ + struct rpmsg_info *info = dev_get_drvdata(dev); + struct rpmsg_msg *rpmsg_tx; + struct rpmsg_msg *rpmsg_rx; + + rpmsg_tx = &info->msg[TX_SUSPEND]; + rpmsg_rx = &info->msg[RX_SUSPEND]; + + rpmsg_tx->s_msg.header.cmd = TX_SUSPEND; + info->send_message(rpmsg_tx, info); + + rpmsg_rx->s_msg.header.cmd = RX_SUSPEND; + info->send_message(rpmsg_rx, info); + + return 0; +} + +static int imx_rpmsg_pcm_resume(struct device *dev) +{ + struct rpmsg_info *info = dev_get_drvdata(dev); + struct rpmsg_msg *rpmsg_tx; + struct rpmsg_msg *rpmsg_rx; + + rpmsg_tx = &info->msg[TX_RESUME]; + rpmsg_rx = &info->msg[RX_RESUME]; + + rpmsg_tx->s_msg.header.cmd = TX_RESUME; + info->send_message(rpmsg_tx, info); + + rpmsg_rx->s_msg.header.cmd = RX_RESUME; + info->send_message(rpmsg_rx, info); + + return 0; +} +#endif /* CONFIG_PM_SLEEP */ + +static const struct dev_pm_ops imx_rpmsg_pcm_pm_ops = { + SET_RUNTIME_PM_OPS(imx_rpmsg_pcm_runtime_suspend, + imx_rpmsg_pcm_runtime_resume, + NULL) + SET_SYSTEM_SLEEP_PM_OPS(imx_rpmsg_pcm_suspend, + imx_rpmsg_pcm_resume) +}; + +static struct platform_driver imx_pcm_rpmsg_driver = { + .probe = imx_rpmsg_pcm_probe, + .remove = imx_rpmsg_pcm_remove, + .driver = { + .name = IMX_PCM_DRV_NAME, + .pm = &imx_rpmsg_pcm_pm_ops, + }, +}; +module_platform_driver(imx_pcm_rpmsg_driver); + +MODULE_DESCRIPTION("Freescale SoC Audio RPMSG PCM interface"); +MODULE_AUTHOR("Shengjiu Wang "); +MODULE_ALIAS("platform:" IMX_PCM_DRV_NAME); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/fsl/imx-pcm-rpmsg.h b/sound/soc/fsl/imx-pcm-rpmsg.h new file mode 100644 index 000000000000..308d153920a3 --- /dev/null +++ b/sound/soc/fsl/imx-pcm-rpmsg.h @@ -0,0 +1,512 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Copyright 2017-2021 NXP + * + ****************************************************************************** + * Communication stack of audio with rpmsg + ****************************************************************************** + * Packet structure: + * A SRTM message consists of a 10 bytes header followed by 0~N bytes of data + * + * +---------------+-------------------------------+ + * | | Content | + * +---------------+-------------------------------+ + * | Byte Offset | 7 6 5 4 3 2 1 0 | + * +---------------+---+---+---+---+---+---+---+---+ + * | 0 | Category | + * +---------------+---+---+---+---+---+---+---+---+ + * | 1 ~ 2 | Version | + * +---------------+---+---+---+---+---+---+---+---+ + * | 3 | Type | + * +---------------+---+---+---+---+---+---+---+---+ + * | 4 | Command | + * +---------------+---+---+---+---+---+---+---+---+ + * | 5 | Reserved0 | + * +---------------+---+---+---+---+---+---+---+---+ + * | 6 | Reserved1 | + * +---------------+---+---+---+---+---+---+---+---+ + * | 7 | Reserved2 | + * +---------------+---+---+---+---+---+---+---+---+ + * | 8 | Reserved3 | + * +---------------+---+---+---+---+---+---+---+---+ + * | 9 | Reserved4 | + * +---------------+---+---+---+---+---+---+---+---+ + * | 10 | DATA 0 | + * +---------------+---+---+---+---+---+---+---+---+ + * : : : : : : : : : : : : : + * +---------------+---+---+---+---+---+---+---+---+ + * | N + 10 - 1 | DATA N-1 | + * +---------------+---+---+---+---+---+---+---+---+ + * + * +----------+------------+------------------------------------------------+ + * | Field | Byte | | + * +----------+------------+------------------------------------------------+ + * | Category | 0 | The destination category. | + * +----------+------------+------------------------------------------------+ + * | Version | 1 ~ 2 | The category version of the sender of the | + * | | | packet. | + * | | | The first byte represent the major version of | + * | | | the packet.The second byte represent the minor | + * | | | version of the packet. | + * +----------+------------+------------------------------------------------+ + * | Type | 3 | The message type of current message packet. | + * +----------+------------+------------------------------------------------+ + * | Command | 4 | The command byte sent to remote processor/SoC. | + * +----------+------------+------------------------------------------------+ + * | Reserved | 5 ~ 9 | Reserved field for future extension. | + * +----------+------------+------------------------------------------------+ + * | Data | N | The data payload of the message packet. | + * +----------+------------+------------------------------------------------+ + * + * Audio control: + * SRTM Audio Control Category Request Command Table: + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | Category | Version | Type | Command | Data | Function | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x00 | Data[0]: Audio Device Index | Open a TX Instance. | + * | | | | | Data[1]: format | | + * | | | | | Data[2]: channels | | + * | | | | | Data[3-6]: samplerate | | + * | | | | | Data[7-10]: buffer_addr | | + * | | | | | Data[11-14]: buffer_size | | + * | | | | | Data[15-18]: period_size | | + * | | | | | Data[19-22]: buffer_tail | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x01 | Data[0]: Audio Device Index | Start a TX Instance. | + * | | | | | Same as above command | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x02 | Data[0]: Audio Device Index | Pause a TX Instance. | + * | | | | | Same as above command | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x03 | Data[0]: Audio Device Index | Resume a TX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x04 | Data[0]: Audio Device Index | Stop a TX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x05 | Data[0]: Audio Device Index | Close a TX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x06 | Data[0]: Audio Device Index | Set Parameters for | + * | | | | | Data[1]: format | a TX Instance. | + * | | | | | Data[2]: channels | | + * | | | | | Data[3-6]: samplerate | | + * | | | | | Data[7-22]: reserved | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x07 | Data[0]: Audio Device Index | Set TX Buffer. | + * | | | | | Data[1-6]: reserved | | + * | | | | | Data[7-10]: buffer_addr | | + * | | | | | Data[11-14]: buffer_size | | + * | | | | | Data[15-18]: period_size | | + * | | | | | Data[19-22]: buffer_tail | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x08 | Data[0]: Audio Device Index | Suspend a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x09 | Data[0]: Audio Device Index | Resume a TX Instance. | + * | | | | | Data[1]: format | | + * | | | | | Data[2]: channels | | + * | | | | | Data[3-6]: samplerate | | + * | | | | | Data[7-10]: buffer_addr | | + * | | | | | Data[11-14]: buffer_size | | + * | | | | | Data[15-18]: period_size | | + * | | | | | Data[19-22]: buffer_tail | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x0A | Data[0]: Audio Device Index | Open a RX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x0B | Data[0]: Audio Device Index | Start a RX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x0C | Data[0]: Audio Device Index | Pause a RX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x0D | Data[0]: Audio Device Index | Resume a RX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x0E | Data[0]: Audio Device Index | Stop a RX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x0F | Data[0]: Audio Device Index | Close a RX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x10 | Data[0]: Audio Device Index | Set Parameters for | + * | | | | | Data[1]: format | a RX Instance. | + * | | | | | Data[2]: channels | | + * | | | | | Data[3-6]: samplerate | | + * | | | | | Data[7-22]: reserved | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x11 | Data[0]: Audio Device Index | Set RX Buffer. | + * | | | | | Data[1-6]: reserved | | + * | | | | | Data[7-10]: buffer_addr | | + * | | | | | Data[11-14]: buffer_size | | + * | | | | | Data[15-18]: period_size | | + * | | | | | Data[19-22]: buffer_tail | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x12 | Data[0]: Audio Device Index | Suspend a RX Instance.| + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x13 | Data[0]: Audio Device Index | Resume a RX Instance. | + * | | | | | Data[1]: format | | + * | | | | | Data[2]: channels | | + * | | | | | Data[3-6]: samplerate | | + * | | | | | Data[7-10]: buffer_addr | | + * | | | | | Data[11-14]: buffer_size | | + * | | | | | Data[15-18]: period_size | | + * | | | | | Data[19-22]: buffer_tail | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x14 | Data[0]: Audio Device Index | Set register value | + * | | | | | Data[1-6]: reserved | to codec | + * | | | | | Data[7-10]: register | | + * | | | | | Data[11-14]: value | | + * | | | | | Data[15-22]: reserved | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x00 | 0x15 | Data[0]: Audio Device Index | Get register value | + * | | | | | Data[1-6]: reserved | from codec | + * | | | | | Data[7-10]: register | | + * | | | | | Data[11-22]: reserved | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * Note 1: See for available value of + * Sample Format; + * Note 2: See for available value of Channels; + * Note 3: Sample Rate of Set Parameters for an Audio TX Instance + * Command and Set Parameters for an Audio RX Instance Command is + * in little-endian format. + * + * SRTM Audio Control Category Response Command Table: + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | Category | Version | Type | Command | Data | Function | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x00 | Data[0]: Audio Device Index | Reply for Open | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x01 | Data[0]: Audio Device Index | Reply for Start | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x02 | Data[0]: Audio Device Index | Reply for Pause | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x03 | Data[0]: Audio Device Index | Reply for Resume | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x04 | Data[0]: Audio Device Index | Reply for Stop | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x05 | Data[0]: Audio Device Index | Reply for Close | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x06 | Data[0]: Audio Device Index | Reply for Set Param | + * | | | | | Data[1]: Return code | for a TX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x07 | Data[0]: Audio Device Index | Reply for Set | + * | | | | | Data[1]: Return code | TX Buffer | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x08 | Data[0]: Audio Device Index | Reply for Suspend | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x09 | Data[0]: Audio Device Index | Reply for Resume | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x0A | Data[0]: Audio Device Index | Reply for Open | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x0B | Data[0]: Audio Device Index | Reply for Start | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x0C | Data[0]: Audio Device Index | Reply for Pause | + * | | | | | Data[1]: Return code | a TX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x0D | Data[0]: Audio Device Index | Reply for Resume | + * | | | | | Data[1]: Return code | a RX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x0E | Data[0]: Audio Device Index | Reply for Stop | + * | | | | | Data[1]: Return code | a RX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x0F | Data[0]: Audio Device Index | Reply for Close | + * | | | | | Data[1]: Return code | a RX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x10 | Data[0]: Audio Device Index | Reply for Set Param | + * | | | | | Data[1]: Return code | for a RX Instance. | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x11 | Data[0]: Audio Device Index | Reply for Set | + * | | | | | Data[1]: Return code | RX Buffer | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x12 | Data[0]: Audio Device Index | Reply for Suspend | + * | | | | | Data[1]: Return code | a RX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x13 | Data[0]: Audio Device Index | Reply for Resume | + * | | | | | Data[1]: Return code | a RX Instance | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x14 | Data[0]: Audio Device Index | Reply for Set codec | + * | | | | | Data[1]: Return code | register value | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x01 | 0x15 | Data[0]: Audio Device Index | Reply for Get codec | + * | | | | | Data[1]: Return code | register value | + * | | | | | Data[2-6]: reserved | | + * | | | | | Data[7-10]: register | | + * | | | | | Data[11-14]: value | | + * | | | | | Data[15-22]: reserved | | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * + * SRTM Audio Control Category Notification Command Table: + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | Category | Version | Type | Command | Data | Function | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x02 | 0x00 | Data[0]: Audio Device Index | Notify one TX period | + * | | | | | | is finished | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * | 0x03 | 0x0100 | 0x02 | 0x01 | Data[0]: Audio Device Index | Notify one RX period | + * | | | | | | is finished | + * +----------+---------+------+---------+-------------------------------+-----------------------+ + * + * List of Sample Format: + * +------------------+-----------------------+ + * | Sample Format | Description | + * +------------------+-----------------------+ + * | 0x0 | S16_LE | + * +------------------+-----------------------+ + * | 0x1 | S24_LE | + * +------------------+-----------------------+ + * + * List of Audio Channels + * +------------------+-----------------------+ + * | Audio Channel | Description | + * +------------------+-----------------------+ + * | 0x0 | Left Channel | + * +------------------+-----------------------+ + * | 0x1 | Right Channel | + * +------------------+---------------- ------+ + * | 0x2 | Left & Right Channel | + * +------------------+-----------------------+ + * + */ + +#ifndef _IMX_PCM_RPMSG_H +#define _IMX_PCM_RPMSG_H + +#include +#include +#include + +#define RPMSG_TIMEOUT 1000 + +/* RPMSG Command (TYPE A)*/ +#define TX_OPEN 0x0 +#define TX_START 0x1 +#define TX_PAUSE 0x2 +#define TX_RESTART 0x3 +#define TX_TERMINATE 0x4 +#define TX_CLOSE 0x5 +#define TX_HW_PARAM 0x6 +#define TX_BUFFER 0x7 +#define TX_SUSPEND 0x8 +#define TX_RESUME 0x9 + +#define RX_OPEN 0xA +#define RX_START 0xB +#define RX_PAUSE 0xC +#define RX_RESTART 0xD +#define RX_TERMINATE 0xE +#define RX_CLOSE 0xF +#define RX_HW_PARAM 0x10 +#define RX_BUFFER 0x11 +#define RX_SUSPEND 0x12 +#define RX_RESUME 0x13 +#define SET_CODEC_VALUE 0x14 +#define GET_CODEC_VALUE 0x15 +#define TX_POINTER 0x16 +#define RX_POINTER 0x17 +/* Total msg numver for type A */ +#define MSG_TYPE_A_NUM 0x18 + +/* RPMSG Command (TYPE C)*/ +#define TX_PERIOD_DONE 0x0 +#define RX_PERIOD_DONE 0x1 +/* Total msg numver for type C */ +#define MSG_TYPE_C_NUM 0x2 + +#define MSG_MAX_NUM (MSG_TYPE_A_NUM + MSG_TYPE_C_NUM) + +#define MSG_TYPE_A 0x0 +#define MSG_TYPE_B 0x1 +#define MSG_TYPE_C 0x2 + +#define RESP_NONE 0x0 +#define RESP_NOT_ALLOWED 0x1 +#define RESP_SUCCESS 0x2 +#define RESP_FAILED 0x3 + +#define RPMSG_S16_LE 0x0 +#define RPMSG_S24_LE 0x1 +#define RPMSG_S32_LE 0x2 +#define RPMSG_DSD_U16_LE 0x3 +#define RPMSG_DSD_U24_LE 0x4 +#define RPMSG_DSD_U32_LE 0x5 + +#define RPMSG_CH_LEFT 0x0 +#define RPMSG_CH_RIGHT 0x1 +#define RPMSG_CH_STEREO 0x2 + +#define WORK_MAX_NUM 0x30 + +/* Category define */ +#define IMX_RMPSG_LIFECYCLE 1 +#define IMX_RPMSG_PMIC 2 +#define IMX_RPMSG_AUDIO 3 +#define IMX_RPMSG_KEY 4 +#define IMX_RPMSG_GPIO 5 +#define IMX_RPMSG_RTC 6 +#define IMX_RPMSG_SENSOR 7 + +/* rpmsg version */ +#define IMX_RMPSG_MAJOR 1 +#define IMX_RMPSG_MINOR 0 + +#define TX SNDRV_PCM_STREAM_PLAYBACK +#define RX SNDRV_PCM_STREAM_CAPTURE + +/** + * struct rpmsg_head: rpmsg header structure + * + * @cate: category + * @major: major version + * @minor: minor version + * @type: message type (A/B/C) + * @cmd: message command + * @reserved: reserved space + */ +struct rpmsg_head { + u8 cate; + u8 major; + u8 minor; + u8 type; + u8 cmd; + u8 reserved[5]; +} __packed; + +/** + * struct param_s: sent rpmsg parameter + * + * @audioindex: audio instance index + * @format: audio format + * @channels: audio channel number + * @rate: sample rate + * @buffer_addr: dma buffer physical address or register for SET_CODEC_VALUE + * @buffer_size: dma buffer size or register value for SET_CODEC_VALUE + * @period_size: period size + * @buffer_tail: current period index + */ +struct param_s { + unsigned char audioindex; + unsigned char format; + unsigned char channels; + unsigned int rate; + unsigned int buffer_addr; + unsigned int buffer_size; + unsigned int period_size; + unsigned int buffer_tail; +} __packed; + +/** + * struct param_s: send rpmsg parameter + * + * @audioindex: audio instance index + * @resp: response value + * @reserved1: reserved space + * @buffer_offset: the consumed offset of buffer + * @reg_addr: register addr of codec + * @reg_data: register value of codec + * @reserved2: reserved space + * @buffer_tail: current period index + */ +struct param_r { + unsigned char audioindex; + unsigned char resp; + unsigned char reserved1[1]; + unsigned int buffer_offset; + unsigned int reg_addr; + unsigned int reg_data; + unsigned char reserved2[4]; + unsigned int buffer_tail; +} __packed; + +/* Struct of sent message */ +struct rpmsg_s_msg { + struct rpmsg_head header; + struct param_s param; +}; + +/* Struct of received message */ +struct rpmsg_r_msg { + struct rpmsg_head header; + struct param_r param; +}; + +/* Struct of rpmsg */ +struct rpmsg_msg { + struct rpmsg_s_msg s_msg; + struct rpmsg_r_msg r_msg; +}; + +/* Struct of rpmsg for workqueue */ +struct work_of_rpmsg { + struct rpmsg_info *info; + /* Sent msg for each work */ + struct rpmsg_msg msg; + struct work_struct work; +}; + +/* Struct of timer */ +struct stream_timer { + struct timer_list timer; + struct rpmsg_info *info; + struct snd_pcm_substream *substream; +}; + +typedef void (*dma_callback)(void *arg); + +/** + * struct rpmsg_info: rpmsg audio information + * + * @rpdev: pointer of rpmsg_device + * @dev: pointer for imx_pcm_rpmsg device + * @cmd_complete: command is finished + * @pm_qos_req: request of pm qos + * @r_msg: received rpmsg + * @msg: array of rpmsg + * @notify: notification msg (type C) for TX & RX + * @notify_updated: notification flag for TX & RX + * @rpmsg_wq: rpmsg workqueue + * @work_list: array of work list for workqueue + * @work_write_index: write index of work list + * @work_read_index: read index of work list + * @msg_drop_count: counter of dropped msg for TX & RX + * @num_period: period number for TX & RX + * @callback_param: parameter for period elapse callback for TX & RX + * @callback: period elapse callback for TX & RX + * @send_message: function pointer for send message + * @lock: spin lock for TX & RX + * @wq_lock: lock for work queue + * @msg_lock: lock for send message + * @stream_timer: timer for tigger workqueue + */ +struct rpmsg_info { + struct rpmsg_device *rpdev; + struct device *dev; + struct completion cmd_complete; + struct pm_qos_request pm_qos_req; + + /* Received msg (global) */ + struct rpmsg_r_msg r_msg; + struct rpmsg_msg msg[MSG_MAX_NUM]; + /* period done */ + struct rpmsg_msg notify[2]; + bool notify_updated[2]; + + struct workqueue_struct *rpmsg_wq; + struct work_of_rpmsg work_list[WORK_MAX_NUM]; + int work_write_index; + int work_read_index; + int msg_drop_count[2]; + int num_period[2]; + void *callback_param[2]; + dma_callback callback[2]; + int (*send_message)(struct rpmsg_msg *msg, struct rpmsg_info *info); + spinlock_t lock[2]; /* spin lock for resource protection */ + spinlock_t wq_lock; /* spin lock for resource protection */ + struct mutex msg_lock; /* mutex for resource protection */ + struct stream_timer stream_timer[2]; +}; + +#define IMX_PCM_DRV_NAME "imx_pcm_rpmsg" + +#endif /* IMX_PCM_RPMSG_H */ From 39f8405c3e502e7b9d0533fa0b0bfe715b3e89c1 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Fri, 12 Mar 2021 10:38:45 +0800 Subject: [PATCH 0393/1091] ASoC: imx-rpmsg: Add machine driver for audio base on rpmsg The platform device is not registered by device tree or cpu dai driver, it is registered by the rpmsg channel, So add a dedicated machine driver to handle this case. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615516725-4975-7-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 11 +++ sound/soc/fsl/Makefile | 2 + sound/soc/fsl/imx-rpmsg.c | 150 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 sound/soc/fsl/imx-rpmsg.c diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index 3d3d14f3793e..c71c6024320b 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -337,6 +337,17 @@ config SND_SOC_IMX_HDMI Say Y if you want to add support for SoC audio on an i.MX board with IMX HDMI. +config SND_SOC_IMX_RPMSG + tristate "SoC Audio support for i.MX boards with rpmsg" + depends on RPMSG + select SND_SOC_IMX_PCM_RPMSG + select SND_SOC_IMX_AUDIO_RPMSG + help + SoC Audio support for i.MX boards with rpmsg. + There should be rpmsg devices defined in other core (M core) + Say Y if you want to add support for SoC audio on an i.MX board with + a rpmsg devices. + endif # SND_IMX_SOC endmenu diff --git a/sound/soc/fsl/Makefile b/sound/soc/fsl/Makefile index ce4f4324c3a2..f146ce464acd 100644 --- a/sound/soc/fsl/Makefile +++ b/sound/soc/fsl/Makefile @@ -70,6 +70,7 @@ snd-soc-imx-sgtl5000-objs := imx-sgtl5000.o 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 obj-$(CONFIG_SND_SOC_EUKREA_TLV320) += snd-soc-eukrea-tlv320.o obj-$(CONFIG_SND_SOC_IMX_ES8328) += snd-soc-imx-es8328.o @@ -77,3 +78,4 @@ obj-$(CONFIG_SND_SOC_IMX_SGTL5000) += snd-soc-imx-sgtl5000.o 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 diff --git a/sound/soc/fsl/imx-rpmsg.c b/sound/soc/fsl/imx-rpmsg.c new file mode 100644 index 000000000000..5a9a470d203f --- /dev/null +++ b/sound/soc/fsl/imx-rpmsg.c @@ -0,0 +1,150 @@ +// SPDX-License-Identifier: GPL-2.0+ +// Copyright 2017-2020 NXP + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "imx-pcm-rpmsg.h" + +struct imx_rpmsg { + struct snd_soc_dai_link dai; + struct snd_soc_card card; +}; + +static const struct snd_soc_dapm_widget imx_rpmsg_dapm_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_SPK("Ext Spk", NULL), + SND_SOC_DAPM_MIC("Mic Jack", NULL), + SND_SOC_DAPM_MIC("Main MIC", NULL), +}; + +static int imx_rpmsg_probe(struct platform_device *pdev) +{ + struct snd_soc_dai_link_component *dlc; + struct device *dev = pdev->dev.parent; + /* rpmsg_pdev is the platform device for the rpmsg node that probed us */ + struct platform_device *rpmsg_pdev = to_platform_device(dev); + struct device_node *np = rpmsg_pdev->dev.of_node; + struct of_phandle_args args; + struct imx_rpmsg *data; + int ret = 0; + + dlc = devm_kzalloc(&pdev->dev, 3 * sizeof(*dlc), GFP_KERNEL); + if (!dlc) + return -ENOMEM; + + data = devm_kzalloc(&pdev->dev, sizeof(*data), GFP_KERNEL); + if (!data) { + ret = -ENOMEM; + goto fail; + } + + ret = of_reserved_mem_device_init_by_idx(&pdev->dev, np, 0); + if (ret) + dev_warn(&pdev->dev, "no reserved DMA memory\n"); + + data->dai.cpus = &dlc[0]; + data->dai.num_cpus = 1; + data->dai.platforms = &dlc[1]; + data->dai.num_platforms = 1; + data->dai.codecs = &dlc[2]; + data->dai.num_codecs = 1; + + data->dai.name = "rpmsg hifi"; + data->dai.stream_name = "rpmsg hifi"; + data->dai.dai_fmt = SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | + SND_SOC_DAIFMT_CBS_CFS; + + /* Optional codec node */ + ret = of_parse_phandle_with_fixed_args(np, "audio-codec", 0, 0, &args); + if (ret) { + data->dai.codecs->dai_name = "snd-soc-dummy-dai"; + data->dai.codecs->name = "snd-soc-dummy"; + } else { + data->dai.codecs->of_node = args.np; + ret = snd_soc_get_dai_name(&args, &data->dai.codecs->dai_name); + if (ret) { + dev_err(&pdev->dev, "Unable to get codec_dai_name\n"); + goto fail; + } + } + + data->dai.cpus->dai_name = dev_name(&rpmsg_pdev->dev); + data->dai.platforms->name = IMX_PCM_DRV_NAME; + data->dai.playback_only = true; + data->dai.capture_only = true; + data->card.num_links = 1; + data->card.dai_link = &data->dai; + + if (of_property_read_bool(np, "fsl,rpmsg-out")) + data->dai.capture_only = false; + + if (of_property_read_bool(np, "fsl,rpmsg-in")) + data->dai.playback_only = false; + + if (data->dai.playback_only && data->dai.capture_only) { + dev_err(&pdev->dev, "no enabled rpmsg DAI link\n"); + ret = -EINVAL; + goto fail; + } + + data->card.dev = &pdev->dev; + data->card.owner = THIS_MODULE; + data->card.dapm_widgets = imx_rpmsg_dapm_widgets; + data->card.num_dapm_widgets = ARRAY_SIZE(imx_rpmsg_dapm_widgets); + /* + * Inoder to use common api to get card name and audio routing. + * Use parent of_node for this device, revert it after finishing using + */ + data->card.dev->of_node = np; + + ret = snd_soc_of_parse_card_name(&data->card, "model"); + if (ret) + goto fail; + + if (of_property_read_bool(np, "audio-routing")) { + ret = snd_soc_of_parse_audio_routing(&data->card, "audio-routing"); + if (ret) { + dev_err(&pdev->dev, "failed to parse audio-routing: %d\n", ret); + goto fail; + } + } + + platform_set_drvdata(pdev, &data->card); + snd_soc_card_set_drvdata(&data->card, data); + ret = devm_snd_soc_register_card(&pdev->dev, &data->card); + if (ret) { + dev_err(&pdev->dev, "snd_soc_register_card failed (%d)\n", ret); + goto fail; + } + +fail: + pdev->dev.of_node = NULL; + return ret; +} + +static struct platform_driver imx_rpmsg_driver = { + .driver = { + .name = "imx-audio-rpmsg", + .owner = THIS_MODULE, + .pm = &snd_soc_pm_ops, + }, + .probe = imx_rpmsg_probe, +}; +module_platform_driver(imx_rpmsg_driver); + +MODULE_DESCRIPTION("Freescale SoC Audio RPMSG Machine Driver"); +MODULE_AUTHOR("Shengjiu Wang "); +MODULE_ALIAS("platform:imx-audio-rpmsg"); +MODULE_LICENSE("GPL v2"); From 4da40cb9955c63c3aca02be267faea4abbd2c649 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Mar 2021 11:48:15 +0900 Subject: [PATCH 0394/1091] ASoC: soc.h: add asoc_link_to_cpu/codec/platform() macro We shouldn't use dai_link->cpus/codecs/platforms directly, because these are array now to supporting multi CPU/Codec/Platform. This patch adds asoc_link_to_xxx() macro for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/874kh3aopc.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 24 +++++++++++++++++++++--- 1 file changed, 21 insertions(+), 3 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index 78609ab331c8..e4161071f300 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -716,20 +716,38 @@ struct snd_soc_dai_link { struct snd_soc_dobj dobj; /* For topology */ #endif }; + +static inline struct snd_soc_dai_link_component* +asoc_link_to_cpu(struct snd_soc_dai_link *link, int n) { + return &(link)->cpus[n]; +} + +static inline struct snd_soc_dai_link_component* +asoc_link_to_codec(struct snd_soc_dai_link *link, int n) { + return &(link)->codecs[n]; +} + +static inline struct snd_soc_dai_link_component* +asoc_link_to_platform(struct snd_soc_dai_link *link, int n) { + return &(link)->platforms[n]; +} + #define for_each_link_codecs(link, i, codec) \ for ((i) = 0; \ - ((i) < link->num_codecs) && ((codec) = &link->codecs[i]); \ + ((i) < link->num_codecs) && \ + ((codec) = asoc_link_to_codec(link, i)); \ (i)++) #define for_each_link_platforms(link, i, platform) \ for ((i) = 0; \ ((i) < link->num_platforms) && \ - ((platform) = &link->platforms[i]); \ + ((platform) = asoc_link_to_platform(link, i)); \ (i)++) #define for_each_link_cpus(link, i, cpu) \ for ((i) = 0; \ - ((i) < link->num_cpus) && ((cpu) = &link->cpus[i]); \ + ((i) < link->num_cpus) && \ + ((cpu) = asoc_link_to_cpu(link, i)); \ (i)++) /* From 4a50724eb0ba96b849f4a0c8da28b2b796859f9e Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Mar 2021 11:48:40 +0900 Subject: [PATCH 0395/1091] ASoC: soc.h: fixup return timing for snd_soc_fixup_dai_links_platform_name() Current snd_soc_fixup_dai_links_platform_name() creates name first (A), and checks setup target pointer (B), and set it (C). We should check target pointer first IMO. This patch exchange the order to (B) -> (A) -> (C). int snd_soc_fixup_dai_links_platform_name(...) { ... /* set platform name for each dailink */ for_each_card_prelinks(card, i, dai_link) { (A) name = devm_kstrdup(...); if (!name) return -ENOMEM; (B) if (!dai_link->platforms) return -EINVAL; /* only single platform is supported for now */ (C) dai_link->platforms->name = name; } return 0; } Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8735wnaoon.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/sound/soc.h b/include/sound/soc.h index e4161071f300..200815ca4112 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1280,13 +1280,13 @@ int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, /* set platform name for each dailink */ for_each_card_prelinks(card, i, dai_link) { + if (!dai_link->platforms) + return -EINVAL; + name = devm_kstrdup(card->dev, platform_name, GFP_KERNEL); if (!name) return -ENOMEM; - if (!dai_link->platforms) - return -EINVAL; - /* only single platform is supported for now */ dai_link->platforms->name = name; } From d908b922c71791568384336ccc3d12a8cbcd1777 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 22 Mar 2021 11:48:54 +0900 Subject: [PATCH 0396/1091] ASoC: soc.h: return error if multi platform at snd_soc_fixup_dai_links_platform_name() snd_soc_fixup_dai_links_platform_name() is assuming it is single platform. return error if multi platforms. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/871rc7aoo9.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sound/soc.h b/include/sound/soc.h index 200815ca4112..e746da996351 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -1280,6 +1280,10 @@ int snd_soc_fixup_dai_links_platform_name(struct snd_soc_card *card, /* set platform name for each dailink */ for_each_card_prelinks(card, i, dai_link) { + /* only single platform is supported for now */ + if (dai_link->num_platforms != 1) + return -EINVAL; + if (!dai_link->platforms) return -EINVAL; From 200d925e236f1a839bd52680f13649b23f727d51 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Mon, 22 Mar 2021 11:57:56 +0800 Subject: [PATCH 0397/1091] spi: imx: Use of_device_get_match_data() helper Use the of_device_get_match_data() helper instead of open coding. Signed-off-by: Tian Tao Link: https://lore.kernel.org/r/1616385476-53327-1-git-send-email-tiantao6@hisilicon.com Signed-off-by: Mark Brown --- drivers/spi/spi-imx.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c index 5dc4ea4b4450..916580740e77 100644 --- a/drivers/spi/spi-imx.c +++ b/drivers/spi/spi-imx.c @@ -1548,13 +1548,12 @@ static int spi_imx_slave_abort(struct spi_master *master) static int spi_imx_probe(struct platform_device *pdev) { struct device_node *np = pdev->dev.of_node; - const struct of_device_id *of_id = - of_match_device(spi_imx_dt_ids, &pdev->dev); struct spi_master *master; struct spi_imx_data *spi_imx; struct resource *res; int ret, irq, spi_drctl; - const struct spi_imx_devtype_data *devtype_data = of_id->data; + const struct spi_imx_devtype_data *devtype_data = + of_device_get_match_data(&pdev->dev); bool slave_mode; u32 val; From 9f44673b7af2e776b55b1d15b3a35d8e8eb51331 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 22 Mar 2021 13:50:53 +0800 Subject: [PATCH 0398/1091] ASoC: rt1015: Add bclk detection and dc detection Add bclk detection and dc detection before playback. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20210322055053.31797-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015.c | 18 +++++++++++++++++- sound/soc/codecs/rt1015.h | 10 ++++++++++ 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1015.c b/sound/soc/codecs/rt1015.c index 10a7b7745f4b..9238f12999aa 100644 --- a/sound/soc/codecs/rt1015.c +++ b/sound/soc/codecs/rt1015.c @@ -669,8 +669,23 @@ static int rt1015_amp_drv_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt1015_priv *rt1015 = snd_soc_component_get_drvdata(component); + unsigned int ret, ret2; switch (event) { + case SND_SOC_DAPM_PRE_PMU: + ret = snd_soc_component_read(component, RT1015_CLK_DET); + ret2 = snd_soc_component_read(component, RT1015_SPK_DC_DETECT1); + if (!((ret >> 15) & 0x1)) { + snd_soc_component_update_bits(component, RT1015_CLK_DET, + RT1015_EN_BCLK_DET_MASK, RT1015_EN_BCLK_DET); + dev_dbg(component->dev, "BCLK Detection Enabled.\n"); + } + if (!((ret2 >> 12) & 0x1)) { + snd_soc_component_update_bits(component, RT1015_SPK_DC_DETECT1, + RT1015_EN_CLA_D_DC_DET_MASK, RT1015_EN_CLA_D_DC_DET); + dev_dbg(component->dev, "Class-D DC Detection Enabled.\n"); + } + break; case SND_SOC_DAPM_POST_PMU: if (rt1015->hw_config == RT1015_HW_28) schedule_delayed_work(&rt1015->flush_work, msecs_to_jiffies(10)); @@ -690,7 +705,8 @@ static const struct snd_soc_dapm_widget rt1015_dapm_widgets[] = { r1015_dac_event, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU | SND_SOC_DAPM_POST_PMD), SND_SOC_DAPM_OUT_DRV_E("Amp Drv", SND_SOC_NOPM, 0, 0, NULL, 0, - rt1015_amp_drv_event, SND_SOC_DAPM_POST_PMU), + rt1015_amp_drv_event, SND_SOC_DAPM_PRE_PMU | + SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_OUTPUT("SPO"), }; diff --git a/sound/soc/codecs/rt1015.h b/sound/soc/codecs/rt1015.h index 2aeaf65ba793..14344532048e 100644 --- a/sound/soc/codecs/rt1015.h +++ b/sound/soc/codecs/rt1015.h @@ -209,6 +209,11 @@ #define RT1015_PLL_K_MASK (RT1015_PLL_K_MAX) #define RT1015_PLL_K_SFT 0 +/* 0x0020 */ +#define RT1015_EN_BCLK_DET_MASK (0x1 << 15) +#define RT1015_EN_BCLK_DET (0x1 << 15) +#define RT1015_DIS_BCLK_DET (0x0 << 15) + /* 0x007a */ #define RT1015_ID_MASK 0xff #define RT1015_ID_VERA 0x0 @@ -374,6 +379,11 @@ #define RT1015_PWR_SWR (0x1 << 12) #define RT1015_PWR_SWR_BIT 12 +/* 0x0519 */ +#define RT1015_EN_CLA_D_DC_DET_MASK (0x1 << 12) +#define RT1015_EN_CLA_D_DC_DET (0x1 << 12) +#define RT1015_DIS_CLA_D_DC_DET (0x0 << 12) + /* 0x1300 */ #define RT1015_PWR_CLSD (0x1 << 12) #define RT1015_PWR_CLSD_BIT 12 From 7a0d884986f3693aca8a2dc4e1b31d35c508542e Mon Sep 17 00:00:00 2001 From: Ryan Lee Date: Wed, 24 Mar 2021 20:35:55 -0700 Subject: [PATCH 0399/1091] ASoC: max98373: Added controls for autorestart config 3 new controls are added. "OVC Autorestart Switch" : controls whether or not the speaker amplifier automatically re-enables after an overcurrent fault condition. "THERM Autorestart Switch" : controls whether or not the device automatically resumes playback when the die temperature recovers from thermal shutdown. "CMON Autorestart Switch" : controls whether or not the device automatically resumes playback when the clock returns after stopping. Above Auto Restart functions are enabled by default. Signed-off-by: Ryan Lee Link: https://lore.kernel.org/r/20210325033555.29377-3-ryans.lee@maximintegrated.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98373.c | 14 ++++++++++++++ sound/soc/codecs/max98373.h | 3 +++ 2 files changed, 17 insertions(+) diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 746c829312b8..b1e43c26dd6b 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -202,6 +202,15 @@ SOC_SINGLE("Ramp Up Switch", MAX98373_R203F_AMP_DSP_CFG, MAX98373_AMP_DSP_CFG_RMP_UP_SHIFT, 1, 0), SOC_SINGLE("Ramp Down Switch", MAX98373_R203F_AMP_DSP_CFG, MAX98373_AMP_DSP_CFG_RMP_DN_SHIFT, 1, 0), +/* Speaker Amplifier Overcurrent Automatic Restart Enable */ +SOC_SINGLE("OVC Autorestart Switch", MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, + MAX98373_OVC_AUTORESTART_SHIFT, 1, 0), +/* Thermal Shutdown Automatic Restart Enable */ +SOC_SINGLE("THERM Autorestart Switch", MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, + MAX98373_THERM_AUTORESTART_SHIFT, 1, 0), +/* Clock Monitor Automatic Restart Enable */ +SOC_SINGLE("CMON Autorestart Switch", MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, + MAX98373_CMON_AUTORESTART_SHIFT, 1, 0), SOC_SINGLE("CLK Monitor Switch", MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, MAX98373_CLOCK_MON_SHIFT, 1, 0), SOC_SINGLE("Dither Switch", MAX98373_R203F_AMP_DSP_CFG, @@ -390,6 +399,11 @@ static int max98373_probe(struct snd_soc_component *component) MAX98373_R2021_PCM_TX_HIZ_EN_2, 1 << (max98373->i_slot - 8), 0); + /* enable auto restart function by default */ + regmap_write(max98373->regmap, + MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG, + 0xF); + /* speaker feedback slot configuration */ regmap_write(max98373->regmap, MAX98373_R2023_PCM_TX_SRC_2, diff --git a/sound/soc/codecs/max98373.h b/sound/soc/codecs/max98373.h index 71f5a5228f34..73a2cf69d84a 100644 --- a/sound/soc/codecs/max98373.h +++ b/sound/soc/codecs/max98373.h @@ -195,6 +195,9 @@ #define MAX98373_LIMITER_EN_SHIFT (0) /* MAX98373_R20FE_DEVICE_AUTO_RESTART_CFG */ +#define MAX98373_OVC_AUTORESTART_SHIFT (3) +#define MAX98373_THERM_AUTORESTART_SHIFT (2) +#define MAX98373_CMON_AUTORESTART_SHIFT (1) #define MAX98373_CLOCK_MON_SHIFT (0) /* MAX98373_R20FF_GLOBAL_SHDN */ From efd0b1660829a987354cea6a446179c7ac7cd0e6 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 17 Mar 2021 21:05:02 +0800 Subject: [PATCH 0400/1091] ASoC: fsl-asoc-card: Add support for WM8958 codec WM8958 codec is used on some i.MX based platform. So add it support in this generic driver. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615986303-27959-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/Kconfig | 2 ++ sound/soc/fsl/fsl-asoc-card.c | 17 +++++++++++++++-- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/sound/soc/fsl/Kconfig b/sound/soc/fsl/Kconfig index d7f30036d434..f4c498f50997 100644 --- a/sound/soc/fsl/Kconfig +++ b/sound/soc/fsl/Kconfig @@ -291,6 +291,8 @@ config SND_SOC_FSL_ASOC_CARD select SND_SOC_FSL_ESAI select SND_SOC_FSL_SAI select SND_SOC_FSL_SSI + select SND_SOC_WM8994 + select MFD_WM8994 help ALSA SoC Audio support with ASRC feature for Freescale SoCs that have ESAI/SAI/SSI and connect with external CODECs such as WM8962, CS42888, diff --git a/sound/soc/fsl/fsl-asoc-card.c b/sound/soc/fsl/fsl-asoc-card.c index f62f81ceab0d..c62bfd1c3ac7 100644 --- a/sound/soc/fsl/fsl-asoc-card.c +++ b/sound/soc/fsl/fsl-asoc-card.c @@ -25,6 +25,7 @@ #include "../codecs/sgtl5000.h" #include "../codecs/wm8962.h" #include "../codecs/wm8960.h" +#include "../codecs/wm8994.h" #define CS427x_SYSCLK_MCLK 0 @@ -37,12 +38,14 @@ /** * struct codec_priv - CODEC private data * @mclk_freq: Clock rate of MCLK + * @free_freq: Clock rate of MCLK for hw_free() * @mclk_id: MCLK (or main clock) id for set_sysclk() * @fll_id: FLL (or secordary clock) id for set_sysclk() * @pll_id: PLL id for set_pll() */ struct codec_priv { unsigned long mclk_freq; + unsigned long free_freq; u32 mclk_id; u32 fll_id; u32 pll_id; @@ -235,10 +238,10 @@ static int fsl_asoc_card_hw_free(struct snd_pcm_substream *substream) priv->streams &= ~BIT(substream->stream); if (!priv->streams && codec_priv->pll_id && codec_priv->fll_id) { - /* Force freq to be 0 to avoid error message in codec */ + /* Force freq to be free_freq to avoid error message in codec */ ret = snd_soc_dai_set_sysclk(asoc_rtd_to_codec(rtd, 0), codec_priv->mclk_id, - 0, + codec_priv->free_freq, SND_SOC_CLOCK_IN); if (ret) { dev_err(dev, "failed to switch away from FLL: %d\n", ret); @@ -665,6 +668,15 @@ static int fsl_asoc_card_probe(struct platform_device *pdev) priv->dai_fmt |= SND_SOC_DAIFMT_CBS_CFS; priv->card.dapm_routes = audio_map_rx; priv->card.num_dapm_routes = ARRAY_SIZE(audio_map_rx); + } else if (of_device_is_compatible(np, "fsl,imx-audio-wm8958")) { + codec_dai_name = "wm8994-aif1"; + priv->dai_fmt |= SND_SOC_DAIFMT_CBM_CFM; + priv->codec_priv.mclk_id = WM8994_FLL_SRC_MCLK1; + priv->codec_priv.fll_id = WM8994_SYSCLK_FLL1; + priv->codec_priv.pll_id = WM8994_FLL1; + priv->codec_priv.free_freq = priv->codec_priv.mclk_freq; + priv->card.dapm_routes = NULL; + priv->card.num_dapm_routes = 0; } else { dev_err(&pdev->dev, "unknown Device Tree compatible\n"); ret = -EINVAL; @@ -882,6 +894,7 @@ static const struct of_device_id fsl_asoc_card_dt_ids[] = { { .compatible = "fsl,imx-audio-mqs", }, { .compatible = "fsl,imx-audio-wm8524", }, { .compatible = "fsl,imx-audio-si476x", }, + { .compatible = "fsl,imx-audio-wm8958", }, {} }; MODULE_DEVICE_TABLE(of, fsl_asoc_card_dt_ids); From df8077c6fe64fe98c1b1c1f9ecf84afc773e726f Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 17 Mar 2021 21:05:03 +0800 Subject: [PATCH 0401/1091] ASoC: bindings: fsl-asoc-card: add compatible string for WM8958 codec The WM8958 codec is used on i.MX7D val board. Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1615986303-27959-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/fsl-asoc-card.txt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt index 90d9e9d81624..23d83fa7609f 100644 --- a/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt +++ b/Documentation/devicetree/bindings/sound/fsl-asoc-card.txt @@ -42,6 +42,8 @@ The compatible list for this generic sound card currently: "fsl,imx-audio-si476x" + "fsl,imx-audio-wm8958" + Required properties: - compatible : Contains one of entries in the compatible list. From 99067c07e8d877035f6249d194a317c78b7d052d Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 3 Mar 2021 11:07:42 +0800 Subject: [PATCH 0402/1091] ASoC: wm8960: Remove bitclk relax condition in wm8960_configure_sysclk The call sequence in wm8960_configure_clocking is ret = wm8960_configure_sysclk(); if (ret >= 0) goto configure_clock; .... ret = wm8960_configure_pll(); configure_clock: ... wm8960_configure_sysclk is called before wm8960_configure_pll, as there is bitclk relax on both functions, so wm8960_configure_sysclk always return success, then wm8960_configure_pll() never be called. With this case: aplay -Dhw:0,0 -d 5 -r 48000 -f S24_LE -c 2 audio48k24b2c.wav the required bitclk is 48000 * 24 * 2 = 2304000, bitclk got from wm8960_configure_sysclk is 3072000, but if go to wm8960_configure_pll. it can get correct bitclk 2304000. So bitclk relax condition should be removed in wm8960_configure_sysclk, then wm8960_configure_pll can be called, and there is also bitclk relax function in wm8960_configure_pll. Fixes: 3c01b9ee2ab9 ("ASoC: codec: wm8960: Relax bit clock computation") Signed-off-by: Shengjiu Wang Signed-off-by: Daniel Baluta Acked-by: Charles Keepax Link: https://lore.kernel.org/r/1614740862-30196-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/wm8960.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/sound/soc/codecs/wm8960.c b/sound/soc/codecs/wm8960.c index df351519a3a6..847ca16b9841 100644 --- a/sound/soc/codecs/wm8960.c +++ b/sound/soc/codecs/wm8960.c @@ -608,10 +608,6 @@ static const int bclk_divs[] = { * - lrclk = sysclk / dac_divs * - 10 * bclk = sysclk / bclk_divs * - * If we cannot find an exact match for (sysclk, lrclk, bclk) - * triplet, we relax the bclk such that bclk is chosen as the - * closest available frequency greater than expected bclk. - * * @wm8960: codec private data * @mclk: MCLK used to derive sysclk * @sysclk_idx: sysclk_divs index for found sysclk @@ -629,7 +625,7 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk, { int sysclk, bclk, lrclk; int i, j, k; - int diff, closest = mclk; + int diff; /* marker for no match */ *bclk_idx = -1; @@ -653,12 +649,6 @@ int wm8960_configure_sysclk(struct wm8960_priv *wm8960, int mclk, *bclk_idx = k; break; } - if (diff > 0 && closest > diff) { - *sysclk_idx = i; - *dac_idx = j; - *bclk_idx = k; - closest = diff; - } } if (k != ARRAY_SIZE(bclk_divs)) break; From 22f8b5df881e9f1302514bbbbbb8649c2051de55 Mon Sep 17 00:00:00 2001 From: Norbert Ciosek Date: Thu, 28 Jan 2021 10:17:02 -0800 Subject: [PATCH 0403/1091] virtchnl: Fix layout of RSS structures Remove padding from RSS structures. Previous layout could lead to unwanted compiler optimizations in loops when iterating over key and lut arrays. Fixes: 65ece6de0114 ("virtchnl: Add missing explicit padding to structures") Signed-off-by: Norbert Ciosek Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- include/linux/avf/virtchnl.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/include/linux/avf/virtchnl.h b/include/linux/avf/virtchnl.h index 40bad71865ea..532bcbfc4716 100644 --- a/include/linux/avf/virtchnl.h +++ b/include/linux/avf/virtchnl.h @@ -476,7 +476,6 @@ struct virtchnl_rss_key { u16 vsi_id; u16 key_len; u8 key[1]; /* RSS hash key, packed bytes */ - u8 pad[1]; }; VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_key); @@ -485,7 +484,6 @@ struct virtchnl_rss_lut { u16 vsi_id; u16 lut_entries; u8 lut[1]; /* RSS lookup table */ - u8 pad[1]; }; VIRTCHNL_CHECK_STRUCT_LEN(6, virtchnl_rss_lut); From 90449e98c265296329446c7abcd2aae3b20c0bc9 Mon Sep 17 00:00:00 2001 From: Mateusz Palczewski Date: Mon, 4 Jan 2021 15:00:02 +0000 Subject: [PATCH 0404/1091] i40e: Added Asym_Pause to supported link modes Add Asym_Pause to supported link modes (it is supported by HW). Lack of Asym_Pause in supported modes can cause several problems, i.e. it won't be possible to turn the autonegotiation on with asymmetric pause settings (i.e. Tx on, Rx off). Fixes: 4e91bcd5d47a ("i40e: Finish implementation of ethtool get settings") Signed-off-by: Dawid Lukwinski Signed-off-by: Mateusz Palczewski Reviewed-by: Aleksandr Loktionov Reviewed-by: Przemyslaw Patynowski Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index c70dec65a572..2c637a5678b3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -1101,6 +1101,7 @@ static int i40e_get_link_ksettings(struct net_device *netdev, /* Set flow control settings */ ethtool_link_ksettings_add_link_mode(ks, supported, Pause); + ethtool_link_ksettings_add_link_mode(ks, supported, Asym_Pause); switch (hw->fc.requested_mode) { case I40E_FC_FULL: From e61c589587c772c5f672b22683c3e0b38be20702 Mon Sep 17 00:00:00 2001 From: Argus Lin Date: Wed, 10 Mar 2021 21:33:05 +0800 Subject: [PATCH 0405/1091] ASoC: mt6359: add ASoC mt6359 ASoC accdet jack document This patch adds MediaTek MT6359 ASoC accdet jack document. Signed-off-by: Argus Lin Link: https://lore.kernel.org/r/1615383186-18500-2-git-send-email-argus.lin@mediatek.com Signed-off-by: Mark Brown --- .../bindings/sound/mt6359-accdet.yaml | 164 ++++++++++++++++++ 1 file changed, 164 insertions(+) create mode 100644 Documentation/devicetree/bindings/sound/mt6359-accdet.yaml diff --git a/Documentation/devicetree/bindings/sound/mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mt6359-accdet.yaml new file mode 100644 index 000000000000..7fb3e8dfb4c5 --- /dev/null +++ b/Documentation/devicetree/bindings/sound/mt6359-accdet.yaml @@ -0,0 +1,164 @@ +# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) +%YAML 1.2 +--- +$id: http://devicetree.org/schemas/sound/mt6359-accdet.yaml# +$schema: http://devicetree.org/meta-schemas/core.yaml# + +title: Mediatek Technologies Inc. MT6359 ASoC accdet jack driver bindings + +maintainers: + - Chipeng Chang + +description: | + This binding describes the Mediatek Technologies MT6359 ASoC + accdet jack driver. + +properties: + mediatek,accdet-name: + maxItems: 1 + description: named as "mt6359-accdet" jack. + + mediatek,mic-vol: + maxItems: 1 + description: | + accdet micbias1 voltage. + + enum: + - 0x00 # 1.7v - micbias1 volage is 1.7v. + - 0x01 # 1.8v - micbias1 volage is 1.8v. + - 0x02 # 1.9v - micbias1 volage is 1.9v. + - 0x03 # 2.0v - micbias1 volage is 2.0v. + - 0x04 # 2.1v - micbias1 volage is 2.1v. + - 0x05 # 2.5v - micbias1 volage is 2.5v. + - 0x06 # 2.6v - micbias1 volage is 2.6v. + - 0x07 # 2.7v - micbias1 volage is 2.7v. + - 0x08 # 2.8v - micbias1 volage is 2.8v. + - 0x09 # 2.85v - micbias1 volage is 2.85v. + + mediatek,mic-mode: + maxItems: 1 + description: | + value as 1, 2, 6 to indicate ACC/DCC mode. default is DCC mode 2. + + enum: + - 0x01 # ACC - ACC mode. + - 0x02 # DCC - low cost without in bias. + - 0x06 # DCC - low cost with in bias. + + mediatek,pwm-deb-setting: + maxItems: 15 + description: | + headset-mode-setting : Indicates customized pwm, debounce setting + accdet pwm_width, pwm_thresh, fall_delay, rise_delay + debounce0, debounce1, debounce3, debounce4 + eint pwm_width, eint pwm_thresh + eint deb(debounce0, debounce1, debounce2, debounce3), inv_debounce. + + mediatek,eint-use-ap: + maxItems: 1 + description: | + indicates to use ap gpio. + + enum: + - 0x00 # MT6359 eint detection mode. + - 0x01 # SoC GPIO detection mode. + + mediatek,eint-detect-mode: + maxItems: 1 + description: | + indicates to use ap gpio. + + enum: + - 0x00 # detection mode with higher detection power. + - 0x01 # detection mode with lower detection power. + - 0x02 # detection mode with sw moisture detection mode. + - 0x03 # detection mode with hw moisture detection mode1. + - 0x04 # detection mode with hw moisture detection mode2. + + mediatek,eint-num: + maxItems: 1 + description: | + incicates pmic eint usage. + + enum: + - 0x0 # PMIC_EINT0 - use pmic eint0 to trigger plug interrupt. + - 0x1 # PMIC_EINT1 - use pmic eint1 to trigger plug interrupt. + - 0x2 # PMIC_BI_EINT - use pmic eint0/1 to trigger plug interrupt. + + mediatek,eint-trig-mode: + maxItems: 1 + description: | + incicates pmic eint trigger mode. + + enum: + - 0x0 # PMIC_GPIO - use pmic gpio to detect plug status. + - 0x1 # PMIC_INVERTER - use pmic inverter to detect plug status. + + mediatek,eint-use-ext-res: + maxItems: 1 + description: | + select HP_EINT pull up resistance, default 0 use internal resistance. + + enum: + - 0x0 # use internal resistor. + - 0x1 # use external resistor. + + mediatek,eint-comp-vth: + maxItems: 1 + description: | + indicates comparator detection voltage. + + enum: + - 0x00 # 2.8v. + - 0x01 # 2.4v. + - 0x02 # 2.0v. + - 0x03 # 0.7v. + + mediatek,key-mode: + maxItems: 1 + description: | + incicates key mode type. + + enum: + - 0x0 # THREE_KEY - support 3-key key mode. + - 0x1 # FOUR_KEY - support 4-key key mode. + - 0x2 # TRI_KEY_CDD - support 3-key google CDD key mode. + + mediatek,three-key-thr: + maxItems: 4 + description: | + 3 key device detection threshold: 0--MD_MAX--UP_MAX--DW_MAX. + + mediatek,tri-key-cdd-thr: + maxItems: 4 + description: | + 3 key CDD device detection threshold: 0--MD_MAX--UP_MAX--DW_MAX. + + mediatek,four-key-thr: + maxItems: 4 + description: | + 4 key device detection threshold: 0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX. + +additionalProperties: false + +examples: + - | + accdet: accdet { + mediatek,accdet-name = "mt6359-accdet"; + mediatek,mic-vol = <8>; + mediatek,mic-mode = <2>; + mediatek,pwm-deb-setting = <0x500 0x500 1 0x1f0 + 0x800 0x800 0x20 0x44 + 0x4 0x1 + 0x5 0x3 0x3 0x5 0xe>; + mediatek,eint-use-ap = <0>; + mediatek,eint-detect-mode = <4>; + mediatek,eint-num = <0>; + mediatek,eint-trig-mode = <1>; + mediatek,eint-use-ext-res = <0>; + mediatek,eint-comp-vth = <2>; + mediatek,key-mode = <0>; + mediatek,three-key-thr = <0 80 220 400>; + status = "okay"; + }; +... From eef07b9e0925e16457ab9444b56a7f93b541aee3 Mon Sep 17 00:00:00 2001 From: Argus Lin Date: Wed, 10 Mar 2021 21:33:06 +0800 Subject: [PATCH 0406/1091] ASoC: mediatek: mt6359: add MT6359 accdet jack driver MT6359 audio codec supports jack detection feature, adds MT6359 accdet driver to support jack plugged detection and key detection. Signed-off-by: Argus Lin Link: https://lore.kernel.org/r/1615383186-18500-3-git-send-email-argus.lin@mediatek.com Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 8 + sound/soc/codecs/Makefile | 2 + sound/soc/codecs/mt6359-accdet.c | 1080 +++++++++++++++++ sound/soc/codecs/mt6359-accdet.h | 128 ++ sound/soc/codecs/mt6359.h | 1858 ++++++++++++++++++++++++++++-- 5 files changed, 2972 insertions(+), 104 deletions(-) create mode 100644 sound/soc/codecs/mt6359-accdet.c create mode 100644 sound/soc/codecs/mt6359-accdet.h diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 4ab34bca71aa..6d9cb00aa3d2 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -1812,6 +1812,14 @@ config SND_SOC_MT6359 Enable support for the platform which uses MT6359 as external codec device. +config SND_SOC_MT6359_ACCDET + tristate "MediaTek MT6359 ACCDET driver" + depends on MTK_PMIC_WRAP + help + ACCDET means Accessory Detection technology, MediaTek develop it + for ASoC codec soc-jack detection mechanism. + Select N if you don't have jack on board. + config SND_SOC_MT6660 tristate "Mediatek MT6660 Speaker Amplifier" depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index a710dfea7876..1d8980be7019 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -136,6 +136,7 @@ snd-soc-msm8916-digital-objs := msm8916-wcd-digital.o snd-soc-mt6351-objs := mt6351.o snd-soc-mt6358-objs := mt6358.o snd-soc-mt6359-objs := mt6359.o +snd-soc-mt6359-accdet-objs := mt6359-accdet.o snd-soc-mt6660-objs := mt6660.o snd-soc-nau8315-objs := nau8315.o snd-soc-nau8540-objs := nau8540.o @@ -454,6 +455,7 @@ obj-$(CONFIG_SND_SOC_MSM8916_WCD_DIGITAL) +=snd-soc-msm8916-digital.o obj-$(CONFIG_SND_SOC_MT6351) += snd-soc-mt6351.o obj-$(CONFIG_SND_SOC_MT6358) += snd-soc-mt6358.o obj-$(CONFIG_SND_SOC_MT6359) += snd-soc-mt6359.o +obj-$(CONFIG_SND_SOC_MT6359_ACCDET) += mt6359-accdet.o obj-$(CONFIG_SND_SOC_MT6660) += snd-soc-mt6660.o obj-$(CONFIG_SND_SOC_NAU8315) += snd-soc-nau8315.o obj-$(CONFIG_SND_SOC_NAU8540) += snd-soc-nau8540.o diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c new file mode 100644 index 000000000000..0bef6eaad5ad --- /dev/null +++ b/sound/soc/codecs/mt6359-accdet.c @@ -0,0 +1,1080 @@ +// SPDX-License-Identifier: GPL-2.0 +// +// mt6359-accdet.c -- ALSA SoC mt6359 accdet driver +// +// Copyright (C) 2021 MediaTek Inc. +// Author: Argus Lin +// + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "mt6359-accdet.h" +#include "mt6359.h" + +/* global variable definitions */ +#define REGISTER_VAL(x) ((x) - 1) + +/* mt6359 accdet capability */ +#define ACCDET_PMIC_EINT_IRQ BIT(0) +#define ACCDET_AP_GPIO_EINT BIT(1) + +#define ACCDET_PMIC_EINT0 BIT(2) +#define ACCDET_PMIC_EINT1 BIT(3) +#define ACCDET_PMIC_BI_EINT BIT(4) + +#define ACCDET_PMIC_GPIO_TRIG_EINT BIT(5) +#define ACCDET_PMIC_INVERTER_TRIG_EINT BIT(6) +#define ACCDET_PMIC_RSV_EINT BIT(7) + +#define ACCDET_THREE_KEY BIT(8) +#define ACCDET_FOUR_KEY BIT(9) +#define ACCDET_TRI_KEY_CDD BIT(10) +#define ACCDET_RSV_KEY BIT(11) + +#define ACCDET_ANALOG_FASTDISCHARGE BIT(12) +#define ACCDET_DIGITAL_FASTDISCHARGE BIT(13) +#define ACCDET_AD_FASTDISCHRAGE BIT(14) + +static struct platform_driver mt6359_accdet_driver; +static const struct snd_soc_component_driver mt6359_accdet_soc_driver; + +/* local function declaration */ +static void accdet_set_debounce(struct mt6359_accdet *priv, int state, + unsigned int debounce); +static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv); +static void config_digital_init_by_mode(struct mt6359_accdet *priv); +static void config_eint_init_by_mode(struct mt6359_accdet *priv); +static inline void mt6359_accdet_init(struct mt6359_accdet *priv); +static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv); +static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv); +static void mt6359_accdet_jack_report(struct mt6359_accdet *priv); +static void recover_eint_analog_setting(struct mt6359_accdet *priv); +static void recover_eint_digital_setting(struct mt6359_accdet *priv); +static void recover_eint_setting(struct mt6359_accdet *priv); + +static unsigned int adjust_eint_analog_setting(struct mt6359_accdet *priv) +{ + if (priv->data->eint_detect_mode == 0x3 || + priv->data->eint_detect_mode == 0x4) { + /* ESD switches off */ + regmap_update_bits(priv->regmap, + RG_ACCDETSPARE_ADDR, 1 << 8, 0); + } + if (priv->data->eint_detect_mode == 0x4) { + if (priv->caps & ACCDET_PMIC_EINT0) { + /* enable RG_EINT0CONFIGACCDET */ + regmap_update_bits(priv->regmap, + RG_EINT0CONFIGACCDET_ADDR, + RG_EINT0CONFIGACCDET_MASK_SFT, + BIT(RG_EINT0CONFIGACCDET_SFT)); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + /* enable RG_EINT1CONFIGACCDET */ + regmap_update_bits(priv->regmap, + RG_EINT1CONFIGACCDET_ADDR, + RG_EINT1CONFIGACCDET_MASK_SFT, + BIT(RG_EINT1CONFIGACCDET_SFT)); + } + if (priv->data->eint_use_ext_res == 0x3 || + priv->data->eint_use_ext_res == 0x4) { + /*select 500k, use internal resistor */ + regmap_update_bits(priv->regmap, + RG_EINT0HIRENB_ADDR, + RG_EINT0HIRENB_MASK_SFT, + BIT(RG_EINT0HIRENB_SFT)); + } + } + return 0; +} + +static unsigned int adjust_eint_digital_setting(struct mt6359_accdet *priv) +{ + if (priv->caps & ACCDET_PMIC_EINT0) { + /* disable inverter */ + regmap_update_bits(priv->regmap, + ACCDET_EINT0_INVERTER_SW_EN_ADDR, + ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, 0); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + /* disable inverter */ + regmap_update_bits(priv->regmap, + ACCDET_EINT1_INVERTER_SW_EN_ADDR, + ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, 0); + } + + if (priv->data->eint_detect_mode == 0x4) { + if (priv->caps & ACCDET_PMIC_EINT0) { + /* set DA stable signal */ + regmap_update_bits(priv->regmap, + ACCDET_DA_STABLE_ADDR, + ACCDET_EINT0_CEN_STABLE_MASK_SFT, 0); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + /* set DA stable signal */ + regmap_update_bits(priv->regmap, + ACCDET_DA_STABLE_ADDR, + ACCDET_EINT1_CEN_STABLE_MASK_SFT, 0); + } + } + return 0; +} + +static unsigned int mt6359_accdet_jd_setting(struct mt6359_accdet *priv) +{ + if (priv->jd_sts == M_PLUG_IN) { + /* adjust digital setting */ + adjust_eint_digital_setting(priv); + /* adjust analog setting */ + adjust_eint_analog_setting(priv); + } else if (priv->jd_sts == M_PLUG_OUT) { + /* set debounce to 1ms */ + accdet_set_debounce(priv, eint_state000, + priv->data->pwm_deb->eint_debounce0); + } else { + dev_dbg(priv->dev, "should not be here %s()\n", __func__); + } + + return 0; +} + +static void recover_eint_analog_setting(struct mt6359_accdet *priv) +{ + if (priv->data->eint_detect_mode == 0x3 || + priv->data->eint_detect_mode == 0x4) { + /* ESD switches on */ + regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, + 1 << 8, 1 << 8); + } + if (priv->data->eint_detect_mode == 0x4) { + if (priv->caps & ACCDET_PMIC_EINT0) { + /* disable RG_EINT0CONFIGACCDET */ + regmap_update_bits(priv->regmap, + RG_EINT0CONFIGACCDET_ADDR, + RG_EINT0CONFIGACCDET_MASK_SFT, 0); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + /* disable RG_EINT1CONFIGACCDET */ + regmap_update_bits(priv->regmap, + RG_EINT1CONFIGACCDET_ADDR, + RG_EINT1CONFIGACCDET_MASK_SFT, 0); + } + regmap_update_bits(priv->regmap, RG_EINT0HIRENB_ADDR, + RG_EINT0HIRENB_MASK_SFT, 0); + } +} + +static void recover_eint_digital_setting(struct mt6359_accdet *priv) +{ + if (priv->caps & ACCDET_PMIC_EINT0) { + regmap_update_bits(priv->regmap, + ACCDET_EINT0_M_SW_EN_ADDR, + ACCDET_EINT0_M_SW_EN_MASK_SFT, 0); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + regmap_update_bits(priv->regmap, + ACCDET_EINT1_M_SW_EN_ADDR, + ACCDET_EINT1_M_SW_EN_MASK_SFT, 0); + } + if (priv->data->eint_detect_mode == 0x4) { + /* enable eint0cen */ + if (priv->caps & ACCDET_PMIC_EINT0) { + /* enable eint0cen */ + regmap_update_bits(priv->regmap, + ACCDET_DA_STABLE_ADDR, + ACCDET_EINT0_CEN_STABLE_MASK_SFT, + BIT(ACCDET_EINT0_CEN_STABLE_SFT)); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + /* enable eint1cen */ + regmap_update_bits(priv->regmap, + ACCDET_DA_STABLE_ADDR, + ACCDET_EINT1_CEN_STABLE_MASK_SFT, + BIT(ACCDET_EINT1_CEN_STABLE_SFT)); + } + } + + if (priv->data->eint_detect_mode != 0x1) { + if (priv->caps & ACCDET_PMIC_EINT0) { + /* enable inverter */ + regmap_update_bits(priv->regmap, + ACCDET_EINT0_INVERTER_SW_EN_ADDR, + ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, + BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT)); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + /* enable inverter */ + regmap_update_bits(priv->regmap, + ACCDET_EINT1_INVERTER_SW_EN_ADDR, + ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, + BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT)); + } + } +} + +static void recover_eint_setting(struct mt6359_accdet *priv) +{ + if (priv->jd_sts == M_PLUG_OUT) { + recover_eint_analog_setting(priv); + recover_eint_digital_setting(priv); + } +} + +static void mt6359_accdet_recover_jd_setting(struct mt6359_accdet *priv) +{ + int ret = 0; + unsigned int value = 0; + + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_IRQ_CLR_MASK_SFT, BIT(ACCDET_IRQ_CLR_SFT)); + usleep_range(200, 300); + ret = regmap_read_poll_timeout(priv->regmap, + ACCDET_IRQ_ADDR, + value, + (value & ACCDET_IRQ_MASK_SFT) == 0, + 0, + 1000); + if (ret) + dev_warn(priv->dev, "%s(), ret %d\n", __func__, ret); + /* clear accdet int, modify for fix interrupt trigger twice error */ + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_IRQ_CLR_MASK_SFT, 0); + regmap_update_bits(priv->regmap, RG_INT_STATUS_ACCDET_ADDR, + RG_INT_STATUS_ACCDET_MASK_SFT, + BIT(RG_INT_STATUS_ACCDET_SFT)); + + /* recover accdet debounce0,3 */ + accdet_set_debounce(priv, accdet_state000, + priv->data->pwm_deb->debounce0); + accdet_set_debounce(priv, accdet_state001, + priv->data->pwm_deb->debounce1); + accdet_set_debounce(priv, accdet_state011, + priv->data->pwm_deb->debounce3); + + priv->jack_type = 0; + priv->btn_type = 0; + priv->accdet_status = 0x3; + mt6359_accdet_jack_report(priv); +} + +static void accdet_set_debounce(struct mt6359_accdet *priv, int state, + unsigned int debounce) +{ + switch (state) { + case accdet_state000: + regmap_write(priv->regmap, ACCDET_DEBOUNCE0_ADDR, debounce); + break; + case accdet_state001: + regmap_write(priv->regmap, ACCDET_DEBOUNCE1_ADDR, debounce); + break; + case accdet_state010: + regmap_write(priv->regmap, ACCDET_DEBOUNCE2_ADDR, debounce); + break; + case accdet_state011: + regmap_write(priv->regmap, ACCDET_DEBOUNCE3_ADDR, debounce); + break; + case accdet_auxadc: + regmap_write(priv->regmap, + ACCDET_CONNECT_AUXADC_TIME_DIG_ADDR, debounce); + break; + case eint_state000: + regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE0_ADDR, + 0xF << ACCDET_EINT_DEBOUNCE0_SFT, + debounce << ACCDET_EINT_DEBOUNCE0_SFT); + break; + case eint_state001: + regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE1_ADDR, + 0xF << ACCDET_EINT_DEBOUNCE1_SFT, + debounce << ACCDET_EINT_DEBOUNCE1_SFT); + break; + case eint_state010: + regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE2_ADDR, + 0xF << ACCDET_EINT_DEBOUNCE2_SFT, + debounce << ACCDET_EINT_DEBOUNCE2_SFT); + break; + case eint_state011: + regmap_update_bits(priv->regmap, ACCDET_EINT_DEBOUNCE3_ADDR, + 0xF << ACCDET_EINT_DEBOUNCE3_SFT, + debounce << ACCDET_EINT_DEBOUNCE3_SFT); + break; + case eint_inverter_state000: + regmap_write(priv->regmap, ACCDET_EINT_INVERTER_DEBOUNCE_ADDR, + debounce); + break; + default: + dev_warn(priv->dev, "Error: %s error state (%d)\n", __func__, + state); + break; + } +} + +static void mt6359_accdet_jack_report(struct mt6359_accdet *priv) +{ + int report = 0; + + if (!priv->jack) + return; + + report = priv->jack_type | priv->btn_type; + snd_soc_jack_report(priv->jack, report, MT6359_ACCDET_JACK_MASK); +} + +static unsigned int check_button(struct mt6359_accdet *priv, unsigned int v) +{ + if (priv->caps & ACCDET_FOUR_KEY) { + if (v < priv->data->four_key.down && + v >= priv->data->four_key.up) + priv->btn_type = SND_JACK_BTN_1; + if (v < priv->data->four_key.up && + v >= priv->data->four_key.voice) + priv->btn_type = SND_JACK_BTN_2; + if (v < priv->data->four_key.voice && + v >= priv->data->four_key.mid) + priv->btn_type = SND_JACK_BTN_3; + if (v < priv->data->four_key.mid) + priv->btn_type = SND_JACK_BTN_0; + } else { + if (v < priv->data->three_key.down && + v >= priv->data->three_key.up) + priv->btn_type = SND_JACK_BTN_1; + if (v < priv->data->three_key.up && + v >= priv->data->three_key.mid) + priv->btn_type = SND_JACK_BTN_2; + if (v < priv->data->three_key.mid) + priv->btn_type = SND_JACK_BTN_0; + } + return 0; +} + +static void is_key_pressed(struct mt6359_accdet *priv, bool pressed) +{ + priv->btn_type = priv->jack_type & ~MT6359_ACCDET_BTN_MASK; + + if (pressed) + check_button(priv, priv->cali_voltage); +} + +static inline void check_jack_btn_type(struct mt6359_accdet *priv) +{ + unsigned int val = 0; + + regmap_read(priv->regmap, ACCDET_MEM_IN_ADDR, &val); + + priv->accdet_status = + (val >> ACCDET_STATE_MEM_IN_OFFSET) & ACCDET_STATE_AB_MASK; + + switch (priv->accdet_status) { + case 0: + if (priv->jack_type == SND_JACK_HEADSET) + is_key_pressed(priv, true); + else + priv->jack_type = SND_JACK_HEADPHONE; + break; + case 1: + if (priv->jack_type == SND_JACK_HEADSET) { + is_key_pressed(priv, false); + } else { + priv->jack_type = SND_JACK_HEADSET; + accdet_set_debounce(priv, eint_state011, 0x1); + } + break; + case 3: + default: + priv->jack_type = 0; + break; + } +} + +static void mt6359_accdet_work(struct work_struct *work) +{ + struct mt6359_accdet *priv = + container_of(work, struct mt6359_accdet, accdet_work); + + mutex_lock(&priv->res_lock); + priv->pre_accdet_status = priv->accdet_status; + check_jack_btn_type(priv); + + if (priv->jack_plugged && + priv->pre_accdet_status != priv->accdet_status) + mt6359_accdet_jack_report(priv); + mutex_unlock(&priv->res_lock); +} + +static void mt6359_accdet_jd_work(struct work_struct *work) +{ + int ret = 0; + unsigned int value = 0; + + struct mt6359_accdet *priv = + container_of(work, struct mt6359_accdet, jd_work); + + mutex_lock(&priv->res_lock); + if (priv->jd_sts == M_PLUG_IN) { + priv->jack_plugged = true; + + /* set and clear initial bit every eint interrupt */ + regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR, + ACCDET_SEQ_INIT_MASK_SFT, + BIT(ACCDET_SEQ_INIT_SFT)); + regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR, + ACCDET_SEQ_INIT_MASK_SFT, 0); + ret = regmap_read_poll_timeout(priv->regmap, + ACCDET_SEQ_INIT_ADDR, + value, + (value & ACCDET_SEQ_INIT_MASK_SFT) == 0, + 0, + 1000); + if (ret) + dev_err(priv->dev, "%s(), ret %d\n", __func__, ret); + + /* enable ACCDET unit */ + regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR, + ACCDET_SW_EN_MASK_SFT, BIT(ACCDET_SW_EN_SFT)); + } else if (priv->jd_sts == M_PLUG_OUT) { + priv->jack_plugged = false; + + accdet_set_debounce(priv, accdet_state011, + priv->data->pwm_deb->debounce3); + regmap_update_bits(priv->regmap, ACCDET_SW_EN_ADDR, + ACCDET_SW_EN_MASK_SFT, 0); + mt6359_accdet_recover_jd_setting(priv); + } + + if (priv->caps & ACCDET_PMIC_EINT_IRQ) + recover_eint_setting(priv); + mutex_unlock(&priv->res_lock); +} + +static irqreturn_t mt6359_accdet_irq(int irq, void *data) +{ + struct mt6359_accdet *priv = data; + unsigned int irq_val = 0, val = 0, value = 0; + int ret = 0; + + mutex_lock(&priv->res_lock); + regmap_read(priv->regmap, ACCDET_IRQ_ADDR, &irq_val); + + if (irq_val & ACCDET_IRQ_MASK_SFT) { + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_IRQ_CLR_MASK_SFT, + BIT(ACCDET_IRQ_CLR_SFT)); + ret = regmap_read_poll_timeout(priv->regmap, + ACCDET_IRQ_ADDR, + value, + (value & ACCDET_IRQ_MASK_SFT) == 0, + 0, + 1000); + if (ret) { + dev_err(priv->dev, "%s(), ret %d\n", __func__, ret); + mutex_unlock(&priv->res_lock); + return IRQ_NONE; + } + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_IRQ_CLR_MASK_SFT, 0); + regmap_update_bits(priv->regmap, RG_INT_STATUS_ACCDET_ADDR, + RG_INT_STATUS_ACCDET_MASK_SFT, + BIT(RG_INT_STATUS_ACCDET_SFT)); + + queue_work(priv->accdet_workqueue, &priv->accdet_work); + } else { + if (irq_val & ACCDET_EINT0_IRQ_MASK_SFT) { + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_EINT0_IRQ_CLR_MASK_SFT, + BIT(ACCDET_EINT0_IRQ_CLR_SFT)); + ret = regmap_read_poll_timeout(priv->regmap, + ACCDET_IRQ_ADDR, + value, + (value & ACCDET_EINT0_IRQ_MASK_SFT) == 0, + 0, + 1000); + if (ret) { + dev_err(priv->dev, "%s(), ret %d\n", __func__, + ret); + mutex_unlock(&priv->res_lock); + return IRQ_NONE; + } + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_EINT0_IRQ_CLR_MASK_SFT, 0); + regmap_update_bits(priv->regmap, + RG_INT_STATUS_ACCDET_ADDR, + RG_INT_STATUS_ACCDET_EINT0_MASK_SFT, + BIT(RG_INT_STATUS_ACCDET_EINT0_SFT)); + } + if (irq_val & ACCDET_EINT1_IRQ_MASK_SFT) { + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_EINT1_IRQ_CLR_MASK_SFT, + BIT(ACCDET_EINT1_IRQ_CLR_SFT)); + ret = regmap_read_poll_timeout(priv->regmap, + ACCDET_IRQ_ADDR, + value, + (value & ACCDET_EINT1_IRQ_MASK_SFT) == 0, + 0, + 1000); + if (ret) { + dev_err(priv->dev, "%s(), ret %d\n", __func__, + ret); + mutex_unlock(&priv->res_lock); + return IRQ_NONE; + } + regmap_update_bits(priv->regmap, ACCDET_IRQ_ADDR, + ACCDET_EINT1_IRQ_CLR_MASK_SFT, 0); + regmap_update_bits(priv->regmap, + RG_INT_STATUS_ACCDET_ADDR, + RG_INT_STATUS_ACCDET_EINT1_MASK_SFT, + BIT(RG_INT_STATUS_ACCDET_EINT1_SFT)); + } + /* get jack detection status */ + regmap_read(priv->regmap, ACCDET_EINT0_MEM_IN_ADDR, &val); + priv->jd_sts = ((val >> ACCDET_EINT0_MEM_IN_SFT) & + ACCDET_EINT0_MEM_IN_MASK); + /* adjust eint digital/analog setting */ + mt6359_accdet_jd_setting(priv); + + queue_work(priv->jd_workqueue, &priv->jd_work); + } + mutex_unlock(&priv->res_lock); + + return IRQ_HANDLED; +} + +static int mt6359_accdet_parse_dt(struct mt6359_accdet *priv) +{ + int ret = 0; + struct device *dev = priv->dev; + struct device_node *node = NULL; + int pwm_deb[15] = {0}; + unsigned int tmp = 0; + + node = of_get_child_by_name(dev->parent->of_node, "accdet"); + if (!node) + return -EINVAL; + + ret = of_property_read_u32(node, "mediatek,mic-vol", + &priv->data->mic_vol); + if (ret) + priv->data->mic_vol = 8; + + ret = of_property_read_u32(node, "mediatek,plugout-debounce", + &priv->data->plugout_deb); + if (ret) + priv->data->plugout_deb = 1; + + ret = of_property_read_u32(node, "mediatek,mic-mode", + &priv->data->mic_mode); + if (ret) + priv->data->mic_mode = 2; + + ret = of_property_read_u32_array(node, "mediatek,pwm-deb-setting", + pwm_deb, ARRAY_SIZE(pwm_deb)); + /* debounce8(auxadc debounce) is default, needn't get from dts */ + if (!ret) + memcpy(priv->data->pwm_deb, pwm_deb, sizeof(pwm_deb)); + + ret = of_property_read_u32(node, "mediatek,eint-level-pol", + &priv->data->eint_pol); + if (ret) + priv->data->eint_pol = 8; + + ret = of_property_read_u32(node, "mediatek,eint-use-ap", &tmp); + if (ret) + tmp = 0; + if (tmp == 0) + priv->caps |= ACCDET_PMIC_EINT_IRQ; + else if (tmp == 1) + priv->caps |= ACCDET_AP_GPIO_EINT; + + ret = of_property_read_u32(node, "mediatek,eint-detect-mode", + &priv->data->eint_detect_mode); + if (ret) { + /* eint detection mode equals to EINT HW Mode */ + priv->data->eint_detect_mode = 0x4; + } + + ret = of_property_read_u32(node, "mediatek,eint-num", &tmp); + if (ret) + tmp = 0; + if (tmp == 0) + priv->caps |= ACCDET_PMIC_EINT0; + else if (tmp == 1) + priv->caps |= ACCDET_PMIC_EINT1; + else if (tmp == 2) + priv->caps |= ACCDET_PMIC_BI_EINT; + + ret = of_property_read_u32(node, "mediatek,eint-trig-mode", + &tmp); + if (ret) + tmp = 0; + if (tmp == 0) + priv->caps |= ACCDET_PMIC_GPIO_TRIG_EINT; + else if (tmp == 1) + priv->caps |= ACCDET_PMIC_INVERTER_TRIG_EINT; + + ret = of_property_read_u32(node, "mediatek,eint-use-ext-res", + &priv->data->eint_use_ext_res); + if (ret) { + /* eint use internal resister */ + priv->data->eint_use_ext_res = 0x0; + } + + ret = of_property_read_u32(node, "mediatek,eint-comp-vth", + &priv->data->eint_comp_vth); + if (ret) + priv->data->eint_comp_vth = 0x0; + + ret = of_property_read_u32(node, "mediatek,key-mode", &tmp); + if (ret) + tmp = 0; + if (tmp == 0) { + int three_key[4]; + + priv->caps |= ACCDET_THREE_KEY; + ret = of_property_read_u32_array(node, + "mediatek,three-key-thr", + three_key, + ARRAY_SIZE(three_key)); + if (!ret) + memcpy(&priv->data->three_key, three_key + 1, + sizeof(struct three_key_threshold)); + } else if (tmp == 1) { + int four_key[5]; + + priv->caps |= ACCDET_FOUR_KEY; + ret = of_property_read_u32_array(node, + "mediatek,four-key-thr", + four_key, + ARRAY_SIZE(four_key)); + if (!ret) { + memcpy(&priv->data->four_key, four_key + 1, + sizeof(struct four_key_threshold)); + } else { + dev_warn(priv->dev, + "accdet no 4-key-thrsh dts, use efuse\n"); + } + } else if (tmp == 2) { + int three_key[4]; + + priv->caps |= ACCDET_TRI_KEY_CDD; + ret = of_property_read_u32_array(node, + "mediatek,tri-key-cdd-thr", + three_key, + ARRAY_SIZE(three_key)); + if (!ret) + memcpy(&priv->data->three_key, three_key + 1, + sizeof(struct three_key_threshold)); + } + + dev_warn(priv->dev, "accdet caps=%x\n", priv->caps); + + return 0; +} + +static void config_digital_init_by_mode(struct mt6359_accdet *priv) +{ + /* enable eint cmpmem pwm */ + regmap_write(priv->regmap, ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR, + (priv->data->pwm_deb->eint_pwm_width << 4 | + priv->data->pwm_deb->eint_pwm_thresh)); + /* DA signal stable */ + if (priv->caps & ACCDET_PMIC_EINT0) { + regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR, + ACCDET_EINT0_STABLE_VAL); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + regmap_write(priv->regmap, ACCDET_DA_STABLE_ADDR, + ACCDET_EINT1_STABLE_VAL); + } + /* after receive n+1 number, interrupt issued. */ + regmap_update_bits(priv->regmap, ACCDET_EINT_M_PLUG_IN_NUM_ADDR, + ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT, + BIT(ACCDET_EINT_M_PLUG_IN_NUM_SFT)); + /* setting HW mode, enable digital fast discharge + * if use EINT0 & EINT1 detection, please modify + * ACCDET_HWMODE_EN_ADDR[2:1] + */ + regmap_write(priv->regmap, ACCDET_HWMODE_EN_ADDR, 0x100); + + regmap_update_bits(priv->regmap, ACCDET_EINT_M_DETECT_EN_ADDR, + ACCDET_EINT_M_DETECT_EN_MASK_SFT, 0); + + /* enable PWM */ + regmap_write(priv->regmap, ACCDET_CMP_PWM_EN_ADDR, 0x67); + /* enable inverter detection */ + if (priv->data->eint_detect_mode == 0x1) { + /* disable inverter detection */ + if (priv->caps & ACCDET_PMIC_EINT0) { + regmap_update_bits(priv->regmap, + ACCDET_EINT0_INVERTER_SW_EN_ADDR, + ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, + 0); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + regmap_update_bits(priv->regmap, + ACCDET_EINT1_INVERTER_SW_EN_ADDR, + ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, + 0); + } + } else { + if (priv->caps & ACCDET_PMIC_EINT0) { + regmap_update_bits(priv->regmap, + ACCDET_EINT0_INVERTER_SW_EN_ADDR, + ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT, + BIT(ACCDET_EINT0_INVERTER_SW_EN_SFT)); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + regmap_update_bits(priv->regmap, + ACCDET_EINT1_INVERTER_SW_EN_ADDR, + ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT, + BIT(ACCDET_EINT1_INVERTER_SW_EN_SFT)); + } + } +} + +static void config_eint_init_by_mode(struct mt6359_accdet *priv) +{ + unsigned int val = 0; + + if (priv->caps & ACCDET_PMIC_EINT0) { + regmap_update_bits(priv->regmap, RG_EINT0EN_ADDR, + RG_EINT0EN_MASK_SFT, BIT(RG_EINT0EN_SFT)); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + regmap_update_bits(priv->regmap, RG_EINT1EN_ADDR, + RG_EINT1EN_MASK_SFT, BIT(RG_EINT1EN_SFT)); + } + /* ESD switches on */ + regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, + 1 << 8, 1 << 8); + /* before playback, set NCP pull low before nagative voltage */ + regmap_update_bits(priv->regmap, RG_NCP_PDDIS_EN_ADDR, + RG_NCP_PDDIS_EN_MASK_SFT, BIT(RG_NCP_PDDIS_EN_SFT)); + + if (priv->data->eint_detect_mode == 0x1 || + priv->data->eint_detect_mode == 0x2 || + priv->data->eint_detect_mode == 0x3) { + if (priv->data->eint_use_ext_res == 0x1) { + if (priv->caps & ACCDET_PMIC_EINT0) { + regmap_update_bits(priv->regmap, + RG_EINT0CONFIGACCDET_ADDR, + RG_EINT0CONFIGACCDET_MASK_SFT, + 0); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + regmap_update_bits(priv->regmap, + RG_EINT1CONFIGACCDET_ADDR, + RG_EINT1CONFIGACCDET_MASK_SFT, + 0); + } + } else { + if (priv->caps & ACCDET_PMIC_EINT0) { + regmap_update_bits(priv->regmap, + RG_EINT0CONFIGACCDET_ADDR, + RG_EINT0CONFIGACCDET_MASK_SFT, + BIT(RG_EINT0CONFIGACCDET_SFT)); + } else if (priv->caps & ACCDET_PMIC_EINT1) { + regmap_update_bits(priv->regmap, + RG_EINT1CONFIGACCDET_ADDR, + RG_EINT1CONFIGACCDET_MASK_SFT, + BIT(RG_EINT1CONFIGACCDET_SFT)); + } + } + } + + if (priv->data->eint_detect_mode != 0x1) { + /* current detect set 0.25uA */ + regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, + 0x3 << RG_ACCDETSPARE_SFT, + 0x3 << RG_ACCDETSPARE_SFT); + } + regmap_write(priv->regmap, RG_EINTCOMPVTH_ADDR, + val | priv->data->eint_comp_vth << RG_EINTCOMPVTH_SFT); +} + +static void mt6359_accdet_init(struct mt6359_accdet *priv) +{ + unsigned int reg = 0; + + regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR, + ACCDET_SEQ_INIT_MASK_SFT, BIT(ACCDET_SEQ_INIT_SFT)); + mdelay(2); + regmap_update_bits(priv->regmap, ACCDET_SEQ_INIT_ADDR, + ACCDET_SEQ_INIT_MASK_SFT, 0); + mdelay(1); + /* init the debounce time (debounce/32768)sec */ + accdet_set_debounce(priv, accdet_state000, + priv->data->pwm_deb->debounce0); + accdet_set_debounce(priv, accdet_state001, + priv->data->pwm_deb->debounce1); + accdet_set_debounce(priv, accdet_state011, + priv->data->pwm_deb->debounce3); + accdet_set_debounce(priv, accdet_auxadc, + priv->data->pwm_deb->debounce4); + + accdet_set_debounce(priv, eint_state000, + priv->data->pwm_deb->eint_debounce0); + accdet_set_debounce(priv, eint_state001, + priv->data->pwm_deb->eint_debounce1); + accdet_set_debounce(priv, eint_state011, + priv->data->pwm_deb->eint_debounce3); + accdet_set_debounce(priv, eint_inverter_state000, + priv->data->pwm_deb->eint_inverter_debounce); + + regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR, + RG_ACCDET_RST_MASK_SFT, BIT(RG_ACCDET_RST_SFT)); + regmap_update_bits(priv->regmap, RG_ACCDET_RST_ADDR, + RG_ACCDET_RST_MASK_SFT, 0); + + /* clear high micbias1 voltage setting */ + regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, + 0x3 << RG_AUDMICBIAS1HVEN_SFT, 0); + regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, + 0x7 << RG_AUDMICBIAS1VREF_SFT, 0); + + /* init pwm frequency, duty & rise/falling delay */ + regmap_write(priv->regmap, ACCDET_PWM_WIDTH_ADDR, + REGISTER_VAL(priv->data->pwm_deb->pwm_width)); + regmap_write(priv->regmap, ACCDET_PWM_THRESH_ADDR, + REGISTER_VAL(priv->data->pwm_deb->pwm_thresh)); + regmap_write(priv->regmap, ACCDET_RISE_DELAY_ADDR, + (priv->data->pwm_deb->fall_delay << 15 | + priv->data->pwm_deb->rise_delay)); + + regmap_read(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, ®); + if (priv->data->mic_vol <= 7) { + /* micbias1 <= 2.7V */ + regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, + reg | (priv->data->mic_vol << RG_AUDMICBIAS1VREF_SFT) | + RG_AUDMICBIAS1LOWPEN_MASK_SFT); + } else if (priv->data->mic_vol == 8) { + /* micbias1 = 2.8v */ + regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, + reg | (3 << RG_AUDMICBIAS1HVEN_SFT) | + RG_AUDMICBIAS1LOWPEN_MASK_SFT); + } else if (priv->data->mic_vol == 9) { + /* micbias1 = 2.85v */ + regmap_write(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, + reg | (1 << RG_AUDMICBIAS1HVEN_SFT) | + RG_AUDMICBIAS1LOWPEN_MASK_SFT); + } + /* mic mode setting */ + regmap_read(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, ®); + if (priv->data->mic_mode == HEADSET_MODE_1) { + /* ACC mode*/ + regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, + reg | RG_ACCDET_MODE_ANA11_MODE1); + /* enable analog fast discharge */ + regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR, + RG_ANALOGFDEN_MASK_SFT, + BIT(RG_ANALOGFDEN_SFT)); + regmap_update_bits(priv->regmap, RG_ACCDETSPARE_ADDR, + 0x3 << 11, 0x3 << 11); + } else if (priv->data->mic_mode == HEADSET_MODE_2) { + /* DCC mode Low cost mode without internal bias */ + regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, + reg | RG_ACCDET_MODE_ANA11_MODE2); + /* enable analog fast discharge */ + regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR, + 0x3 << RG_ANALOGFDEN_SFT, + 0x3 << RG_ANALOGFDEN_SFT); + } else if (priv->data->mic_mode == HEADSET_MODE_6) { + /* DCC mode Low cost mode with internal bias, + * bit8 = 1 to use internal bias + */ + regmap_write(priv->regmap, RG_AUDACCDETMICBIAS0PULLLOW_ADDR, + reg | RG_ACCDET_MODE_ANA11_MODE6); + regmap_update_bits(priv->regmap, RG_AUDPWDBMICBIAS1_ADDR, + RG_AUDMICBIAS1DCSW1PEN_MASK_SFT, + BIT(RG_AUDMICBIAS1DCSW1PEN_SFT)); + /* enable analog fast discharge */ + regmap_update_bits(priv->regmap, RG_ANALOGFDEN_ADDR, + 0x3 << RG_ANALOGFDEN_SFT, + 0x3 << RG_ANALOGFDEN_SFT); + } + + if (priv->caps & ACCDET_PMIC_EINT_IRQ) { + config_eint_init_by_mode(priv); + config_digital_init_by_mode(priv); + } +} + +int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *jack) +{ + struct mt6359_accdet *priv = + snd_soc_component_get_drvdata(component); + + snd_jack_set_key(jack->jack, SND_JACK_BTN_0, KEY_PLAYPAUSE); + snd_jack_set_key(jack->jack, SND_JACK_BTN_1, KEY_VOLUMEDOWN); + snd_jack_set_key(jack->jack, SND_JACK_BTN_2, KEY_VOLUMEUP); + snd_jack_set_key(jack->jack, SND_JACK_BTN_3, KEY_VOICECOMMAND); + + priv->jack = jack; + + mt6359_accdet_jack_report(priv); + + return 0; +} +EXPORT_SYMBOL_GPL(mt6359_accdet_enable_jack_detect); + +static int mt6359_accdet_probe(struct platform_device *pdev) +{ + struct mt6359_accdet *priv; + struct mt6397_chip *mt6397 = dev_get_drvdata(pdev->dev.parent); + int ret = 0; + + dev_dbg(&pdev->dev, "%s(), dev name %s\n", + __func__, dev_name(&pdev->dev)); + + priv = devm_kzalloc(&pdev->dev, sizeof(struct mt6359_accdet), + GFP_KERNEL); + if (!priv) + return -ENOMEM; + + priv->data = devm_kzalloc(&pdev->dev, sizeof(struct dts_data), + GFP_KERNEL); + if (!priv->data) + return -ENOMEM; + + priv->data->pwm_deb = devm_kzalloc(&pdev->dev, + sizeof(struct pwm_deb_settings), + GFP_KERNEL); + if (!priv->data->pwm_deb) + return -ENOMEM; + + priv->regmap = mt6397->regmap; + if (IS_ERR(priv->regmap)) { + ret = PTR_ERR(priv->regmap); + dev_err(&pdev->dev, "Failed to allocate register map: %d\n", + ret); + return ret; + } + priv->dev = &pdev->dev; + + ret = mt6359_accdet_parse_dt(priv); + if (ret) { + dev_err(&pdev->dev, "Failed to parse dts\n"); + return ret; + } + mutex_init(&priv->res_lock); + + priv->accdet_irq = platform_get_irq(pdev, 0); + if (priv->accdet_irq) { + ret = devm_request_threaded_irq(&pdev->dev, priv->accdet_irq, + NULL, mt6359_accdet_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "ACCDET_IRQ", priv); + if (ret) { + dev_err(&pdev->dev, + "Failed to request IRQ: (%d)\n", ret); + return ret; + } + } + + if (priv->caps & ACCDET_PMIC_EINT0) { + priv->accdet_eint0 = platform_get_irq(pdev, 1); + if (priv->accdet_eint0) { + ret = devm_request_threaded_irq(&pdev->dev, + priv->accdet_eint0, + NULL, mt6359_accdet_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "ACCDET_EINT0", priv); + if (ret) { + dev_err(&pdev->dev, + "Failed to request eint0 IRQ (%d)\n", + ret); + return ret; + } + } + } else if (priv->caps & ACCDET_PMIC_EINT1) { + priv->accdet_eint1 = platform_get_irq(pdev, 2); + if (priv->accdet_eint1) { + ret = devm_request_threaded_irq(&pdev->dev, + priv->accdet_eint1, + NULL, mt6359_accdet_irq, + IRQF_TRIGGER_HIGH | IRQF_ONESHOT, + "ACCDET_EINT1", priv); + if (ret) { + dev_err(&pdev->dev, + "Failed to request eint1 IRQ (%d)\n", + ret); + return ret; + } + } + } + + priv->accdet_workqueue = create_singlethread_workqueue("accdet"); + INIT_WORK(&priv->accdet_work, mt6359_accdet_work); + if (!priv->accdet_workqueue) { + dev_err(&pdev->dev, "Failed to create accdet workqueue\n"); + ret = -1; + goto err_accdet_wq; + } + + priv->jd_workqueue = create_singlethread_workqueue("mt6359_accdet_jd"); + INIT_WORK(&priv->jd_work, mt6359_accdet_jd_work); + if (!priv->jd_workqueue) { + dev_err(&pdev->dev, "Failed to reate jack detect workqueue\n"); + ret = -1; + goto err_eint_wq; + } + + platform_set_drvdata(pdev, priv); + ret = devm_snd_soc_register_component(&pdev->dev, + &mt6359_accdet_soc_driver, + NULL, 0); + if (ret) { + dev_err(&pdev->dev, "Failed to register component\n"); + return ret; + } + + priv->jd_sts = M_PLUG_OUT; + priv->jack_type = 0; + priv->btn_type = 0; + priv->accdet_status = 0x3; + mt6359_accdet_init(priv); + + mt6359_accdet_jack_report(priv); + + return 0; + +err_eint_wq: + destroy_workqueue(priv->accdet_workqueue); +err_accdet_wq: + dev_err(&pdev->dev, "%s error. now exit.!\n", __func__); + return ret; +} + +static struct platform_driver mt6359_accdet_driver = { + .driver = { + .name = "pmic-codec-accdet", + }, + .probe = mt6359_accdet_probe, +}; + +static int __init mt6359_accdet_driver_init(void) +{ + int ret = 0; + + ret = platform_driver_register(&mt6359_accdet_driver); + if (ret) + return -ENODEV; + return 0; +} + +static void __exit mt6359_accdet_driver_exit(void) +{ + platform_driver_unregister(&mt6359_accdet_driver); +} +module_init(mt6359_accdet_driver_init); +module_exit(mt6359_accdet_driver_exit); + +/* Module information */ +MODULE_DESCRIPTION("MT6359 ALSA SoC codec jack driver"); +MODULE_AUTHOR("Argus Lin "); +MODULE_LICENSE("GPL v2"); diff --git a/sound/soc/codecs/mt6359-accdet.h b/sound/soc/codecs/mt6359-accdet.h new file mode 100644 index 000000000000..c234f2f4276a --- /dev/null +++ b/sound/soc/codecs/mt6359-accdet.h @@ -0,0 +1,128 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +/* + * Copyright (C) 2021 MediaTek Inc. + * Author: Argus Lin + */ + +#ifndef _ACCDET_H_ +#define _ACCDET_H_ + +#include +#include + +#define ACCDET_DEVNAME "accdet" + +#define HEADSET_MODE_1 (1) +#define HEADSET_MODE_2 (2) +#define HEADSET_MODE_6 (6) + +#define MT6359_ACCDET_NUM_BUTTONS 4 +#define MT6359_ACCDET_JACK_MASK (SND_JACK_HEADPHONE | \ + SND_JACK_HEADSET | \ + SND_JACK_BTN_0 | \ + SND_JACK_BTN_1 | \ + SND_JACK_BTN_2 | \ + SND_JACK_BTN_3) +#define MT6359_ACCDET_BTN_MASK (SND_JACK_BTN_0 | \ + SND_JACK_BTN_1 | \ + SND_JACK_BTN_2 | \ + SND_JACK_BTN_3) + +enum eint_moisture_status { + M_PLUG_IN = 0, + M_WATER_IN = 1, + M_HP_PLUG_IN = 2, + M_PLUG_OUT = 3, + M_NO_ACT = 4, + M_UNKNOWN = 5, +}; + +enum { + accdet_state000 = 0, + accdet_state001, + accdet_state010, + accdet_state011, + accdet_auxadc, + eint_state000, + eint_state001, + eint_state010, + eint_state011, + eint_inverter_state000, +}; + +struct three_key_threshold { + unsigned int mid; + unsigned int up; + unsigned int down; +}; + +struct four_key_threshold { + unsigned int mid; + unsigned int voice; + unsigned int up; + unsigned int down; +}; + +struct pwm_deb_settings { + unsigned int pwm_width; + unsigned int pwm_thresh; + unsigned int fall_delay; + unsigned int rise_delay; + unsigned int debounce0; + unsigned int debounce1; + unsigned int debounce3; + unsigned int debounce4; + unsigned int eint_pwm_width; + unsigned int eint_pwm_thresh; + unsigned int eint_debounce0; + unsigned int eint_debounce1; + unsigned int eint_debounce2; + unsigned int eint_debounce3; + unsigned int eint_inverter_debounce; + +}; + +struct dts_data { + unsigned int mic_vol; + unsigned int mic_mode; + unsigned int plugout_deb; + unsigned int eint_pol; + struct pwm_deb_settings *pwm_deb; + struct three_key_threshold three_key; + struct four_key_threshold four_key; + unsigned int moisture_detect_enable; + unsigned int eint_detect_mode; + unsigned int eint_use_ext_res; + unsigned int eint_comp_vth; + unsigned int moisture_detect_mode; + unsigned int moisture_comp_vth; + unsigned int moisture_comp_vref2; + unsigned int moisture_use_ext_res; +}; + +struct mt6359_accdet { + struct snd_soc_jack *jack; + struct device *dev; + struct regmap *regmap; + struct dts_data *data; + unsigned int caps; + int accdet_irq; + int accdet_eint0; + int accdet_eint1; + struct mutex res_lock; /* lock protection */ + bool jack_plugged; + unsigned int jack_type; + unsigned int btn_type; + unsigned int accdet_status; + unsigned int pre_accdet_status; + unsigned int cali_voltage; + unsigned int jd_sts; + struct work_struct accdet_work; + struct workqueue_struct *accdet_workqueue; + struct work_struct jd_work; + struct workqueue_struct *jd_workqueue; +}; + +int mt6359_accdet_enable_jack_detect(struct snd_soc_component *component, + struct snd_soc_jack *jack); +#endif diff --git a/sound/soc/codecs/mt6359.h b/sound/soc/codecs/mt6359.h index 35f806b7396d..296ffa7f50b5 100644 --- a/sound/soc/codecs/mt6359.h +++ b/sound/soc/codecs/mt6359.h @@ -8,129 +8,1779 @@ #define _MT6359_H_ /*************Register Bit Define*************/ -#define PMIC_ACCDET_IRQ_SHIFT 0 -#define PMIC_ACCDET_EINT0_IRQ_SHIFT 2 -#define PMIC_ACCDET_EINT1_IRQ_SHIFT 3 -#define PMIC_ACCDET_IRQ_CLR_SHIFT 8 -#define PMIC_ACCDET_EINT0_IRQ_CLR_SHIFT 10 -#define PMIC_ACCDET_EINT1_IRQ_CLR_SHIFT 11 -#define PMIC_RG_INT_STATUS_ACCDET_SHIFT 5 -#define PMIC_RG_INT_STATUS_ACCDET_EINT0_SHIFT 6 -#define PMIC_RG_INT_STATUS_ACCDET_EINT1_SHIFT 7 -#define PMIC_RG_EINT0CONFIGACCDET_SHIFT 11 -#define PMIC_RG_EINT1CONFIGACCDET_SHIFT 0 -#define PMIC_ACCDET_EINT0_INVERTER_SW_EN_SHIFT 6 -#define PMIC_ACCDET_EINT1_INVERTER_SW_EN_SHIFT 8 -#define PMIC_RG_MTEST_EN_SHIFT 8 -#define PMIC_RG_MTEST_SEL_SHIFT 9 -#define PMIC_ACCDET_EINT0_M_SW_EN_SHIFT 10 -#define PMIC_ACCDET_EINT1_M_SW_EN_SHIFT 11 -#define PMIC_ACCDET_EINT0_CEN_STABLE_SHIFT 5 -#define PMIC_ACCDET_EINT1_CEN_STABLE_SHIFT 10 -#define PMIC_ACCDET_DA_STABLE_SHIFT 0 -#define PMIC_ACCDET_EINT0_EN_STABLE_SHIFT 1 -#define PMIC_ACCDET_EINT0_CMPEN_STABLE_SHIFT 2 -#define PMIC_ACCDET_EINT1_EN_STABLE_SHIFT 6 -#define PMIC_ACCDET_EINT1_CMPEN_STABLE_SHIFT 7 -#define PMIC_ACCDET_EINT_CTURBO_SEL_SHIFT 7 -#define PMIC_ACCDET_EINT0_CTURBO_SW_SHIFT 7 -#define PMIC_RG_EINTCOMPVTH_SHIFT 4 -#define PMIC_RG_EINT0HIRENB_SHIFT 12 -#define PMIC_RG_EINT0NOHYS_SHIFT 10 -#define PMIC_ACCDET_SW_EN_SHIFT 0 -#define PMIC_ACCDET_EINT0_MEM_IN_SHIFT 6 -#define PMIC_ACCDET_MEM_IN_SHIFT 6 -#define PMIC_ACCDET_EINT_DEBOUNCE0_SHIFT 0 -#define PMIC_ACCDET_EINT_DEBOUNCE1_SHIFT 4 -#define PMIC_ACCDET_EINT_DEBOUNCE2_SHIFT 8 -#define PMIC_ACCDET_EINT_DEBOUNCE3_SHIFT 12 -#define PMIC_RG_ACCDET2AUXSWEN_SHIFT 14 -#define PMIC_AUDACCDETAUXADCSWCTRL_SEL_SHIFT 9 -#define PMIC_AUDACCDETAUXADCSWCTRL_SW_SHIFT 10 -#define PMIC_RG_EINT0CTURBO_SHIFT 5 -#define PMIC_RG_EINT1CTURBO_SHIFT 13 -#define PMIC_ACCDET_EINT_M_PLUG_IN_NUM_SHIFT 12 -#define PMIC_ACCDET_EINT_M_DETECT_EN_SHIFT 12 -#define PMIC_ACCDET_EINT0_SW_EN_SHIFT 2 -#define PMIC_ACCDET_EINT1_SW_EN_SHIFT 4 -#define PMIC_ACCDET_EINT_CMPMOUT_SEL_SHIFT 12 -#define PMIC_ACCDET_EINT_CMPMEN_SEL_SHIFT 6 -#define PMIC_RG_HPLOUTPUTSTBENH_VAUDP32_SHIFT 0 -#define PMIC_RG_HPROUTPUTSTBENH_VAUDP32_SHIFT 4 -#define PMIC_RG_EINT0EN_SHIFT 2 -#define PMIC_RG_EINT1EN_SHIFT 10 -#define PMIC_RG_NCP_PDDIS_EN_SHIFT 0 -#define PMIC_RG_ACCDETSPARE_SHIFT 0 -#define PMIC_RG_ACCDET_RST_SHIFT 1 -#define PMIC_RG_AUDMICBIAS1HVEN_SHIFT 12 -#define PMIC_RG_AUDMICBIAS1VREF_SHIFT 4 -#define PMIC_RG_ANALOGFDEN_SHIFT 12 -#define PMIC_RG_AUDMICBIAS1DCSW1PEN_SHIFT 8 -#define PMIC_RG_AUDMICBIAS1LOWPEN_SHIFT 2 -#define PMIC_ACCDET_SEQ_INIT_SHIFT 1 -#define PMIC_RG_EINTCOMPVTH_MASK 0xf -#define PMIC_ACCDET_EINT0_MEM_IN_MASK 0x3 -#define PMIC_ACCDET_EINT_DEBOUNCE0_MASK 0xf -#define PMIC_ACCDET_EINT_DEBOUNCE1_MASK 0xf -#define PMIC_ACCDET_EINT_DEBOUNCE2_MASK 0xf -#define PMIC_ACCDET_EINT_DEBOUNCE3_MASK 0xf -#define PMIC_ACCDET_EINT0_IRQ_SHIFT 2 -#define PMIC_ACCDET_EINT1_IRQ_SHIFT 3 +#define MT6359_TOP0_ID 0x0 +#define MT6359_SMT_CON1 0x32 +#define MT6359_DRV_CON2 0x3c +#define MT6359_DRV_CON3 0x3e +#define MT6359_DRV_CON4 0x40 +#define MT6359_TOP_CKPDN_CON0 0x10c +#define MT6359_TOP_CKPDN_CON0_SET 0x10e +#define MT6359_TOP_CKPDN_CON0_CLR 0x110 +#define MT6359_AUXADC_RQST0 0x1108 +#define MT6359_AUXADC_CON10 0x11a0 +#define MT6359_AUXADC_ACCDET 0x11ba +#define MT6359_LDO_VUSB_OP_EN 0x1d0c +#define MT6359_LDO_VUSB_OP_EN_SET 0x1d0e +#define MT6359_LDO_VUSB_OP_EN_CLR 0x1d10 +#define MT6359_AUD_TOP_CKPDN_CON0 0x230c +#define MT6359_AUD_TOP_CKPDN_CON0_SET 0x230e +#define MT6359_AUD_TOP_CKPDN_CON0_CLR 0x2310 +#define MT6359_AUD_TOP_RST_CON0 0x2320 +#define MT6359_AUD_TOP_RST_CON0_SET 0x2322 +#define MT6359_AUD_TOP_RST_CON0_CLR 0x2324 +#define MT6359_AUD_TOP_INT_CON0 0x2328 +#define MT6359_AUD_TOP_INT_CON0_SET 0x232a +#define MT6359_AUD_TOP_INT_CON0_CLR 0x232c +#define MT6359_AUD_TOP_INT_MASK_CON0 0x232e +#define MT6359_AUD_TOP_INT_MASK_CON0_SET 0x2330 +#define MT6359_AUD_TOP_INT_MASK_CON0_CLR 0x2332 +#define MT6359_AUD_TOP_INT_STATUS0 0x2334 +#define MT6359_AFE_NCP_CFG2 0x24e2 +#define MT6359_AUDENC_DSN_ID 0x2500 +#define MT6359_AUDENC_DSN_REV0 0x2502 +#define MT6359_AUDENC_DSN_DBI 0x2504 +#define MT6359_AUDENC_DSN_FPI 0x2506 +#define MT6359_AUDENC_ANA_CON0 0x2508 +#define MT6359_AUDENC_ANA_CON1 0x250a +#define MT6359_AUDENC_ANA_CON2 0x250c +#define MT6359_AUDENC_ANA_CON3 0x250e +#define MT6359_AUDENC_ANA_CON4 0x2510 +#define MT6359_AUDENC_ANA_CON5 0x2512 +#define MT6359_AUDENC_ANA_CON6 0x2514 +#define MT6359_AUDENC_ANA_CON7 0x2516 +#define MT6359_AUDENC_ANA_CON8 0x2518 +#define MT6359_AUDENC_ANA_CON9 0x251a +#define MT6359_AUDENC_ANA_CON10 0x251c +#define MT6359_AUDENC_ANA_CON11 0x251e +#define MT6359_AUDENC_ANA_CON12 0x2520 +#define MT6359_AUDENC_ANA_CON13 0x2522 +#define MT6359_AUDENC_ANA_CON14 0x2524 +#define MT6359_AUDENC_ANA_CON15 0x2526 +#define MT6359_AUDENC_ANA_CON16 0x2528 +#define MT6359_AUDENC_ANA_CON17 0x252a +#define MT6359_AUDENC_ANA_CON18 0x252c +#define MT6359_AUDENC_ANA_CON19 0x252e +#define MT6359_AUDENC_ANA_CON20 0x2530 +#define MT6359_AUDENC_ANA_CON21 0x2532 +#define MT6359_AUDENC_ANA_CON22 0x2534 +#define MT6359_AUDENC_ANA_CON23 0x2536 +#define MT6359_AUDDEC_DSN_ID 0x2580 +#define MT6359_AUDDEC_DSN_REV0 0x2582 +#define MT6359_AUDDEC_DSN_DBI 0x2584 +#define MT6359_AUDDEC_DSN_FPI 0x2586 +#define MT6359_AUDDEC_ANA_CON0 0x2588 +#define MT6359_AUDDEC_ANA_CON1 0x258a +#define MT6359_AUDDEC_ANA_CON2 0x258c +#define MT6359_AUDDEC_ANA_CON3 0x258e +#define MT6359_AUDDEC_ANA_CON4 0x2590 +#define MT6359_AUDDEC_ANA_CON5 0x2592 +#define MT6359_AUDDEC_ANA_CON6 0x2594 +#define MT6359_AUDDEC_ANA_CON7 0x2596 +#define MT6359_AUDDEC_ANA_CON8 0x2598 +#define MT6359_AUDDEC_ANA_CON9 0x259a +#define MT6359_AUDDEC_ANA_CON10 0x259c +#define MT6359_AUDDEC_ANA_CON11 0x259e +#define MT6359_AUDDEC_ANA_CON12 0x25a0 +#define MT6359_AUDDEC_ANA_CON13 0x25a2 +#define MT6359_AUDDEC_ANA_CON14 0x25a4 +#define MT6359_ACCDET_DSN_DIG_ID 0x2680 +#define MT6359_ACCDET_DSN_DIG_REV0 0x2682 +#define MT6359_ACCDET_DSN_DBI 0x2684 +#define MT6359_ACCDET_DSN_FPI 0x2686 +#define MT6359_ACCDET_CON0 0x2688 +#define MT6359_ACCDET_CON1 0x268a +#define MT6359_ACCDET_CON2 0x268c +#define MT6359_ACCDET_CON3 0x268e +#define MT6359_ACCDET_CON4 0x2690 +#define MT6359_ACCDET_CON5 0x2692 +#define MT6359_ACCDET_CON6 0x2694 +#define MT6359_ACCDET_CON7 0x2696 +#define MT6359_ACCDET_CON8 0x2698 +#define MT6359_ACCDET_CON9 0x269a +#define MT6359_ACCDET_CON10 0x269c +#define MT6359_ACCDET_CON11 0x269e +#define MT6359_ACCDET_CON12 0x26a0 +#define MT6359_ACCDET_CON13 0x26a2 +#define MT6359_ACCDET_CON14 0x26a4 +#define MT6359_ACCDET_CON15 0x26a6 +#define MT6359_ACCDET_CON16 0x26a8 +#define MT6359_ACCDET_CON17 0x26aa +#define MT6359_ACCDET_CON18 0x26ac +#define MT6359_ACCDET_CON19 0x26ae +#define MT6359_ACCDET_CON20 0x26b0 +#define MT6359_ACCDET_CON21 0x26b2 +#define MT6359_ACCDET_CON22 0x26b4 +#define MT6359_ACCDET_CON23 0x26b6 +#define MT6359_ACCDET_CON24 0x26b8 +#define MT6359_ACCDET_CON25 0x26ba +#define MT6359_ACCDET_CON26 0x26bc +#define MT6359_ACCDET_CON27 0x26be +#define MT6359_ACCDET_CON28 0x26c0 +#define MT6359_ACCDET_CON29 0x26c2 +#define MT6359_ACCDET_CON30 0x26c4 +#define MT6359_ACCDET_CON31 0x26c6 +#define MT6359_ACCDET_CON32 0x26c8 +#define MT6359_ACCDET_CON33 0x26ca +#define MT6359_ACCDET_CON34 0x26cc +#define MT6359_ACCDET_CON35 0x26ce +#define MT6359_ACCDET_CON36 0x26d0 +#define MT6359_ACCDET_CON37 0x26d2 +#define MT6359_ACCDET_CON38 0x26d4 +#define MT6359_ACCDET_CON39 0x26d6 +#define MT6359_ACCDET_CON40 0x26d8 -/* AUDENC_ANA_CON16: */ -#define RG_AUD_MICBIAS1_LOWP_EN BIT(PMIC_RG_AUDMICBIAS1LOWPEN_SHIFT) +#define TOP0_ANA_ID_ADDR \ + MT6359_TOP0_ID +#define TOP0_ANA_ID_SFT 0 +#define TOP0_ANA_ID_MASK 0xFF +#define TOP0_ANA_ID_MASK_SFT (0xFF << 0) +#define AUXADC_RQST_CH0_ADDR \ + MT6359_AUXADC_RQST0 +#define AUXADC_RQST_CH0_SFT 0 +#define AUXADC_RQST_CH0_MASK 0x1 +#define AUXADC_RQST_CH0_MASK_SFT (0x1 << 0) +#define AUXADC_ACCDET_ANASWCTRL_EN_ADDR \ + MT6359_AUXADC_CON15 +#define AUXADC_ACCDET_ANASWCTRL_EN_SFT 6 +#define AUXADC_ACCDET_ANASWCTRL_EN_MASK 0x1 +#define AUXADC_ACCDET_ANASWCTRL_EN_MASK_SFT (0x1 << 6) +#define AUXADC_ACCDET_AUTO_SPL_ADDR \ + MT6359_AUXADC_ACCDET +#define AUXADC_ACCDET_AUTO_SPL_SFT 0 +#define AUXADC_ACCDET_AUTO_SPL_MASK 0x1 +#define AUXADC_ACCDET_AUTO_SPL_MASK_SFT (0x1 << 0) +#define AUXADC_ACCDET_AUTO_RQST_CLR_ADDR \ + MT6359_AUXADC_ACCDET +#define AUXADC_ACCDET_AUTO_RQST_CLR_SFT 1 +#define AUXADC_ACCDET_AUTO_RQST_CLR_MASK 0x1 +#define AUXADC_ACCDET_AUTO_RQST_CLR_MASK_SFT (0x1 << 1) +#define AUXADC_ACCDET_DIG1_RSV0_ADDR \ + MT6359_AUXADC_ACCDET +#define AUXADC_ACCDET_DIG1_RSV0_SFT 2 +#define AUXADC_ACCDET_DIG1_RSV0_MASK 0x3F +#define AUXADC_ACCDET_DIG1_RSV0_MASK_SFT (0x3F << 2) +#define AUXADC_ACCDET_DIG0_RSV0_ADDR \ + MT6359_AUXADC_ACCDET +#define AUXADC_ACCDET_DIG0_RSV0_SFT 8 +#define AUXADC_ACCDET_DIG0_RSV0_MASK 0xFF +#define AUXADC_ACCDET_DIG0_RSV0_MASK_SFT (0xFF << 8) + +#define RG_ACCDET_CK_PDN_ADDR \ + MT6359_AUD_TOP_CKPDN_CON0 +#define RG_ACCDET_CK_PDN_SFT 0 +#define RG_ACCDET_CK_PDN_MASK 0x1 +#define RG_ACCDET_CK_PDN_MASK_SFT (0x1 << 0) + +#define RG_ACCDET_RST_ADDR \ + MT6359_AUD_TOP_RST_CON0 +#define RG_ACCDET_RST_SFT 1 +#define RG_ACCDET_RST_MASK 0x1 +#define RG_ACCDET_RST_MASK_SFT (0x1 << 1) +#define BANK_ACCDET_SWRST_ADDR \ + MT6359_AUD_TOP_RST_BANK_CON0 +#define BANK_ACCDET_SWRST_SFT 0 +#define BANK_ACCDET_SWRST_MASK 0x1 +#define BANK_ACCDET_SWRST_MASK_SFT (0x1 << 0) + +#define RG_INT_EN_ACCDET_ADDR \ + MT6359_AUD_TOP_INT_CON0 +#define RG_INT_EN_ACCDET_SFT 5 +#define RG_INT_EN_ACCDET_MASK 0x1 +#define RG_INT_EN_ACCDET_MASK_SFT (0x1 << 5) +#define RG_INT_EN_ACCDET_EINT0_ADDR \ + MT6359_AUD_TOP_INT_CON0 +#define RG_INT_EN_ACCDET_EINT0_SFT 6 +#define RG_INT_EN_ACCDET_EINT0_MASK 0x1 +#define RG_INT_EN_ACCDET_EINT0_MASK_SFT (0x1 << 6) +#define RG_INT_EN_ACCDET_EINT1_ADDR \ + MT6359_AUD_TOP_INT_CON0 +#define RG_INT_EN_ACCDET_EINT1_SFT 7 +#define RG_INT_EN_ACCDET_EINT1_MASK 0x1 +#define RG_INT_EN_ACCDET_EINT1_MASK_SFT (0x1 << 7) + +#define RG_INT_MASK_ACCDET_ADDR \ + MT6359_AUD_TOP_INT_MASK_CON0 +#define RG_INT_MASK_ACCDET_SFT 5 +#define RG_INT_MASK_ACCDET_MASK 0x1 +#define RG_INT_MASK_ACCDET_MASK_SFT (0x1 << 5) +#define RG_INT_MASK_ACCDET_EINT0_ADDR \ + MT6359_AUD_TOP_INT_MASK_CON0 +#define RG_INT_MASK_ACCDET_EINT0_SFT 6 +#define RG_INT_MASK_ACCDET_EINT0_MASK 0x1 +#define RG_INT_MASK_ACCDET_EINT0_MASK_SFT (0x1 << 6) +#define RG_INT_MASK_ACCDET_EINT1_ADDR \ + MT6359_AUD_TOP_INT_MASK_CON0 +#define RG_INT_MASK_ACCDET_EINT1_SFT 7 +#define RG_INT_MASK_ACCDET_EINT1_MASK 0x1 +#define RG_INT_MASK_ACCDET_EINT1_MASK_SFT (0x1 << 7) + +#define RG_INT_STATUS_ACCDET_ADDR \ + MT6359_AUD_TOP_INT_STATUS0 +#define RG_INT_STATUS_ACCDET_SFT 5 +#define RG_INT_STATUS_ACCDET_MASK 0x1 +#define RG_INT_STATUS_ACCDET_MASK_SFT (0x1 << 5) +#define RG_INT_STATUS_ACCDET_EINT0_ADDR \ + MT6359_AUD_TOP_INT_STATUS0 +#define RG_INT_STATUS_ACCDET_EINT0_SFT 6 +#define RG_INT_STATUS_ACCDET_EINT0_MASK 0x1 +#define RG_INT_STATUS_ACCDET_EINT0_MASK_SFT (0x1 << 6) +#define RG_INT_STATUS_ACCDET_EINT1_ADDR \ + MT6359_AUD_TOP_INT_STATUS0 +#define RG_INT_STATUS_ACCDET_EINT1_SFT 7 +#define RG_INT_STATUS_ACCDET_EINT1_MASK 0x1 +#define RG_INT_STATUS_ACCDET_EINT1_MASK_SFT (0x1 << 7) + +#define RG_INT_RAW_STATUS_ACCDET_ADDR \ + MT6359_AUD_TOP_INT_RAW_STATUS0 +#define RG_INT_RAW_STATUS_ACCDET_SFT 5 +#define RG_INT_RAW_STATUS_ACCDET_MASK 0x1 +#define RG_INT_RAW_STATUS_ACCDET_MASK_SFT (0x1 << 5) +#define RG_INT_RAW_STATUS_ACCDET_EINT0_ADDR \ + MT6359_AUD_TOP_INT_RAW_STATUS0 +#define RG_INT_RAW_STATUS_ACCDET_EINT0_SFT 6 +#define RG_INT_RAW_STATUS_ACCDET_EINT0_MASK 0x1 +#define RG_INT_RAW_STATUS_ACCDET_EINT0_MASK_SFT (0x1 << 6) +#define RG_INT_RAW_STATUS_ACCDET_EINT1_ADDR \ + MT6359_AUD_TOP_INT_RAW_STATUS0 +#define RG_INT_RAW_STATUS_ACCDET_EINT1_SFT 7 +#define RG_INT_RAW_STATUS_ACCDET_EINT1_MASK 0x1 +#define RG_INT_RAW_STATUS_ACCDET_EINT1_MASK_SFT (0x1 << 7) + +#define RG_AUDACCDETMICBIAS0PULLLOW_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETMICBIAS0PULLLOW_SFT 0 +#define RG_AUDACCDETMICBIAS0PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS0PULLLOW_MASK_SFT (0x1 << 0) +#define RG_AUDACCDETMICBIAS1PULLLOW_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETMICBIAS1PULLLOW_SFT 1 +#define RG_AUDACCDETMICBIAS1PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS1PULLLOW_MASK_SFT (0x1 << 1) +#define RG_AUDACCDETMICBIAS2PULLLOW_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETMICBIAS2PULLLOW_SFT 2 +#define RG_AUDACCDETMICBIAS2PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS2PULLLOW_MASK_SFT (0x1 << 2) +#define RG_AUDACCDETVIN1PULLLOW_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETVIN1PULLLOW_SFT 3 +#define RG_AUDACCDETVIN1PULLLOW_MASK 0x1 +#define RG_AUDACCDETVIN1PULLLOW_MASK_SFT (0x1 << 3) +#define RG_AUDACCDETVTHACAL_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETVTHACAL_SFT 4 +#define RG_AUDACCDETVTHACAL_MASK 0x1 +#define RG_AUDACCDETVTHACAL_MASK_SFT (0x1 << 4) +#define RG_AUDACCDETVTHBCAL_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETVTHBCAL_SFT 5 +#define RG_AUDACCDETVTHBCAL_MASK 0x1 +#define RG_AUDACCDETVTHBCAL_MASK_SFT (0x1 << 5) +#define RG_AUDACCDETTVDET_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETTVDET_SFT 6 +#define RG_AUDACCDETTVDET_MASK 0x1 +#define RG_AUDACCDETTVDET_MASK_SFT (0x1 << 6) +#define RG_ACCDETSEL_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_ACCDETSEL_SFT 7 +#define RG_ACCDETSEL_MASK 0x1 +#define RG_ACCDETSEL_MASK_SFT (0x1 << 7) + +#define RG_AUDPWDBMICBIAS1_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDPWDBMICBIAS1_SFT 0 +#define RG_AUDPWDBMICBIAS1_MASK 0x1 +#define RG_AUDPWDBMICBIAS1_MASK_SFT (0x1 << 0) +#define RG_AUDMICBIAS1BYPASSEN_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDMICBIAS1BYPASSEN_SFT 1 +#define RG_AUDMICBIAS1BYPASSEN_MASK 0x1 +#define RG_AUDMICBIAS1BYPASSEN_MASK_SFT (0x1 << 1) +#define RG_AUDMICBIAS1LOWPEN_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDMICBIAS1LOWPEN_SFT 2 +#define RG_AUDMICBIAS1LOWPEN_MASK 0x1 +#define RG_AUDMICBIAS1LOWPEN_MASK_SFT (0x1 << 2) +#define RG_AUDMICBIAS1VREF_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDMICBIAS1VREF_SFT 4 +#define RG_AUDMICBIAS1VREF_MASK 0x7 +#define RG_AUDMICBIAS1VREF_MASK_SFT (0x7 << 4) +#define RG_AUDMICBIAS1DCSW1PEN_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDMICBIAS1DCSW1PEN_SFT 8 +#define RG_AUDMICBIAS1DCSW1PEN_MASK 0x1 +#define RG_AUDMICBIAS1DCSW1PEN_MASK_SFT (0x1 << 8) +#define RG_AUDMICBIAS1DCSW1NEN_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDMICBIAS1DCSW1NEN_SFT 9 +#define RG_AUDMICBIAS1DCSW1NEN_MASK 0x1 +#define RG_AUDMICBIAS1DCSW1NEN_MASK_SFT (0x1 << 9) +#define RG_BANDGAPGEN_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_BANDGAPGEN_SFT 10 +#define RG_BANDGAPGEN_MASK 0x1 +#define RG_BANDGAPGEN_MASK_SFT (0x1 << 10) +#define RG_AUDMICBIAS1HVEN_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDMICBIAS1HVEN_SFT 12 +#define RG_AUDMICBIAS1HVEN_MASK 0x1 +#define RG_AUDMICBIAS1HVEN_MASK_SFT (0x1 << 12) +#define RG_AUDMICBIAS1HVVREF_ADDR \ + MT6359_AUDENC_ANA_CON16 +#define RG_AUDMICBIAS1HVVREF_SFT 13 +#define RG_AUDMICBIAS1HVVREF_MASK 0x1 +#define RG_AUDMICBIAS1HVVREF_MASK_SFT (0x1 << 13) + +#define RG_EINT0NOHYS_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_EINT0NOHYS_SFT 10 +#define RG_EINT0NOHYS_MASK 0x1 +#define RG_EINT0NOHYS_MASK_SFT (0x1 << 10) +#define RG_EINT0CONFIGACCDET_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_EINT0CONFIGACCDET_SFT 11 +#define RG_EINT0CONFIGACCDET_MASK 0x1 +#define RG_EINT0CONFIGACCDET_MASK_SFT (0x1 << 11) +#define RG_EINT0HIRENB_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_EINT0HIRENB_SFT 12 +#define RG_EINT0HIRENB_MASK 0x1 +#define RG_EINT0HIRENB_MASK_SFT (0x1 << 12) +#define RG_ACCDET2AUXRESBYPASS_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_ACCDET2AUXRESBYPASS_SFT 13 +#define RG_ACCDET2AUXRESBYPASS_MASK 0x1 +#define RG_ACCDET2AUXRESBYPASS_MASK_SFT (0x1 << 13) +#define RG_ACCDET2AUXSWEN_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_ACCDET2AUXSWEN_SFT 14 +#define RG_ACCDET2AUXSWEN_MASK 0x1 +#define RG_ACCDET2AUXSWEN_MASK_SFT (0x1 << 14) +#define RG_AUDACCDETMICBIAS3PULLLOW_ADDR \ + MT6359_AUDENC_ANA_CON18 +#define RG_AUDACCDETMICBIAS3PULLLOW_SFT 15 +#define RG_AUDACCDETMICBIAS3PULLLOW_MASK 0x1 +#define RG_AUDACCDETMICBIAS3PULLLOW_MASK_SFT (0x1 << 15) +#define RG_EINT1CONFIGACCDET_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_EINT1CONFIGACCDET_SFT 0 +#define RG_EINT1CONFIGACCDET_MASK 0x1 +#define RG_EINT1CONFIGACCDET_MASK_SFT (0x1 << 0) +#define RG_EINT1HIRENB_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_EINT1HIRENB_SFT 1 +#define RG_EINT1HIRENB_MASK 0x1 +#define RG_EINT1HIRENB_MASK_SFT (0x1 << 1) +#define RG_EINT1NOHYS_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_EINT1NOHYS_SFT 2 +#define RG_EINT1NOHYS_MASK 0x1 +#define RG_EINT1NOHYS_MASK_SFT (0x1 << 2) +#define RG_EINTCOMPVTH_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_MTEST_EN_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_MTEST_EN_SFT 8 +#define RG_MTEST_EN_MASK 0x1 +#define RG_MTEST_EN_MASK_SFT (0x1 << 8) +#define RG_MTEST_SEL_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_MTEST_SEL_SFT 9 +#define RG_MTEST_SEL_MASK 0x1 +#define RG_MTEST_SEL_MASK_SFT (0x1 << 9) +#define RG_MTEST_CURRENT_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_MTEST_CURRENT_SFT 10 +#define RG_MTEST_CURRENT_MASK 0x1 +#define RG_MTEST_CURRENT_MASK_SFT (0x1 << 10) +#define RG_ANALOGFDEN_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_ANALOGFDEN_SFT 12 +#define RG_ANALOGFDEN_MASK 0x1 +#define RG_ANALOGFDEN_MASK_SFT (0x1 << 12) +#define RG_FDVIN1PPULLLOW_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_FDVIN1PPULLLOW_SFT 13 +#define RG_FDVIN1PPULLLOW_MASK 0x1 +#define RG_FDVIN1PPULLLOW_MASK_SFT (0x1 << 13) +#define RG_FDEINT0TYPE_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_FDEINT0TYPE_SFT 14 +#define RG_FDEINT0TYPE_MASK 0x1 +#define RG_FDEINT0TYPE_MASK_SFT (0x1 << 14) +#define RG_FDEINT1TYPE_ADDR \ + MT6359_AUDENC_ANA_CON19 +#define RG_FDEINT1TYPE_SFT 15 +#define RG_FDEINT1TYPE_MASK 0x1 +#define RG_FDEINT1TYPE_MASK_SFT (0x1 << 15) +#define RG_EINT0CMPEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT0CMPEN_SFT 0 +#define RG_EINT0CMPEN_MASK 0x1 +#define RG_EINT0CMPEN_MASK_SFT (0x1 << 0) +#define RG_EINT0CMPMEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT0CMPMEN_SFT 1 +#define RG_EINT0CMPMEN_MASK 0x1 +#define RG_EINT0CMPMEN_MASK_SFT (0x1 << 1) +#define RG_EINT0EN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT0EN_SFT 2 +#define RG_EINT0EN_MASK 0x1 +#define RG_EINT0EN_MASK_SFT (0x1 << 2) +#define RG_EINT0CEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT0CEN_SFT 3 +#define RG_EINT0CEN_MASK 0x1 +#define RG_EINT0CEN_MASK_SFT (0x1 << 3) +#define RG_EINT0INVEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT0INVEN_SFT 4 +#define RG_EINT0INVEN_MASK 0x1 +#define RG_EINT0INVEN_MASK_SFT (0x1 << 4) +#define RG_EINT0CTURBO_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT0CTURBO_SFT 5 +#define RG_EINT0CTURBO_MASK 0x7 +#define RG_EINT0CTURBO_MASK_SFT (0x7 << 5) +#define RG_EINT1CMPEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT1CMPEN_SFT 8 +#define RG_EINT1CMPEN_MASK 0x1 +#define RG_EINT1CMPEN_MASK_SFT (0x1 << 8) +#define RG_EINT1CMPMEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT1CMPMEN_SFT 9 +#define RG_EINT1CMPMEN_MASK 0x1 +#define RG_EINT1CMPMEN_MASK_SFT (0x1 << 9) +#define RG_EINT1EN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT1EN_SFT 10 +#define RG_EINT1EN_MASK 0x1 +#define RG_EINT1EN_MASK_SFT (0x1 << 10) +#define RG_EINT1CEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT1CEN_SFT 11 +#define RG_EINT1CEN_MASK 0x1 +#define RG_EINT1CEN_MASK_SFT (0x1 << 11) +#define RG_EINT1INVEN_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT1INVEN_SFT 12 +#define RG_EINT1INVEN_MASK 0x1 +#define RG_EINT1INVEN_MASK_SFT (0x1 << 12) +#define RG_EINT1CTURBO_ADDR \ + MT6359_AUDENC_ANA_CON20 +#define RG_EINT1CTURBO_SFT 13 +#define RG_EINT1CTURBO_MASK 0x7 +#define RG_EINT1CTURBO_MASK_SFT (0x7 << 13) +#define RG_ACCDETSPARE_ADDR \ + MT6359_AUDENC_ANA_CON21 + +#define ACCDET_ANA_ID_ADDR \ + MT6359_ACCDET_DSN_DIG_ID +#define ACCDET_ANA_ID_SFT 0 +#define ACCDET_ANA_ID_MASK 0xFF +#define ACCDET_ANA_ID_MASK_SFT (0xFF << 0) +#define ACCDET_DIG_ID_ADDR \ + MT6359_ACCDET_DSN_DIG_ID +#define ACCDET_DIG_ID_SFT 8 +#define ACCDET_DIG_ID_MASK 0xFF +#define ACCDET_DIG_ID_MASK_SFT (0xFF << 8) +#define ACCDET_ANA_MINOR_REV_ADDR \ + MT6359_ACCDET_DSN_DIG_REV0 +#define ACCDET_ANA_MINOR_REV_SFT 0 +#define ACCDET_ANA_MINOR_REV_MASK 0xF +#define ACCDET_ANA_MINOR_REV_MASK_SFT (0xF << 0) +#define ACCDET_ANA_MAJOR_REV_ADDR \ + MT6359_ACCDET_DSN_DIG_REV0 +#define ACCDET_ANA_MAJOR_REV_SFT 4 +#define ACCDET_ANA_MAJOR_REV_MASK 0xF +#define ACCDET_ANA_MAJOR_REV_MASK_SFT (0xF << 4) +#define ACCDET_DIG_MINOR_REV_ADDR \ + MT6359_ACCDET_DSN_DIG_REV0 +#define ACCDET_DIG_MINOR_REV_SFT 8 +#define ACCDET_DIG_MINOR_REV_MASK 0xF +#define ACCDET_DIG_MINOR_REV_MASK_SFT (0xF << 8) +#define ACCDET_DIG_MAJOR_REV_ADDR \ + MT6359_ACCDET_DSN_DIG_REV0 +#define ACCDET_DIG_MAJOR_REV_SFT 12 +#define ACCDET_DIG_MAJOR_REV_MASK 0xF +#define ACCDET_DIG_MAJOR_REV_MASK_SFT (0xF << 12) +#define ACCDET_DSN_CBS_ADDR \ + MT6359_ACCDET_DSN_DBI +#define ACCDET_DSN_CBS_SFT 0 +#define ACCDET_DSN_CBS_MASK 0x3 +#define ACCDET_DSN_CBS_MASK_SFT (0x3 << 0) +#define ACCDET_DSN_BIX_ADDR \ + MT6359_ACCDET_DSN_DBI +#define ACCDET_DSN_BIX_SFT 2 +#define ACCDET_DSN_BIX_MASK 0x3 +#define ACCDET_DSN_BIX_MASK_SFT (0x3 << 2) +#define ACCDET_ESP_ADDR \ + MT6359_ACCDET_DSN_DBI +#define ACCDET_ESP_SFT 8 +#define ACCDET_ESP_MASK 0xFF +#define ACCDET_ESP_MASK_SFT (0xFF << 8) +#define ACCDET_DSN_FPI_ADDR \ + MT6359_ACCDET_DSN_FPI +#define ACCDET_DSN_FPI_SFT 0 +#define ACCDET_DSN_FPI_MASK 0xFF +#define ACCDET_DSN_FPI_MASK_SFT (0xFF << 0) +#define ACCDET_AUXADC_SEL_ADDR \ + MT6359_ACCDET_CON0 +#define ACCDET_AUXADC_SEL_SFT 0 +#define ACCDET_AUXADC_SEL_MASK 0x1 +#define ACCDET_AUXADC_SEL_MASK_SFT (0x1 << 0) +#define ACCDET_AUXADC_SW_ADDR \ + MT6359_ACCDET_CON0 +#define ACCDET_AUXADC_SW_SFT 1 +#define ACCDET_AUXADC_SW_MASK 0x1 +#define ACCDET_AUXADC_SW_MASK_SFT (0x1 << 1) +#define ACCDET_TEST_AUXADC_ADDR \ + MT6359_ACCDET_CON0 +#define ACCDET_TEST_AUXADC_SFT 2 +#define ACCDET_TEST_AUXADC_MASK 0x1 +#define ACCDET_TEST_AUXADC_MASK_SFT (0x1 << 2) +#define ACCDET_AUXADC_ANASWCTRL_SEL_ADDR \ + MT6359_ACCDET_CON0 +#define ACCDET_AUXADC_ANASWCTRL_SEL_SFT 8 +#define ACCDET_AUXADC_ANASWCTRL_SEL_MASK 0x1 +#define ACCDET_AUXADC_ANASWCTRL_SEL_MASK_SFT (0x1 << 8) +#define AUDACCDETAUXADCSWCTRL_SEL_ADDR \ + MT6359_ACCDET_CON0 +#define AUDACCDETAUXADCSWCTRL_SEL_SFT 9 +#define AUDACCDETAUXADCSWCTRL_SEL_MASK 0x1 +#define AUDACCDETAUXADCSWCTRL_SEL_MASK_SFT (0x1 << 9) +#define AUDACCDETAUXADCSWCTRL_SW_ADDR \ + MT6359_ACCDET_CON0 +#define AUDACCDETAUXADCSWCTRL_SW_SFT 10 +#define AUDACCDETAUXADCSWCTRL_SW_MASK 0x1 +#define AUDACCDETAUXADCSWCTRL_SW_MASK_SFT (0x1 << 10) +#define ACCDET_TEST_ANA_ADDR \ + MT6359_ACCDET_CON0 +#define ACCDET_TEST_ANA_SFT 11 +#define ACCDET_TEST_ANA_MASK 0x1 +#define ACCDET_TEST_ANA_MASK_SFT (0x1 << 11) +#define RG_AUDACCDETRSV_ADDR \ + MT6359_ACCDET_CON0 +#define RG_AUDACCDETRSV_SFT 13 +#define RG_AUDACCDETRSV_MASK 0x3 +#define RG_AUDACCDETRSV_MASK_SFT (0x3 << 13) +#define ACCDET_SW_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_SW_EN_SFT 0 +#define ACCDET_SW_EN_MASK 0x1 +#define ACCDET_SW_EN_MASK_SFT (0x1 << 0) +#define ACCDET_SEQ_INIT_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_SEQ_INIT_SFT 1 +#define ACCDET_SEQ_INIT_MASK 0x1 +#define ACCDET_SEQ_INIT_MASK_SFT (0x1 << 1) +#define ACCDET_EINT0_SW_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT0_SW_EN_SFT 2 +#define ACCDET_EINT0_SW_EN_MASK 0x1 +#define ACCDET_EINT0_SW_EN_MASK_SFT (0x1 << 2) +#define ACCDET_EINT0_SEQ_INIT_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT0_SEQ_INIT_SFT 3 +#define ACCDET_EINT0_SEQ_INIT_MASK 0x1 +#define ACCDET_EINT0_SEQ_INIT_MASK_SFT (0x1 << 3) +#define ACCDET_EINT1_SW_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT1_SW_EN_SFT 4 +#define ACCDET_EINT1_SW_EN_MASK 0x1 +#define ACCDET_EINT1_SW_EN_MASK_SFT (0x1 << 4) +#define ACCDET_EINT1_SEQ_INIT_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT1_SEQ_INIT_SFT 5 +#define ACCDET_EINT1_SEQ_INIT_MASK 0x1 +#define ACCDET_EINT1_SEQ_INIT_MASK_SFT (0x1 << 5) +#define ACCDET_EINT0_INVERTER_SW_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT0_INVERTER_SW_EN_SFT 6 +#define ACCDET_EINT0_INVERTER_SW_EN_MASK 0x1 +#define ACCDET_EINT0_INVERTER_SW_EN_MASK_SFT (0x1 << 6) +#define ACCDET_EINT0_INVERTER_SEQ_INIT_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT0_INVERTER_SEQ_INIT_SFT 7 +#define ACCDET_EINT0_INVERTER_SEQ_INIT_MASK 0x1 +#define ACCDET_EINT0_INVERTER_SEQ_INIT_MASK_SFT (0x1 << 7) +#define ACCDET_EINT1_INVERTER_SW_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT1_INVERTER_SW_EN_SFT 8 +#define ACCDET_EINT1_INVERTER_SW_EN_MASK 0x1 +#define ACCDET_EINT1_INVERTER_SW_EN_MASK_SFT (0x1 << 8) +#define ACCDET_EINT1_INVERTER_SEQ_INIT_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT1_INVERTER_SEQ_INIT_SFT 9 +#define ACCDET_EINT1_INVERTER_SEQ_INIT_MASK 0x1 +#define ACCDET_EINT1_INVERTER_SEQ_INIT_MASK_SFT (0x1 << 9) +#define ACCDET_EINT0_M_SW_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT0_M_SW_EN_SFT 10 +#define ACCDET_EINT0_M_SW_EN_MASK 0x1 +#define ACCDET_EINT0_M_SW_EN_MASK_SFT (0x1 << 10) +#define ACCDET_EINT1_M_SW_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT1_M_SW_EN_SFT 11 +#define ACCDET_EINT1_M_SW_EN_MASK 0x1 +#define ACCDET_EINT1_M_SW_EN_MASK_SFT (0x1 << 11) +#define ACCDET_EINT_M_DETECT_EN_ADDR \ + MT6359_ACCDET_CON1 +#define ACCDET_EINT_M_DETECT_EN_SFT 12 +#define ACCDET_EINT_M_DETECT_EN_MASK 0x1 +#define ACCDET_EINT_M_DETECT_EN_MASK_SFT (0x1 << 12) +#define ACCDET_CMP_PWM_EN_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_CMP_PWM_EN_SFT 0 +#define ACCDET_CMP_PWM_EN_MASK 0x1 +#define ACCDET_CMP_PWM_EN_MASK_SFT (0x1 << 0) +#define ACCDET_VTH_PWM_EN_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_VTH_PWM_EN_SFT 1 +#define ACCDET_VTH_PWM_EN_MASK 0x1 +#define ACCDET_VTH_PWM_EN_MASK_SFT (0x1 << 1) +#define ACCDET_MBIAS_PWM_EN_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_MBIAS_PWM_EN_SFT 2 +#define ACCDET_MBIAS_PWM_EN_MASK 0x1 +#define ACCDET_MBIAS_PWM_EN_MASK_SFT (0x1 << 2) +#define ACCDET_EINT_EN_PWM_EN_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_EINT_EN_PWM_EN_SFT 3 +#define ACCDET_EINT_EN_PWM_EN_MASK 0x1 +#define ACCDET_EINT_EN_PWM_EN_MASK_SFT (0x1 << 3) +#define ACCDET_EINT_CMPEN_PWM_EN_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_EINT_CMPEN_PWM_EN_SFT 4 +#define ACCDET_EINT_CMPEN_PWM_EN_MASK 0x1 +#define ACCDET_EINT_CMPEN_PWM_EN_MASK_SFT (0x1 << 4) +#define ACCDET_EINT_CMPMEN_PWM_EN_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_EINT_CMPMEN_PWM_EN_SFT 5 +#define ACCDET_EINT_CMPMEN_PWM_EN_MASK 0x1 +#define ACCDET_EINT_CMPMEN_PWM_EN_MASK_SFT (0x1 << 5) +#define ACCDET_EINT_CTURBO_PWM_EN_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_EINT_CTURBO_PWM_EN_SFT 6 +#define ACCDET_EINT_CTURBO_PWM_EN_MASK 0x1 +#define ACCDET_EINT_CTURBO_PWM_EN_MASK_SFT (0x1 << 6) +#define ACCDET_CMP_PWM_IDLE_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_CMP_PWM_IDLE_SFT 8 +#define ACCDET_CMP_PWM_IDLE_MASK 0x1 +#define ACCDET_CMP_PWM_IDLE_MASK_SFT (0x1 << 8) +#define ACCDET_VTH_PWM_IDLE_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_VTH_PWM_IDLE_SFT 9 +#define ACCDET_VTH_PWM_IDLE_MASK 0x1 +#define ACCDET_VTH_PWM_IDLE_MASK_SFT (0x1 << 9) +#define ACCDET_MBIAS_PWM_IDLE_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_MBIAS_PWM_IDLE_SFT 10 +#define ACCDET_MBIAS_PWM_IDLE_MASK 0x1 +#define ACCDET_MBIAS_PWM_IDLE_MASK_SFT (0x1 << 10) +#define ACCDET_EINT0_CMPEN_PWM_IDLE_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_EINT0_CMPEN_PWM_IDLE_SFT 11 +#define ACCDET_EINT0_CMPEN_PWM_IDLE_MASK 0x1 +#define ACCDET_EINT0_CMPEN_PWM_IDLE_MASK_SFT (0x1 << 11) +#define ACCDET_EINT1_CMPEN_PWM_IDLE_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_EINT1_CMPEN_PWM_IDLE_SFT 12 +#define ACCDET_EINT1_CMPEN_PWM_IDLE_MASK 0x1 +#define ACCDET_EINT1_CMPEN_PWM_IDLE_MASK_SFT (0x1 << 12) +#define ACCDET_PWM_EN_SW_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_PWM_EN_SW_SFT 13 +#define ACCDET_PWM_EN_SW_MASK 0x1 +#define ACCDET_PWM_EN_SW_MASK_SFT (0x1 << 13) +#define ACCDET_PWM_EN_SEL_ADDR \ + MT6359_ACCDET_CON2 +#define ACCDET_PWM_EN_SEL_SFT 14 +#define ACCDET_PWM_EN_SEL_MASK 0x3 +#define ACCDET_PWM_EN_SEL_MASK_SFT (0x3 << 14) +#define ACCDET_PWM_WIDTH_ADDR \ + MT6359_ACCDET_CON3 +#define ACCDET_PWM_WIDTH_SFT 0 +#define ACCDET_PWM_WIDTH_MASK 0xFFFF +#define ACCDET_PWM_WIDTH_MASK_SFT (0xFFFF << 0) +#define ACCDET_PWM_THRESH_ADDR \ + MT6359_ACCDET_CON4 +#define ACCDET_PWM_THRESH_SFT 0 +#define ACCDET_PWM_THRESH_MASK 0xFFFF +#define ACCDET_PWM_THRESH_MASK_SFT (0xFFFF << 0) +#define ACCDET_RISE_DELAY_ADDR \ + MT6359_ACCDET_CON5 +#define ACCDET_RISE_DELAY_SFT 0 +#define ACCDET_RISE_DELAY_MASK 0x7FFF +#define ACCDET_RISE_DELAY_MASK_SFT (0x7FFF << 0) +#define ACCDET_FALL_DELAY_ADDR \ + MT6359_ACCDET_CON5 +#define ACCDET_FALL_DELAY_SFT 15 +#define ACCDET_FALL_DELAY_MASK 0x1 +#define ACCDET_FALL_DELAY_MASK_SFT (0x1 << 15) +#define ACCDET_EINT_CMPMEN_PWM_THRESH_ADDR \ + MT6359_ACCDET_CON6 +#define ACCDET_EINT_CMPMEN_PWM_THRESH_SFT 0 +#define ACCDET_EINT_CMPMEN_PWM_THRESH_MASK 0x7 +#define ACCDET_EINT_CMPMEN_PWM_THRESH_MASK_SFT (0x7 << 0) +#define ACCDET_EINT_CMPMEN_PWM_WIDTH_ADDR \ + MT6359_ACCDET_CON6 +#define ACCDET_EINT_CMPMEN_PWM_WIDTH_SFT 4 +#define ACCDET_EINT_CMPMEN_PWM_WIDTH_MASK 0x7 +#define ACCDET_EINT_CMPMEN_PWM_WIDTH_MASK_SFT (0x7 << 4) +#define ACCDET_EINT_EN_PWM_THRESH_ADDR \ + MT6359_ACCDET_CON7 +#define ACCDET_EINT_EN_PWM_THRESH_SFT 0 +#define ACCDET_EINT_EN_PWM_THRESH_MASK 0x7 +#define ACCDET_EINT_EN_PWM_THRESH_MASK_SFT (0x7 << 0) +#define ACCDET_EINT_EN_PWM_WIDTH_ADDR \ + MT6359_ACCDET_CON7 +#define ACCDET_EINT_EN_PWM_WIDTH_SFT 4 +#define ACCDET_EINT_EN_PWM_WIDTH_MASK 0x3 +#define ACCDET_EINT_EN_PWM_WIDTH_MASK_SFT (0x3 << 4) +#define ACCDET_EINT_CMPEN_PWM_THRESH_ADDR \ + MT6359_ACCDET_CON7 +#define ACCDET_EINT_CMPEN_PWM_THRESH_SFT 8 +#define ACCDET_EINT_CMPEN_PWM_THRESH_MASK 0x7 +#define ACCDET_EINT_CMPEN_PWM_THRESH_MASK_SFT (0x7 << 8) +#define ACCDET_EINT_CMPEN_PWM_WIDTH_ADDR \ + MT6359_ACCDET_CON7 +#define ACCDET_EINT_CMPEN_PWM_WIDTH_SFT 12 +#define ACCDET_EINT_CMPEN_PWM_WIDTH_MASK 0x3 +#define ACCDET_EINT_CMPEN_PWM_WIDTH_MASK_SFT (0x3 << 12) +#define ACCDET_DEBOUNCE0_ADDR \ + MT6359_ACCDET_CON8 +#define ACCDET_DEBOUNCE0_SFT 0 +#define ACCDET_DEBOUNCE0_MASK 0xFFFF +#define ACCDET_DEBOUNCE0_MASK_SFT (0xFFFF << 0) +#define ACCDET_DEBOUNCE1_ADDR \ + MT6359_ACCDET_CON9 +#define ACCDET_DEBOUNCE1_SFT 0 +#define ACCDET_DEBOUNCE1_MASK 0xFFFF +#define ACCDET_DEBOUNCE1_MASK_SFT (0xFFFF << 0) +#define ACCDET_DEBOUNCE2_ADDR \ + MT6359_ACCDET_CON10 +#define ACCDET_DEBOUNCE2_SFT 0 +#define ACCDET_DEBOUNCE2_MASK 0xFFFF +#define ACCDET_DEBOUNCE2_MASK_SFT (0xFFFF << 0) +#define ACCDET_DEBOUNCE3_ADDR \ + MT6359_ACCDET_CON11 +#define ACCDET_DEBOUNCE3_SFT 0 +#define ACCDET_DEBOUNCE3_MASK 0xFFFF +#define ACCDET_DEBOUNCE3_MASK_SFT (0xFFFF << 0) +#define ACCDET_CONNECT_AUXADC_TIME_DIG_ADDR \ + MT6359_ACCDET_CON12 +#define ACCDET_CONNECT_AUXADC_TIME_DIG_SFT 0 +#define ACCDET_CONNECT_AUXADC_TIME_DIG_MASK 0xFFFF +#define ACCDET_CONNECT_AUXADC_TIME_DIG_MASK_SFT (0xFFFF << 0) +#define ACCDET_CONNECT_AUXADC_TIME_ANA_ADDR \ + MT6359_ACCDET_CON13 +#define ACCDET_CONNECT_AUXADC_TIME_ANA_SFT 0 +#define ACCDET_CONNECT_AUXADC_TIME_ANA_MASK 0xFFFF +#define ACCDET_CONNECT_AUXADC_TIME_ANA_MASK_SFT (0xFFFF << 0) +#define ACCDET_EINT_DEBOUNCE0_ADDR \ + MT6359_ACCDET_CON14 +#define ACCDET_EINT_DEBOUNCE0_SFT 0 +#define ACCDET_EINT_DEBOUNCE0_MASK 0xF +#define ACCDET_EINT_DEBOUNCE0_MASK_SFT (0xF << 0) +#define ACCDET_EINT_DEBOUNCE1_ADDR \ + MT6359_ACCDET_CON14 +#define ACCDET_EINT_DEBOUNCE1_SFT 4 +#define ACCDET_EINT_DEBOUNCE1_MASK 0xF +#define ACCDET_EINT_DEBOUNCE1_MASK_SFT (0xF << 4) +#define ACCDET_EINT_DEBOUNCE2_ADDR \ + MT6359_ACCDET_CON14 +#define ACCDET_EINT_DEBOUNCE2_SFT 8 +#define ACCDET_EINT_DEBOUNCE2_MASK 0xF +#define ACCDET_EINT_DEBOUNCE2_MASK_SFT (0xF << 8) +#define ACCDET_EINT_DEBOUNCE3_ADDR \ + MT6359_ACCDET_CON14 +#define ACCDET_EINT_DEBOUNCE3_SFT 12 +#define ACCDET_EINT_DEBOUNCE3_MASK 0xF +#define ACCDET_EINT_DEBOUNCE3_MASK_SFT (0xF << 12) +#define ACCDET_EINT_INVERTER_DEBOUNCE_ADDR \ + MT6359_ACCDET_CON15 +#define ACCDET_EINT_INVERTER_DEBOUNCE_SFT 0 +#define ACCDET_EINT_INVERTER_DEBOUNCE_MASK 0xF +#define ACCDET_EINT_INVERTER_DEBOUNCE_MASK_SFT (0xF << 0) +#define ACCDET_IVAL_CUR_IN_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_IVAL_CUR_IN_SFT 0 +#define ACCDET_IVAL_CUR_IN_MASK 0x3 +#define ACCDET_IVAL_CUR_IN_MASK_SFT (0x3 << 0) +#define ACCDET_IVAL_SAM_IN_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_IVAL_SAM_IN_SFT 2 +#define ACCDET_IVAL_SAM_IN_MASK 0x3 +#define ACCDET_IVAL_SAM_IN_MASK_SFT (0x3 << 2) +#define ACCDET_IVAL_MEM_IN_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_IVAL_MEM_IN_SFT 4 +#define ACCDET_IVAL_MEM_IN_MASK 0x3 +#define ACCDET_IVAL_MEM_IN_MASK_SFT (0x3 << 4) +#define ACCDET_EINT_IVAL_CUR_IN_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_EINT_IVAL_CUR_IN_SFT 6 +#define ACCDET_EINT_IVAL_CUR_IN_MASK 0x3 +#define ACCDET_EINT_IVAL_CUR_IN_MASK_SFT (0x3 << 6) +#define ACCDET_EINT_IVAL_SAM_IN_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_EINT_IVAL_SAM_IN_SFT 8 +#define ACCDET_EINT_IVAL_SAM_IN_MASK 0x3 +#define ACCDET_EINT_IVAL_SAM_IN_MASK_SFT (0x3 << 8) +#define ACCDET_EINT_IVAL_MEM_IN_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_EINT_IVAL_MEM_IN_SFT 10 +#define ACCDET_EINT_IVAL_MEM_IN_MASK 0x3 +#define ACCDET_EINT_IVAL_MEM_IN_MASK_SFT (0x3 << 10) +#define ACCDET_IVAL_SEL_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_IVAL_SEL_SFT 12 +#define ACCDET_IVAL_SEL_MASK 0x1 +#define ACCDET_IVAL_SEL_MASK_SFT (0x1 << 12) +#define ACCDET_EINT_IVAL_SEL_ADDR \ + MT6359_ACCDET_CON16 +#define ACCDET_EINT_IVAL_SEL_SFT 13 +#define ACCDET_EINT_IVAL_SEL_MASK 0x1 +#define ACCDET_EINT_IVAL_SEL_MASK_SFT (0x1 << 13) +#define ACCDET_EINT_INVERTER_IVAL_CUR_IN_ADDR \ + MT6359_ACCDET_CON17 +#define ACCDET_EINT_INVERTER_IVAL_CUR_IN_SFT 0 +#define ACCDET_EINT_INVERTER_IVAL_CUR_IN_MASK 0x1 +#define ACCDET_EINT_INVERTER_IVAL_CUR_IN_MASK_SFT (0x1 << 0) +#define ACCDET_EINT_INVERTER_IVAL_SAM_IN_ADDR \ + MT6359_ACCDET_CON17 +#define ACCDET_EINT_INVERTER_IVAL_SAM_IN_SFT 1 +#define ACCDET_EINT_INVERTER_IVAL_SAM_IN_MASK 0x1 +#define ACCDET_EINT_INVERTER_IVAL_SAM_IN_MASK_SFT (0x1 << 1) +#define ACCDET_EINT_INVERTER_IVAL_MEM_IN_ADDR \ + MT6359_ACCDET_CON17 +#define ACCDET_EINT_INVERTER_IVAL_MEM_IN_SFT 2 +#define ACCDET_EINT_INVERTER_IVAL_MEM_IN_MASK 0x1 +#define ACCDET_EINT_INVERTER_IVAL_MEM_IN_MASK_SFT (0x1 << 2) +#define ACCDET_EINT_INVERTER_IVAL_SEL_ADDR \ + MT6359_ACCDET_CON17 +#define ACCDET_EINT_INVERTER_IVAL_SEL_SFT 3 +#define ACCDET_EINT_INVERTER_IVAL_SEL_MASK 0x1 +#define ACCDET_EINT_INVERTER_IVAL_SEL_MASK_SFT (0x1 << 3) +#define ACCDET_IRQ_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_IRQ_SFT 0 +#define ACCDET_IRQ_MASK 0x1 +#define ACCDET_IRQ_MASK_SFT (0x1 << 0) +#define ACCDET_EINT0_IRQ_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_EINT0_IRQ_SFT 2 +#define ACCDET_EINT0_IRQ_MASK 0x1 +#define ACCDET_EINT0_IRQ_MASK_SFT (0x1 << 2) +#define ACCDET_EINT1_IRQ_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_EINT1_IRQ_SFT 3 +#define ACCDET_EINT1_IRQ_MASK 0x1 +#define ACCDET_EINT1_IRQ_MASK_SFT (0x1 << 3) +#define ACCDET_EINT_IN_INVERSE_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_EINT_IN_INVERSE_SFT 4 +#define ACCDET_EINT_IN_INVERSE_MASK 0x1 +#define ACCDET_EINT_IN_INVERSE_MASK_SFT (0x1 << 4) +#define ACCDET_IRQ_CLR_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_IRQ_CLR_SFT 8 +#define ACCDET_IRQ_CLR_MASK 0x1 +#define ACCDET_IRQ_CLR_MASK_SFT (0x1 << 8) +#define ACCDET_EINT0_IRQ_CLR_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_EINT0_IRQ_CLR_SFT 10 +#define ACCDET_EINT0_IRQ_CLR_MASK 0x1 +#define ACCDET_EINT0_IRQ_CLR_MASK_SFT (0x1 << 10) +#define ACCDET_EINT1_IRQ_CLR_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_EINT1_IRQ_CLR_SFT 11 +#define ACCDET_EINT1_IRQ_CLR_MASK 0x1 +#define ACCDET_EINT1_IRQ_CLR_MASK_SFT (0x1 << 11) +#define ACCDET_EINT_M_PLUG_IN_NUM_ADDR \ + MT6359_ACCDET_CON18 +#define ACCDET_EINT_M_PLUG_IN_NUM_SFT 12 +#define ACCDET_EINT_M_PLUG_IN_NUM_MASK 0x7 +#define ACCDET_EINT_M_PLUG_IN_NUM_MASK_SFT (0x7 << 12) +#define ACCDET_DA_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_DA_STABLE_SFT 0 +#define ACCDET_DA_STABLE_MASK 0x1 +#define ACCDET_DA_STABLE_MASK_SFT (0x1 << 0) +#define ACCDET_EINT0_EN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT0_EN_STABLE_SFT 1 +#define ACCDET_EINT0_EN_STABLE_MASK 0x1 +#define ACCDET_EINT0_EN_STABLE_MASK_SFT (0x1 << 1) +#define ACCDET_EINT0_CMPEN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT0_CMPEN_STABLE_SFT 2 +#define ACCDET_EINT0_CMPEN_STABLE_MASK 0x1 +#define ACCDET_EINT0_CMPEN_STABLE_MASK_SFT (0x1 << 2) +#define ACCDET_EINT0_CMPMEN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT0_CMPMEN_STABLE_SFT 3 +#define ACCDET_EINT0_CMPMEN_STABLE_MASK 0x1 +#define ACCDET_EINT0_CMPMEN_STABLE_MASK_SFT (0x1 << 3) +#define ACCDET_EINT0_CTURBO_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT0_CTURBO_STABLE_SFT 4 +#define ACCDET_EINT0_CTURBO_STABLE_MASK 0x1 +#define ACCDET_EINT0_CTURBO_STABLE_MASK_SFT (0x1 << 4) +#define ACCDET_EINT0_CEN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT0_CEN_STABLE_SFT 5 +#define ACCDET_EINT0_CEN_STABLE_MASK 0x1 +#define ACCDET_EINT0_CEN_STABLE_MASK_SFT (0x1 << 5) +#define ACCDET_EINT1_EN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT1_EN_STABLE_SFT 6 +#define ACCDET_EINT1_EN_STABLE_MASK 0x1 +#define ACCDET_EINT1_EN_STABLE_MASK_SFT (0x1 << 6) +#define ACCDET_EINT1_CMPEN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT1_CMPEN_STABLE_SFT 7 +#define ACCDET_EINT1_CMPEN_STABLE_MASK 0x1 +#define ACCDET_EINT1_CMPEN_STABLE_MASK_SFT (0x1 << 7) +#define ACCDET_EINT1_CMPMEN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT1_CMPMEN_STABLE_SFT 8 +#define ACCDET_EINT1_CMPMEN_STABLE_MASK 0x1 +#define ACCDET_EINT1_CMPMEN_STABLE_MASK_SFT (0x1 << 8) +#define ACCDET_EINT1_CTURBO_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT1_CTURBO_STABLE_SFT 9 +#define ACCDET_EINT1_CTURBO_STABLE_MASK 0x1 +#define ACCDET_EINT1_CTURBO_STABLE_MASK_SFT (0x1 << 9) +#define ACCDET_EINT1_CEN_STABLE_ADDR \ + MT6359_ACCDET_CON19 +#define ACCDET_EINT1_CEN_STABLE_SFT 10 +#define ACCDET_EINT1_CEN_STABLE_MASK 0x1 +#define ACCDET_EINT1_CEN_STABLE_MASK_SFT (0x1 << 10) +#define ACCDET_HWMODE_EN_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_HWMODE_EN_SFT 0 +#define ACCDET_HWMODE_EN_MASK 0x1 +#define ACCDET_HWMODE_EN_MASK_SFT (0x1 << 0) +#define ACCDET_HWMODE_SEL_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_HWMODE_SEL_SFT 1 +#define ACCDET_HWMODE_SEL_MASK 0x3 +#define ACCDET_HWMODE_SEL_MASK_SFT (0x3 << 1) +#define ACCDET_PLUG_OUT_DETECT_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_PLUG_OUT_DETECT_SFT 3 +#define ACCDET_PLUG_OUT_DETECT_MASK 0x1 +#define ACCDET_PLUG_OUT_DETECT_MASK_SFT (0x1 << 3) +#define ACCDET_EINT0_REVERSE_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_EINT0_REVERSE_SFT 4 +#define ACCDET_EINT0_REVERSE_MASK 0x1 +#define ACCDET_EINT0_REVERSE_MASK_SFT (0x1 << 4) +#define ACCDET_EINT1_REVERSE_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_EINT1_REVERSE_SFT 5 +#define ACCDET_EINT1_REVERSE_MASK 0x1 +#define ACCDET_EINT1_REVERSE_MASK_SFT (0x1 << 5) +#define ACCDET_EINT_HWMODE_EN_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_EINT_HWMODE_EN_SFT 8 +#define ACCDET_EINT_HWMODE_EN_MASK 0x1 +#define ACCDET_EINT_HWMODE_EN_MASK_SFT (0x1 << 8) +#define ACCDET_EINT_PLUG_OUT_BYPASS_DEB_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_EINT_PLUG_OUT_BYPASS_DEB_SFT 9 +#define ACCDET_EINT_PLUG_OUT_BYPASS_DEB_MASK 0x1 +#define ACCDET_EINT_PLUG_OUT_BYPASS_DEB_MASK_SFT (0x1 << 9) +#define ACCDET_EINT_M_PLUG_IN_EN_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_EINT_M_PLUG_IN_EN_SFT 10 +#define ACCDET_EINT_M_PLUG_IN_EN_MASK 0x1 +#define ACCDET_EINT_M_PLUG_IN_EN_MASK_SFT (0x1 << 10) +#define ACCDET_EINT_M_HWMODE_EN_ADDR \ + MT6359_ACCDET_CON20 +#define ACCDET_EINT_M_HWMODE_EN_SFT 11 +#define ACCDET_EINT_M_HWMODE_EN_MASK 0x1 +#define ACCDET_EINT_M_HWMODE_EN_MASK_SFT (0x1 << 11) +#define ACCDET_TEST_CMPEN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_TEST_CMPEN_SFT 0 +#define ACCDET_TEST_CMPEN_MASK 0x1 +#define ACCDET_TEST_CMPEN_MASK_SFT (0x1 << 0) +#define ACCDET_TEST_VTHEN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_TEST_VTHEN_SFT 1 +#define ACCDET_TEST_VTHEN_MASK 0x1 +#define ACCDET_TEST_VTHEN_MASK_SFT (0x1 << 1) +#define ACCDET_TEST_MBIASEN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_TEST_MBIASEN_SFT 2 +#define ACCDET_TEST_MBIASEN_MASK 0x1 +#define ACCDET_TEST_MBIASEN_MASK_SFT (0x1 << 2) +#define ACCDET_EINT_TEST_EN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_EN_SFT 3 +#define ACCDET_EINT_TEST_EN_MASK 0x1 +#define ACCDET_EINT_TEST_EN_MASK_SFT (0x1 << 3) +#define ACCDET_EINT_TEST_INVEN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_INVEN_SFT 4 +#define ACCDET_EINT_TEST_INVEN_MASK 0x1 +#define ACCDET_EINT_TEST_INVEN_MASK_SFT (0x1 << 4) +#define ACCDET_EINT_TEST_CMPEN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_CMPEN_SFT 5 +#define ACCDET_EINT_TEST_CMPEN_MASK 0x1 +#define ACCDET_EINT_TEST_CMPEN_MASK_SFT (0x1 << 5) +#define ACCDET_EINT_TEST_CMPMEN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_CMPMEN_SFT 6 +#define ACCDET_EINT_TEST_CMPMEN_MASK 0x1 +#define ACCDET_EINT_TEST_CMPMEN_MASK_SFT (0x1 << 6) +#define ACCDET_EINT_TEST_CTURBO_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_CTURBO_SFT 7 +#define ACCDET_EINT_TEST_CTURBO_MASK 0x1 +#define ACCDET_EINT_TEST_CTURBO_MASK_SFT (0x1 << 7) +#define ACCDET_EINT_TEST_CEN_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_CEN_SFT 8 +#define ACCDET_EINT_TEST_CEN_MASK 0x1 +#define ACCDET_EINT_TEST_CEN_MASK_SFT (0x1 << 8) +#define ACCDET_TEST_B_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_TEST_B_SFT 9 +#define ACCDET_TEST_B_MASK 0x1 +#define ACCDET_TEST_B_MASK_SFT (0x1 << 9) +#define ACCDET_TEST_A_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_TEST_A_SFT 10 +#define ACCDET_TEST_A_MASK 0x1 +#define ACCDET_TEST_A_MASK_SFT (0x1 << 10) +#define ACCDET_EINT_TEST_CMPOUT_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_CMPOUT_SFT 11 +#define ACCDET_EINT_TEST_CMPOUT_MASK 0x1 +#define ACCDET_EINT_TEST_CMPOUT_MASK_SFT (0x1 << 11) +#define ACCDET_EINT_TEST_CMPMOUT_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_CMPMOUT_SFT 12 +#define ACCDET_EINT_TEST_CMPMOUT_MASK 0x1 +#define ACCDET_EINT_TEST_CMPMOUT_MASK_SFT (0x1 << 12) +#define ACCDET_EINT_TEST_INVOUT_ADDR \ + MT6359_ACCDET_CON21 +#define ACCDET_EINT_TEST_INVOUT_SFT 13 +#define ACCDET_EINT_TEST_INVOUT_MASK 0x1 +#define ACCDET_EINT_TEST_INVOUT_MASK_SFT (0x1 << 13) +#define ACCDET_CMPEN_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_CMPEN_SEL_SFT 0 +#define ACCDET_CMPEN_SEL_MASK 0x1 +#define ACCDET_CMPEN_SEL_MASK_SFT (0x1 << 0) +#define ACCDET_VTHEN_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_VTHEN_SEL_SFT 1 +#define ACCDET_VTHEN_SEL_MASK 0x1 +#define ACCDET_VTHEN_SEL_MASK_SFT (0x1 << 1) +#define ACCDET_MBIASEN_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_MBIASEN_SEL_SFT 2 +#define ACCDET_MBIASEN_SEL_MASK 0x1 +#define ACCDET_MBIASEN_SEL_MASK_SFT (0x1 << 2) +#define ACCDET_EINT_EN_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_EN_SEL_SFT 3 +#define ACCDET_EINT_EN_SEL_MASK 0x1 +#define ACCDET_EINT_EN_SEL_MASK_SFT (0x1 << 3) +#define ACCDET_EINT_INVEN_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_INVEN_SEL_SFT 4 +#define ACCDET_EINT_INVEN_SEL_MASK 0x1 +#define ACCDET_EINT_INVEN_SEL_MASK_SFT (0x1 << 4) +#define ACCDET_EINT_CMPEN_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_CMPEN_SEL_SFT 5 +#define ACCDET_EINT_CMPEN_SEL_MASK 0x1 +#define ACCDET_EINT_CMPEN_SEL_MASK_SFT (0x1 << 5) +#define ACCDET_EINT_CMPMEN_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_CMPMEN_SEL_SFT 6 +#define ACCDET_EINT_CMPMEN_SEL_MASK 0x1 +#define ACCDET_EINT_CMPMEN_SEL_MASK_SFT (0x1 << 6) +#define ACCDET_EINT_CTURBO_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_CTURBO_SEL_SFT 7 +#define ACCDET_EINT_CTURBO_SEL_MASK 0x1 +#define ACCDET_EINT_CTURBO_SEL_MASK_SFT (0x1 << 7) +#define ACCDET_B_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_B_SEL_SFT 9 +#define ACCDET_B_SEL_MASK 0x1 +#define ACCDET_B_SEL_MASK_SFT (0x1 << 9) +#define ACCDET_A_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_A_SEL_SFT 10 +#define ACCDET_A_SEL_MASK 0x1 +#define ACCDET_A_SEL_MASK_SFT (0x1 << 10) +#define ACCDET_EINT_CMPOUT_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_CMPOUT_SEL_SFT 11 +#define ACCDET_EINT_CMPOUT_SEL_MASK 0x1 +#define ACCDET_EINT_CMPOUT_SEL_MASK_SFT (0x1 << 11) +#define ACCDET_EINT_CMPMOUT_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_CMPMOUT_SEL_SFT 12 +#define ACCDET_EINT_CMPMOUT_SEL_MASK 0x1 +#define ACCDET_EINT_CMPMOUT_SEL_MASK_SFT (0x1 << 12) +#define ACCDET_EINT_INVOUT_SEL_ADDR \ + MT6359_ACCDET_CON22 +#define ACCDET_EINT_INVOUT_SEL_SFT 13 +#define ACCDET_EINT_INVOUT_SEL_MASK 0x1 +#define ACCDET_EINT_INVOUT_SEL_MASK_SFT (0x1 << 13) +#define ACCDET_CMPEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_CMPEN_SW_SFT 0 +#define ACCDET_CMPEN_SW_MASK 0x1 +#define ACCDET_CMPEN_SW_MASK_SFT (0x1 << 0) +#define ACCDET_VTHEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_VTHEN_SW_SFT 1 +#define ACCDET_VTHEN_SW_MASK 0x1 +#define ACCDET_VTHEN_SW_MASK_SFT (0x1 << 1) +#define ACCDET_MBIASEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_MBIASEN_SW_SFT 2 +#define ACCDET_MBIASEN_SW_MASK 0x1 +#define ACCDET_MBIASEN_SW_MASK_SFT (0x1 << 2) +#define ACCDET_EINT0_EN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT0_EN_SW_SFT 3 +#define ACCDET_EINT0_EN_SW_MASK 0x1 +#define ACCDET_EINT0_EN_SW_MASK_SFT (0x1 << 3) +#define ACCDET_EINT0_INVEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT0_INVEN_SW_SFT 4 +#define ACCDET_EINT0_INVEN_SW_MASK 0x1 +#define ACCDET_EINT0_INVEN_SW_MASK_SFT (0x1 << 4) +#define ACCDET_EINT0_CMPEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT0_CMPEN_SW_SFT 5 +#define ACCDET_EINT0_CMPEN_SW_MASK 0x1 +#define ACCDET_EINT0_CMPEN_SW_MASK_SFT (0x1 << 5) +#define ACCDET_EINT0_CMPMEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT0_CMPMEN_SW_SFT 6 +#define ACCDET_EINT0_CMPMEN_SW_MASK 0x1 +#define ACCDET_EINT0_CMPMEN_SW_MASK_SFT (0x1 << 6) +#define ACCDET_EINT0_CTURBO_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT0_CTURBO_SW_SFT 7 +#define ACCDET_EINT0_CTURBO_SW_MASK 0x1 +#define ACCDET_EINT0_CTURBO_SW_MASK_SFT (0x1 << 7) +#define ACCDET_EINT1_EN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT1_EN_SW_SFT 8 +#define ACCDET_EINT1_EN_SW_MASK 0x1 +#define ACCDET_EINT1_EN_SW_MASK_SFT (0x1 << 8) +#define ACCDET_EINT1_INVEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT1_INVEN_SW_SFT 9 +#define ACCDET_EINT1_INVEN_SW_MASK 0x1 +#define ACCDET_EINT1_INVEN_SW_MASK_SFT (0x1 << 9) +#define ACCDET_EINT1_CMPEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT1_CMPEN_SW_SFT 10 +#define ACCDET_EINT1_CMPEN_SW_MASK 0x1 +#define ACCDET_EINT1_CMPEN_SW_MASK_SFT (0x1 << 10) +#define ACCDET_EINT1_CMPMEN_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT1_CMPMEN_SW_SFT 11 +#define ACCDET_EINT1_CMPMEN_SW_MASK 0x1 +#define ACCDET_EINT1_CMPMEN_SW_MASK_SFT (0x1 << 11) +#define ACCDET_EINT1_CTURBO_SW_ADDR \ + MT6359_ACCDET_CON23 +#define ACCDET_EINT1_CTURBO_SW_SFT 12 +#define ACCDET_EINT1_CTURBO_SW_MASK 0x1 +#define ACCDET_EINT1_CTURBO_SW_MASK_SFT (0x1 << 12) +#define ACCDET_B_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_B_SW_SFT 0 +#define ACCDET_B_SW_MASK 0x1 +#define ACCDET_B_SW_MASK_SFT (0x1 << 0) +#define ACCDET_A_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_A_SW_SFT 1 +#define ACCDET_A_SW_MASK 0x1 +#define ACCDET_A_SW_MASK_SFT (0x1 << 1) +#define ACCDET_EINT0_CMPOUT_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_EINT0_CMPOUT_SW_SFT 2 +#define ACCDET_EINT0_CMPOUT_SW_MASK 0x1 +#define ACCDET_EINT0_CMPOUT_SW_MASK_SFT (0x1 << 2) +#define ACCDET_EINT0_CMPMOUT_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_EINT0_CMPMOUT_SW_SFT 3 +#define ACCDET_EINT0_CMPMOUT_SW_MASK 0x1 +#define ACCDET_EINT0_CMPMOUT_SW_MASK_SFT (0x1 << 3) +#define ACCDET_EINT0_INVOUT_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_EINT0_INVOUT_SW_SFT 4 +#define ACCDET_EINT0_INVOUT_SW_MASK 0x1 +#define ACCDET_EINT0_INVOUT_SW_MASK_SFT (0x1 << 4) +#define ACCDET_EINT1_CMPOUT_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_EINT1_CMPOUT_SW_SFT 5 +#define ACCDET_EINT1_CMPOUT_SW_MASK 0x1 +#define ACCDET_EINT1_CMPOUT_SW_MASK_SFT (0x1 << 5) +#define ACCDET_EINT1_CMPMOUT_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_EINT1_CMPMOUT_SW_SFT 6 +#define ACCDET_EINT1_CMPMOUT_SW_MASK 0x1 +#define ACCDET_EINT1_CMPMOUT_SW_MASK_SFT (0x1 << 6) +#define ACCDET_EINT1_INVOUT_SW_ADDR \ + MT6359_ACCDET_CON24 +#define ACCDET_EINT1_INVOUT_SW_SFT 7 +#define ACCDET_EINT1_INVOUT_SW_MASK 0x1 +#define ACCDET_EINT1_INVOUT_SW_MASK_SFT (0x1 << 7) +#define AD_AUDACCDETCMPOB_ADDR \ + MT6359_ACCDET_CON25 +#define AD_AUDACCDETCMPOB_SFT 0 +#define AD_AUDACCDETCMPOB_MASK 0x1 +#define AD_AUDACCDETCMPOB_MASK_SFT (0x1 << 0) +#define AD_AUDACCDETCMPOA_ADDR \ + MT6359_ACCDET_CON25 +#define AD_AUDACCDETCMPOA_SFT 1 +#define AD_AUDACCDETCMPOA_MASK 0x1 +#define AD_AUDACCDETCMPOA_MASK_SFT (0x1 << 1) +#define ACCDET_CUR_IN_ADDR \ + MT6359_ACCDET_CON25 +#define ACCDET_CUR_IN_SFT 2 +#define ACCDET_CUR_IN_MASK 0x3 +#define ACCDET_CUR_IN_MASK_SFT (0x3 << 2) +#define ACCDET_SAM_IN_ADDR \ + MT6359_ACCDET_CON25 +#define ACCDET_SAM_IN_SFT 4 +#define ACCDET_SAM_IN_MASK 0x3 +#define ACCDET_SAM_IN_MASK_SFT (0x3 << 4) +#define ACCDET_MEM_IN_ADDR \ + MT6359_ACCDET_CON25 +#define ACCDET_MEM_IN_SFT 6 +#define ACCDET_MEM_IN_MASK 0x3 +#define ACCDET_MEM_IN_MASK_SFT (0x3 << 6) +#define ACCDET_STATE_ADDR \ + MT6359_ACCDET_CON25 +#define ACCDET_STATE_SFT 8 +#define ACCDET_STATE_MASK 0x7 +#define ACCDET_STATE_MASK_SFT (0x7 << 8) +#define DA_AUDACCDETMBIASCLK_ADDR \ + MT6359_ACCDET_CON25 +#define DA_AUDACCDETMBIASCLK_SFT 12 +#define DA_AUDACCDETMBIASCLK_MASK 0x1 +#define DA_AUDACCDETMBIASCLK_MASK_SFT (0x1 << 12) +#define DA_AUDACCDETVTHCLK_ADDR \ + MT6359_ACCDET_CON25 +#define DA_AUDACCDETVTHCLK_SFT 13 +#define DA_AUDACCDETVTHCLK_MASK 0x1 +#define DA_AUDACCDETVTHCLK_MASK_SFT (0x1 << 13) +#define DA_AUDACCDETCMPCLK_ADDR \ + MT6359_ACCDET_CON25 +#define DA_AUDACCDETCMPCLK_SFT 14 +#define DA_AUDACCDETCMPCLK_MASK 0x1 +#define DA_AUDACCDETCMPCLK_MASK_SFT (0x1 << 14) +#define DA_AUDACCDETAUXADCSWCTRL_ADDR \ + MT6359_ACCDET_CON25 +#define DA_AUDACCDETAUXADCSWCTRL_SFT 15 +#define DA_AUDACCDETAUXADCSWCTRL_MASK 0x1 +#define DA_AUDACCDETAUXADCSWCTRL_MASK_SFT (0x1 << 15) +#define AD_EINT0CMPMOUT_ADDR \ + MT6359_ACCDET_CON26 +#define AD_EINT0CMPMOUT_SFT 0 +#define AD_EINT0CMPMOUT_MASK 0x1 +#define AD_EINT0CMPMOUT_MASK_SFT (0x1 << 0) +#define AD_EINT0CMPOUT_ADDR \ + MT6359_ACCDET_CON26 +#define AD_EINT0CMPOUT_SFT 1 +#define AD_EINT0CMPOUT_MASK 0x1 +#define AD_EINT0CMPOUT_MASK_SFT (0x1 << 1) +#define ACCDET_EINT0_CUR_IN_ADDR \ + MT6359_ACCDET_CON26 +#define ACCDET_EINT0_CUR_IN_SFT 2 +#define ACCDET_EINT0_CUR_IN_MASK 0x3 +#define ACCDET_EINT0_CUR_IN_MASK_SFT (0x3 << 2) +#define ACCDET_EINT0_SAM_IN_ADDR \ + MT6359_ACCDET_CON26 +#define ACCDET_EINT0_SAM_IN_SFT 4 +#define ACCDET_EINT0_SAM_IN_MASK 0x3 +#define ACCDET_EINT0_SAM_IN_MASK_SFT (0x3 << 4) +#define ACCDET_EINT0_MEM_IN_ADDR \ + MT6359_ACCDET_CON26 +#define ACCDET_EINT0_MEM_IN_SFT 6 +#define ACCDET_EINT0_MEM_IN_MASK 0x3 +#define ACCDET_EINT0_MEM_IN_MASK_SFT (0x3 << 6) +#define ACCDET_EINT0_STATE_ADDR \ + MT6359_ACCDET_CON26 +#define ACCDET_EINT0_STATE_SFT 8 +#define ACCDET_EINT0_STATE_MASK 0x7 +#define ACCDET_EINT0_STATE_MASK_SFT (0x7 << 8) +#define DA_EINT0CMPEN_ADDR \ + MT6359_ACCDET_CON26 +#define DA_EINT0CMPEN_SFT 13 +#define DA_EINT0CMPEN_MASK 0x1 +#define DA_EINT0CMPEN_MASK_SFT (0x1 << 13) +#define DA_EINT0CMPMEN_ADDR \ + MT6359_ACCDET_CON26 +#define DA_EINT0CMPMEN_SFT 14 +#define DA_EINT0CMPMEN_MASK 0x1 +#define DA_EINT0CMPMEN_MASK_SFT (0x1 << 14) +#define DA_EINT0CTURBO_ADDR \ + MT6359_ACCDET_CON26 +#define DA_EINT0CTURBO_SFT 15 +#define DA_EINT0CTURBO_MASK 0x1 +#define DA_EINT0CTURBO_MASK_SFT (0x1 << 15) +#define AD_EINT1CMPMOUT_ADDR \ + MT6359_ACCDET_CON27 +#define AD_EINT1CMPMOUT_SFT 0 +#define AD_EINT1CMPMOUT_MASK 0x1 +#define AD_EINT1CMPMOUT_MASK_SFT (0x1 << 0) +#define AD_EINT1CMPOUT_ADDR \ + MT6359_ACCDET_CON27 +#define AD_EINT1CMPOUT_SFT 1 +#define AD_EINT1CMPOUT_MASK 0x1 +#define AD_EINT1CMPOUT_MASK_SFT (0x1 << 1) +#define ACCDET_EINT1_CUR_IN_ADDR \ + MT6359_ACCDET_CON27 +#define ACCDET_EINT1_CUR_IN_SFT 2 +#define ACCDET_EINT1_CUR_IN_MASK 0x3 +#define ACCDET_EINT1_CUR_IN_MASK_SFT (0x3 << 2) +#define ACCDET_EINT1_SAM_IN_ADDR \ + MT6359_ACCDET_CON27 +#define ACCDET_EINT1_SAM_IN_SFT 4 +#define ACCDET_EINT1_SAM_IN_MASK 0x3 +#define ACCDET_EINT1_SAM_IN_MASK_SFT (0x3 << 4) +#define ACCDET_EINT1_MEM_IN_ADDR \ + MT6359_ACCDET_CON27 +#define ACCDET_EINT1_MEM_IN_SFT 6 +#define ACCDET_EINT1_MEM_IN_MASK 0x3 +#define ACCDET_EINT1_MEM_IN_MASK_SFT (0x3 << 6) +#define ACCDET_EINT1_STATE_ADDR \ + MT6359_ACCDET_CON27 +#define ACCDET_EINT1_STATE_SFT 8 +#define ACCDET_EINT1_STATE_MASK 0x7 +#define ACCDET_EINT1_STATE_MASK_SFT (0x7 << 8) +#define DA_EINT1CMPEN_ADDR \ + MT6359_ACCDET_CON27 +#define DA_EINT1CMPEN_SFT 13 +#define DA_EINT1CMPEN_MASK 0x1 +#define DA_EINT1CMPEN_MASK_SFT (0x1 << 13) +#define DA_EINT1CMPMEN_ADDR \ + MT6359_ACCDET_CON27 +#define DA_EINT1CMPMEN_SFT 14 +#define DA_EINT1CMPMEN_MASK 0x1 +#define DA_EINT1CMPMEN_MASK_SFT (0x1 << 14) +#define DA_EINT1CTURBO_ADDR \ + MT6359_ACCDET_CON27 +#define DA_EINT1CTURBO_SFT 15 +#define DA_EINT1CTURBO_MASK 0x1 +#define DA_EINT1CTURBO_MASK_SFT (0x1 << 15) +#define AD_EINT0INVOUT_ADDR \ + MT6359_ACCDET_CON28 +#define AD_EINT0INVOUT_SFT 0 +#define AD_EINT0INVOUT_MASK 0x1 +#define AD_EINT0INVOUT_MASK_SFT (0x1 << 0) +#define ACCDET_EINT0_INVERTER_CUR_IN_ADDR \ + MT6359_ACCDET_CON28 +#define ACCDET_EINT0_INVERTER_CUR_IN_SFT 1 +#define ACCDET_EINT0_INVERTER_CUR_IN_MASK 0x1 +#define ACCDET_EINT0_INVERTER_CUR_IN_MASK_SFT (0x1 << 1) +#define ACCDET_EINT0_INVERTER_SAM_IN_ADDR \ + MT6359_ACCDET_CON28 +#define ACCDET_EINT0_INVERTER_SAM_IN_SFT 2 +#define ACCDET_EINT0_INVERTER_SAM_IN_MASK 0x1 +#define ACCDET_EINT0_INVERTER_SAM_IN_MASK_SFT (0x1 << 2) +#define ACCDET_EINT0_INVERTER_MEM_IN_ADDR \ + MT6359_ACCDET_CON28 +#define ACCDET_EINT0_INVERTER_MEM_IN_SFT 3 +#define ACCDET_EINT0_INVERTER_MEM_IN_MASK 0x1 +#define ACCDET_EINT0_INVERTER_MEM_IN_MASK_SFT (0x1 << 3) +#define ACCDET_EINT0_INVERTER_STATE_ADDR \ + MT6359_ACCDET_CON28 +#define ACCDET_EINT0_INVERTER_STATE_SFT 8 +#define ACCDET_EINT0_INVERTER_STATE_MASK 0x7 +#define ACCDET_EINT0_INVERTER_STATE_MASK_SFT (0x7 << 8) +#define DA_EINT0EN_ADDR \ + MT6359_ACCDET_CON28 +#define DA_EINT0EN_SFT 12 +#define DA_EINT0EN_MASK 0x1 +#define DA_EINT0EN_MASK_SFT (0x1 << 12) +#define DA_EINT0INVEN_ADDR \ + MT6359_ACCDET_CON28 +#define DA_EINT0INVEN_SFT 13 +#define DA_EINT0INVEN_MASK 0x1 +#define DA_EINT0INVEN_MASK_SFT (0x1 << 13) +#define DA_EINT0CEN_ADDR \ + MT6359_ACCDET_CON28 +#define DA_EINT0CEN_SFT 14 +#define DA_EINT0CEN_MASK 0x1 +#define DA_EINT0CEN_MASK_SFT (0x1 << 14) +#define AD_EINT1INVOUT_ADDR \ + MT6359_ACCDET_CON29 +#define AD_EINT1INVOUT_SFT 0 +#define AD_EINT1INVOUT_MASK 0x1 +#define AD_EINT1INVOUT_MASK_SFT (0x1 << 0) +#define ACCDET_EINT1_INVERTER_CUR_IN_ADDR \ + MT6359_ACCDET_CON29 +#define ACCDET_EINT1_INVERTER_CUR_IN_SFT 1 +#define ACCDET_EINT1_INVERTER_CUR_IN_MASK 0x1 +#define ACCDET_EINT1_INVERTER_CUR_IN_MASK_SFT (0x1 << 1) +#define ACCDET_EINT1_INVERTER_SAM_IN_ADDR \ + MT6359_ACCDET_CON29 +#define ACCDET_EINT1_INVERTER_SAM_IN_SFT 2 +#define ACCDET_EINT1_INVERTER_SAM_IN_MASK 0x1 +#define ACCDET_EINT1_INVERTER_SAM_IN_MASK_SFT (0x1 << 2) +#define ACCDET_EINT1_INVERTER_MEM_IN_ADDR \ + MT6359_ACCDET_CON29 +#define ACCDET_EINT1_INVERTER_MEM_IN_SFT 3 +#define ACCDET_EINT1_INVERTER_MEM_IN_MASK 0x1 +#define ACCDET_EINT1_INVERTER_MEM_IN_MASK_SFT (0x1 << 3) +#define ACCDET_EINT1_INVERTER_STATE_ADDR \ + MT6359_ACCDET_CON29 +#define ACCDET_EINT1_INVERTER_STATE_SFT 8 +#define ACCDET_EINT1_INVERTER_STATE_MASK 0x7 +#define ACCDET_EINT1_INVERTER_STATE_MASK_SFT (0x7 << 8) +#define DA_EINT1EN_ADDR \ + MT6359_ACCDET_CON29 +#define DA_EINT1EN_SFT 12 +#define DA_EINT1EN_MASK 0x1 +#define DA_EINT1EN_MASK_SFT (0x1 << 12) +#define DA_EINT1INVEN_ADDR \ + MT6359_ACCDET_CON29 +#define DA_EINT1INVEN_SFT 13 +#define DA_EINT1INVEN_MASK 0x1 +#define DA_EINT1INVEN_MASK_SFT (0x1 << 13) +#define DA_EINT1CEN_ADDR \ + MT6359_ACCDET_CON29 +#define DA_EINT1CEN_SFT 14 +#define DA_EINT1CEN_MASK 0x1 +#define DA_EINT1CEN_MASK_SFT (0x1 << 14) +#define ACCDET_EN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EN_SFT 0 +#define ACCDET_EN_MASK 0x1 +#define ACCDET_EN_MASK_SFT (0x1 << 0) +#define ACCDET_EINT0_EN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT0_EN_SFT 1 +#define ACCDET_EINT0_EN_MASK 0x1 +#define ACCDET_EINT0_EN_MASK_SFT (0x1 << 1) +#define ACCDET_EINT1_EN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT1_EN_SFT 2 +#define ACCDET_EINT1_EN_MASK 0x1 +#define ACCDET_EINT1_EN_MASK_SFT (0x1 << 2) +#define ACCDET_EINT0_M_EN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT0_M_EN_SFT 3 +#define ACCDET_EINT0_M_EN_MASK 0x1 +#define ACCDET_EINT0_M_EN_MASK_SFT (0x1 << 3) +#define ACCDET_EINT0_DETECT_MOISTURE_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT0_DETECT_MOISTURE_SFT 4 +#define ACCDET_EINT0_DETECT_MOISTURE_MASK 0x1 +#define ACCDET_EINT0_DETECT_MOISTURE_MASK_SFT (0x1 << 4) +#define ACCDET_EINT0_PLUG_IN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT0_PLUG_IN_SFT 5 +#define ACCDET_EINT0_PLUG_IN_MASK 0x1 +#define ACCDET_EINT0_PLUG_IN_MASK_SFT (0x1 << 5) +#define ACCDET_EINT0_M_PLUG_IN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT0_M_PLUG_IN_SFT 6 +#define ACCDET_EINT0_M_PLUG_IN_MASK 0x1 +#define ACCDET_EINT0_M_PLUG_IN_MASK_SFT (0x1 << 6) +#define ACCDET_EINT1_M_EN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT1_M_EN_SFT 7 +#define ACCDET_EINT1_M_EN_MASK 0x1 +#define ACCDET_EINT1_M_EN_MASK_SFT (0x1 << 7) +#define ACCDET_EINT1_DETECT_MOISTURE_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT1_DETECT_MOISTURE_SFT 8 +#define ACCDET_EINT1_DETECT_MOISTURE_MASK 0x1 +#define ACCDET_EINT1_DETECT_MOISTURE_MASK_SFT (0x1 << 8) +#define ACCDET_EINT1_PLUG_IN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT1_PLUG_IN_SFT 9 +#define ACCDET_EINT1_PLUG_IN_MASK 0x1 +#define ACCDET_EINT1_PLUG_IN_MASK_SFT (0x1 << 9) +#define ACCDET_EINT1_M_PLUG_IN_ADDR \ + MT6359_ACCDET_CON30 +#define ACCDET_EINT1_M_PLUG_IN_SFT 10 +#define ACCDET_EINT1_M_PLUG_IN_MASK 0x1 +#define ACCDET_EINT1_M_PLUG_IN_MASK_SFT (0x1 << 10) +#define ACCDET_CUR_DEB_ADDR \ + MT6359_ACCDET_CON31 +#define ACCDET_CUR_DEB_SFT 0 +#define ACCDET_CUR_DEB_MASK 0xFFFF +#define ACCDET_CUR_DEB_MASK_SFT (0xFFFF << 0) +#define ACCDET_EINT0_CUR_DEB_ADDR \ + MT6359_ACCDET_CON32 +#define ACCDET_EINT0_CUR_DEB_SFT 0 +#define ACCDET_EINT0_CUR_DEB_MASK 0x7FFF +#define ACCDET_EINT0_CUR_DEB_MASK_SFT (0x7FFF << 0) +#define ACCDET_EINT1_CUR_DEB_ADDR \ + MT6359_ACCDET_CON33 +#define ACCDET_EINT1_CUR_DEB_SFT 0 +#define ACCDET_EINT1_CUR_DEB_MASK 0x7FFF +#define ACCDET_EINT1_CUR_DEB_MASK_SFT (0x7FFF << 0) +#define ACCDET_EINT0_INVERTER_CUR_DEB_ADDR \ + MT6359_ACCDET_CON34 +#define ACCDET_EINT0_INVERTER_CUR_DEB_SFT 0 +#define ACCDET_EINT0_INVERTER_CUR_DEB_MASK 0x7FFF +#define ACCDET_EINT0_INVERTER_CUR_DEB_MASK_SFT (0x7FFF << 0) +#define ACCDET_EINT1_INVERTER_CUR_DEB_ADDR \ + MT6359_ACCDET_CON35 +#define ACCDET_EINT1_INVERTER_CUR_DEB_SFT 0 +#define ACCDET_EINT1_INVERTER_CUR_DEB_MASK 0x7FFF +#define ACCDET_EINT1_INVERTER_CUR_DEB_MASK_SFT (0x7FFF << 0) +#define AD_AUDACCDETCMPOB_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_AUDACCDETCMPOB_MON_SFT 0 +#define AD_AUDACCDETCMPOB_MON_MASK 0x1 +#define AD_AUDACCDETCMPOB_MON_MASK_SFT (0x1 << 0) +#define AD_AUDACCDETCMPOA_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_AUDACCDETCMPOA_MON_SFT 1 +#define AD_AUDACCDETCMPOA_MON_MASK 0x1 +#define AD_AUDACCDETCMPOA_MON_MASK_SFT (0x1 << 1) +#define AD_EINT0CMPMOUT_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_EINT0CMPMOUT_MON_SFT 2 +#define AD_EINT0CMPMOUT_MON_MASK 0x1 +#define AD_EINT0CMPMOUT_MON_MASK_SFT (0x1 << 2) +#define AD_EINT0CMPOUT_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_EINT0CMPOUT_MON_SFT 3 +#define AD_EINT0CMPOUT_MON_MASK 0x1 +#define AD_EINT0CMPOUT_MON_MASK_SFT (0x1 << 3) +#define AD_EINT0INVOUT_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_EINT0INVOUT_MON_SFT 4 +#define AD_EINT0INVOUT_MON_MASK 0x1 +#define AD_EINT0INVOUT_MON_MASK_SFT (0x1 << 4) +#define AD_EINT1CMPMOUT_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_EINT1CMPMOUT_MON_SFT 5 +#define AD_EINT1CMPMOUT_MON_MASK 0x1 +#define AD_EINT1CMPMOUT_MON_MASK_SFT (0x1 << 5) +#define AD_EINT1CMPOUT_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_EINT1CMPOUT_MON_SFT 6 +#define AD_EINT1CMPOUT_MON_MASK 0x1 +#define AD_EINT1CMPOUT_MON_MASK_SFT (0x1 << 6) +#define AD_EINT1INVOUT_MON_ADDR \ + MT6359_ACCDET_CON36 +#define AD_EINT1INVOUT_MON_SFT 7 +#define AD_EINT1INVOUT_MON_MASK 0x1 +#define AD_EINT1INVOUT_MON_MASK_SFT (0x1 << 7) +#define DA_AUDACCDETCMPCLK_MON_ADDR \ + MT6359_ACCDET_CON37 +#define DA_AUDACCDETCMPCLK_MON_SFT 0 +#define DA_AUDACCDETCMPCLK_MON_MASK 0x1 +#define DA_AUDACCDETCMPCLK_MON_MASK_SFT (0x1 << 0) +#define DA_AUDACCDETVTHCLK_MON_ADDR \ + MT6359_ACCDET_CON37 +#define DA_AUDACCDETVTHCLK_MON_SFT 1 +#define DA_AUDACCDETVTHCLK_MON_MASK 0x1 +#define DA_AUDACCDETVTHCLK_MON_MASK_SFT (0x1 << 1) +#define DA_AUDACCDETMBIASCLK_MON_ADDR \ + MT6359_ACCDET_CON37 +#define DA_AUDACCDETMBIASCLK_MON_SFT 2 +#define DA_AUDACCDETMBIASCLK_MON_MASK 0x1 +#define DA_AUDACCDETMBIASCLK_MON_MASK_SFT (0x1 << 2) +#define DA_AUDACCDETAUXADCSWCTRL_MON_ADDR \ + MT6359_ACCDET_CON37 +#define DA_AUDACCDETAUXADCSWCTRL_MON_SFT 3 +#define DA_AUDACCDETAUXADCSWCTRL_MON_MASK 0x1 +#define DA_AUDACCDETAUXADCSWCTRL_MON_MASK_SFT (0x1 << 3) +#define DA_EINT0CTURBO_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT0CTURBO_MON_SFT 0 +#define DA_EINT0CTURBO_MON_MASK 0x1 +#define DA_EINT0CTURBO_MON_MASK_SFT (0x1 << 0) +#define DA_EINT0CMPMEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT0CMPMEN_MON_SFT 1 +#define DA_EINT0CMPMEN_MON_MASK 0x1 +#define DA_EINT0CMPMEN_MON_MASK_SFT (0x1 << 1) +#define DA_EINT0CMPEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT0CMPEN_MON_SFT 2 +#define DA_EINT0CMPEN_MON_MASK 0x1 +#define DA_EINT0CMPEN_MON_MASK_SFT (0x1 << 2) +#define DA_EINT0INVEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT0INVEN_MON_SFT 3 +#define DA_EINT0INVEN_MON_MASK 0x1 +#define DA_EINT0INVEN_MON_MASK_SFT (0x1 << 3) +#define DA_EINT0CEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT0CEN_MON_SFT 4 +#define DA_EINT0CEN_MON_MASK 0x1 +#define DA_EINT0CEN_MON_MASK_SFT (0x1 << 4) +#define DA_EINT0EN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT0EN_MON_SFT 5 +#define DA_EINT0EN_MON_MASK 0x1 +#define DA_EINT0EN_MON_MASK_SFT (0x1 << 5) +#define DA_EINT1CTURBO_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT1CTURBO_MON_SFT 8 +#define DA_EINT1CTURBO_MON_MASK 0x1 +#define DA_EINT1CTURBO_MON_MASK_SFT (0x1 << 8) +#define DA_EINT1CMPMEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT1CMPMEN_MON_SFT 9 +#define DA_EINT1CMPMEN_MON_MASK 0x1 +#define DA_EINT1CMPMEN_MON_MASK_SFT (0x1 << 9) +#define DA_EINT1CMPEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT1CMPEN_MON_SFT 10 +#define DA_EINT1CMPEN_MON_MASK 0x1 +#define DA_EINT1CMPEN_MON_MASK_SFT (0x1 << 10) +#define DA_EINT1INVEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT1INVEN_MON_SFT 11 +#define DA_EINT1INVEN_MON_MASK 0x1 +#define DA_EINT1INVEN_MON_MASK_SFT (0x1 << 11) +#define DA_EINT1CEN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT1CEN_MON_SFT 12 +#define DA_EINT1CEN_MON_MASK 0x1 +#define DA_EINT1CEN_MON_MASK_SFT (0x1 << 12) +#define DA_EINT1EN_MON_ADDR \ + MT6359_ACCDET_CON38 +#define DA_EINT1EN_MON_SFT 13 +#define DA_EINT1EN_MON_MASK 0x1 +#define DA_EINT1EN_MON_MASK_SFT (0x1 << 13) +#define ACCDET_EINT0_M_PLUG_IN_COUNT_ADDR \ + MT6359_ACCDET_CON39 +#define ACCDET_EINT0_M_PLUG_IN_COUNT_SFT 0 +#define ACCDET_EINT0_M_PLUG_IN_COUNT_MASK 0x7 +#define ACCDET_EINT0_M_PLUG_IN_COUNT_MASK_SFT (0x7 << 0) +#define ACCDET_EINT1_M_PLUG_IN_COUNT_ADDR \ + MT6359_ACCDET_CON39 +#define ACCDET_EINT1_M_PLUG_IN_COUNT_SFT 4 +#define ACCDET_EINT1_M_PLUG_IN_COUNT_MASK 0x7 +#define ACCDET_EINT1_M_PLUG_IN_COUNT_MASK_SFT (0x7 << 4) +#define ACCDET_MON_FLAG_EN_ADDR \ + MT6359_ACCDET_CON40 +#define ACCDET_MON_FLAG_EN_SFT 0 +#define ACCDET_MON_FLAG_EN_MASK 0x1 +#define ACCDET_MON_FLAG_EN_MASK_SFT (0x1 << 0) +#define ACCDET_MON_FLAG_SEL_ADDR \ + MT6359_ACCDET_CON40 +#define ACCDET_MON_FLAG_SEL_SFT 4 +#define ACCDET_MON_FLAG_SEL_MASK 0xF +#define ACCDET_MON_FLAG_SEL_MASK_SFT (0xF << 4) + +#define RG_AUDPWDBMICBIAS0_ADDR \ + MT6359_AUDENC_ANA_CON15 +#define RG_AUDPWDBMICBIAS0_SFT 0 +#define RG_AUDPWDBMICBIAS0_MASK 0x1 +#define RG_AUDPWDBMICBIAS0_MASK_SFT (0x1 << 0) +#define RG_AUDPREAMPLON_ADDR \ + MT6359_AUDENC_ANA_CON0 +#define RG_AUDPREAMPLON_SFT 0 +#define RG_AUDPREAMPLON_MASK 0x1 +#define RG_AUDPREAMPLON_MASK_SFT (0x1 << 0) +#define RG_CLKSQ_EN_ADDR \ + MT6359_AUDENC_ANA_CON23 +#define RG_CLKSQ_EN_SFT 0 +#define RG_CLKSQ_EN_MASK 0x1 +#define RG_CLKSQ_EN_MASK_SFT (0x1 << 0) +#define RG_RTC32K_CK_PDN_ADDR \ + MT6359_TOP_CKPDN_CON0 +#define RG_RTC32K_CK_PDN_SFT 15 +#define RG_RTC32K_CK_PDN_MASK 0x1 +#define RG_RTC32K_CK_PDN_MASK_SFT (0x1 << 15) +#define RG_HPLOUTPUTSTBENH_VAUDP32_ADDR \ + MT6359_AUDDEC_ANA_CON2 +#define RG_HPLOUTPUTSTBENH_VAUDP32_SFT 0 +#define RG_HPLOUTPUTSTBENH_VAUDP32_MASK 0x7 +#define RG_HPLOUTPUTSTBENH_VAUDP32_MASK_SFT (0x7 << 0) +#define AUXADC_RQST_CH5_ADDR \ + MT6359_AUXADC_RQST0 +#define AUXADC_RQST_CH5_SFT 5 +#define AUXADC_RQST_CH5_MASK 0x1 +#define AUXADC_RQST_CH5_MASK_SFT (0x1 << 5) +#define RG_LDO_VUSB_HW0_OP_EN_ADDR \ + MT6359_LDO_VUSB_OP_EN +#define RG_LDO_VUSB_HW0_OP_EN_SFT 0 +#define RG_LDO_VUSB_HW0_OP_EN_MASK 0x1 +#define RG_LDO_VUSB_HW0_OP_EN_MASK_SFT (0x1 << 0) +#define RG_HPROUTPUTSTBENH_VAUDP32_ADDR \ + MT6359_AUDDEC_ANA_CON2 +#define RG_HPROUTPUTSTBENH_VAUDP32_SFT 4 +#define RG_HPROUTPUTSTBENH_VAUDP32_MASK 0x7 +#define RG_HPROUTPUTSTBENH_VAUDP32_MASK_SFT (0x7 << 4) +#define RG_NCP_PDDIS_EN_ADDR \ + MT6359_AFE_NCP_CFG2 +#define RG_NCP_PDDIS_EN_SFT 0 +#define RG_NCP_PDDIS_EN_MASK 0x1 +#define RG_NCP_PDDIS_EN_MASK_SFT (0x1 << 0) +#define RG_SCK32K_CK_PDN_ADDR \ + MT6359_TOP_CKPDN_CON0 +#define RG_SCK32K_CK_PDN_SFT 0 +#define RG_SCK32K_CK_PDN_MASK 0x1 +#define RG_SCK32K_CK_PDN_MASK_SFT (0x1 << 0) /* AUDENC_ANA_CON18: */ -#define RG_ACCDET_MODE_ANA11_MODE1 (0x000f) -#define RG_ACCDET_MODE_ANA11_MODE2 (0x008f) -#define RG_ACCDET_MODE_ANA11_MODE6 (0x008f) +#define RG_ACCDET_MODE_ANA11_MODE1 (0x000F) +#define RG_ACCDET_MODE_ANA11_MODE2 (0x008F) +#define RG_ACCDET_MODE_ANA11_MODE6 (0x008F) /* AUXADC_ADC5: Auxadc CH5 read data */ #define AUXADC_DATA_RDY_CH5 BIT(15) #define AUXADC_DATA_PROCEED_CH5 BIT(15) -#define AUXADC_DATA_MASK (0x0fff) +#define AUXADC_DATA_MASK (0x0FFF) /* AUXADC_RQST0_SET: Auxadc CH5 request, relevant 0x07EC */ #define AUXADC_RQST_CH5_SET BIT(5) /* AUXADC_RQST0_CLR: Auxadc CH5 request, relevant 0x07EC */ #define AUXADC_RQST_CH5_CLR BIT(5) -#define ACCDET_CALI_MASK0 (0xff) -#define ACCDET_CALI_MASK1 (0xff << 8) -#define ACCDET_CALI_MASK2 (0xff) -#define ACCDET_CALI_MASK3 (0xff << 8) -#define ACCDET_CALI_MASK4 (0xff) +#define ACCDET_CALI_MASK0 (0xFF) +#define ACCDET_CALI_MASK1 (0xFF << 8) +#define ACCDET_CALI_MASK2 (0xFF) +#define ACCDET_CALI_MASK3 (0xFF << 8) +#define ACCDET_CALI_MASK4 (0xFF) -#define ACCDET_EINT1_IRQ_CLR_B11 BIT(PMIC_ACCDET_EINT1_IRQ_CLR_SHIFT) -#define ACCDET_EINT0_IRQ_CLR_B10 BIT(PMIC_ACCDET_EINT0_IRQ_CLR_SHIFT) -#define ACCDET_EINT_IRQ_CLR_B10_11 (0x03 << \ - PMIC_ACCDET_EINT0_IRQ_CLR_SHIFT) -#define ACCDET_IRQ_CLR_B8 BIT(PMIC_ACCDET_IRQ_CLR_SHIFT) - -#define ACCDET_EINT1_IRQ_B3 BIT(PMIC_ACCDET_EINT1_IRQ_SHIFT) -#define ACCDET_EINT0_IRQ_B2 BIT(PMIC_ACCDET_EINT0_IRQ_SHIFT) -#define ACCDET_EINT_IRQ_B2_B3 (0x03 << PMIC_ACCDET_EINT0_IRQ_SHIFT) -#define ACCDET_IRQ_B0 BIT(PMIC_ACCDET_IRQ_SHIFT) +#define ACCDET_EINT_IRQ_B2_B3 (0x03 << ACCDET_EINT0_IRQ_SFT) /* ACCDET_CON25: RO, accdet FSM state,etc.*/ -#define ACCDET_STATE_MEM_IN_OFFSET (PMIC_ACCDET_MEM_IN_SHIFT) -#define ACCDET_STATE_AB_MASK (0x03) -#define ACCDET_STATE_AB_00 (0x00) -#define ACCDET_STATE_AB_01 (0x01) -#define ACCDET_STATE_AB_10 (0x02) -#define ACCDET_STATE_AB_11 (0x03) +#define ACCDET_STATE_MEM_IN_OFFSET (ACCDET_MEM_IN_SFT) +#define ACCDET_STATE_AB_MASK (0x03) +#define ACCDET_STATE_AB_00 (0x00) +#define ACCDET_STATE_AB_01 (0x01) +#define ACCDET_STATE_AB_10 (0x02) +#define ACCDET_STATE_AB_11 (0x03) /* ACCDET_CON19 */ -#define ACCDET_EINT0_STABLE_VAL ((1 << PMIC_ACCDET_DA_STABLE_SHIFT) | \ - (1 << PMIC_ACCDET_EINT0_EN_STABLE_SHIFT) | \ - (1 << PMIC_ACCDET_EINT0_CMPEN_STABLE_SHIFT) | \ - (1 << PMIC_ACCDET_EINT0_CEN_STABLE_SHIFT)) - -#define ACCDET_EINT1_STABLE_VAL ((1 << PMIC_ACCDET_DA_STABLE_SHIFT) | \ - (1 << PMIC_ACCDET_EINT1_EN_STABLE_SHIFT) | \ - (1 << PMIC_ACCDET_EINT1_CMPEN_STABLE_SHIFT) | \ - (1 << PMIC_ACCDET_EINT1_CEN_STABLE_SHIFT)) +#define ACCDET_EINT0_STABLE_VAL ((ACCDET_DA_STABLE_MASK_SFT) | \ + (ACCDET_EINT0_EN_STABLE_MASK_SFT) | \ + (ACCDET_EINT0_CMPEN_STABLE_MASK_SFT) | \ + (ACCDET_EINT0_CEN_STABLE_MASK_SFT)) +#define ACCDET_EINT1_STABLE_VAL ((ACCDET_DA_STABLE_MASK_SFT) | \ + (ACCDET_EINT1_EN_STABLE_MASK_SFT) | \ + (ACCDET_EINT1_CMPEN_STABLE_MASK_SFT) | \ + (ACCDET_EINT1_CEN_STABLE_MASK_SFT)) /* The following are used for mt6359.c */ /* MT6359_DCXO_CW12 */ #define RG_XO_AUDIO_EN_M_SFT 13 From ff132c5f93c06bd4432bbab5c369e468653bdec4 Mon Sep 17 00:00:00 2001 From: Bob Peterson Date: Thu, 25 Mar 2021 08:51:13 -0400 Subject: [PATCH 0407/1091] gfs2: report "already frozen/thawed" errors Before this patch, gfs2's freeze function failed to report an error when the target file system was already frozen as it should (and as generic vfs function freeze_super does. Similarly, gfs2's thaw function failed to report an error when trying to thaw a file system that is not frozen, as vfs function thaw_super does. The errors were checked, but it always returned a 0 return code. This patch adds the missing error return codes to gfs2 freeze and thaw. Signed-off-by: Bob Peterson Signed-off-by: Andreas Gruenbacher --- fs/gfs2/super.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/fs/gfs2/super.c b/fs/gfs2/super.c index 9e91c9d92bd6..8fb9602d79b4 100644 --- a/fs/gfs2/super.c +++ b/fs/gfs2/super.c @@ -752,11 +752,13 @@ void gfs2_freeze_func(struct work_struct *work) static int gfs2_freeze(struct super_block *sb) { struct gfs2_sbd *sdp = sb->s_fs_info; - int error = 0; + int error; mutex_lock(&sdp->sd_freeze_mutex); - if (atomic_read(&sdp->sd_freeze_state) != SFS_UNFROZEN) + if (atomic_read(&sdp->sd_freeze_state) != SFS_UNFROZEN) { + error = -EBUSY; goto out; + } for (;;) { if (gfs2_withdrawn(sdp)) { @@ -797,10 +799,10 @@ static int gfs2_unfreeze(struct super_block *sb) struct gfs2_sbd *sdp = sb->s_fs_info; mutex_lock(&sdp->sd_freeze_mutex); - if (atomic_read(&sdp->sd_freeze_state) != SFS_FROZEN || + if (atomic_read(&sdp->sd_freeze_state) != SFS_FROZEN || !gfs2_holder_initialized(&sdp->sd_freeze_gh)) { mutex_unlock(&sdp->sd_freeze_mutex); - return 0; + return -EINVAL; } gfs2_freeze_unlock(&sdp->sd_freeze_gh); From 60c988bc154108bd522a21289e389143006a1ff0 Mon Sep 17 00:00:00 2001 From: Daniel Jordan Date: Wed, 24 Mar 2021 21:05:52 -0400 Subject: [PATCH 0408/1091] vfio/type1: Empty batch for pfnmap pages When vfio_pin_pages_remote() returns with a partial batch consisting of a single VM_PFNMAP pfn, a subsequent call will unfortunately try restoring it from batch->pages, resulting in vfio mapping the wrong page and unbalancing the page refcount. Prevent the function from returning with this kind of partial batch to avoid the issue. There's no explicit check for a VM_PFNMAP pfn because it's awkward to do so, so infer it from characteristics of the batch instead. This may result in occasional false positives but keeps the code simpler. Fixes: 4d83de6da265 ("vfio/type1: Batch page pinning") Link: https://lkml.kernel.org/r/20210323133254.33ed9161@omen.home.shazbot.org/ Reported-by: Alex Williamson Suggested-by: Alex Williamson Signed-off-by: Daniel Jordan Message-Id: <20210325010552.185481-1-daniel.m.jordan@oracle.com> Signed-off-by: Alex Williamson --- drivers/vfio/vfio_iommu_type1.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c index be444407664a..45cbfd4879a5 100644 --- a/drivers/vfio/vfio_iommu_type1.c +++ b/drivers/vfio/vfio_iommu_type1.c @@ -739,6 +739,12 @@ out: ret = vfio_lock_acct(dma, lock_acct, false); unpin_out: + if (batch->size == 1 && !batch->offset) { + /* May be a VM_PFNMAP pfn, which the batch can't remember. */ + put_pfn(pfn, dma->prot); + batch->size = 0; + } + if (ret < 0) { if (pinned && !rsvd) { for (pfn = *pfn_base ; pinned ; pfn++, pinned--) From 347b5650cd158d1d953487cc2bec567af5c5bf96 Mon Sep 17 00:00:00 2001 From: Eryk Rybak Date: Thu, 18 Feb 2021 11:15:26 +0000 Subject: [PATCH 0409/1091] i40e: Fix kernel oops when i40e driver removes VF's Fix the reason of kernel oops when i40e driver removed VFs. Added new __I40E_VFS_RELEASING state to signalize releasing process by PF, that it makes possible to exit of reset VF procedure. Without this patch, it is possible to suspend the VFs reset by releasing VFs resources procedure. Retrying the reset after the timeout works on the freed VF memory causing a kernel oops. Fixes: d43d60e5eb95 ("i40e: ensure reset occurs when disabling VF") Signed-off-by: Eryk Rybak Signed-off-by: Grzegorz Szczurek Reviewed-by: Aleksandr Loktionov Tested-by: Konrad Jankowski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e.h | 1 + drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c | 9 +++++++++ 2 files changed, 10 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e.h b/drivers/net/ethernet/intel/i40e/i40e.h index cd53981fa5e0..15f93b355099 100644 --- a/drivers/net/ethernet/intel/i40e/i40e.h +++ b/drivers/net/ethernet/intel/i40e/i40e.h @@ -142,6 +142,7 @@ enum i40e_state_t { __I40E_VIRTCHNL_OP_PENDING, __I40E_RECOVERY_MODE, __I40E_VF_RESETS_DISABLED, /* disable resets during i40e_remove */ + __I40E_VFS_RELEASING, /* This must be last as it determines the size of the BITMAP */ __I40E_STATE_SIZE__, }; diff --git a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c index 1b6ec9be155a..5d301a466f5c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c +++ b/drivers/net/ethernet/intel/i40e/i40e_virtchnl_pf.c @@ -137,6 +137,7 @@ void i40e_vc_notify_vf_reset(struct i40e_vf *vf) **/ static inline void i40e_vc_disable_vf(struct i40e_vf *vf) { + struct i40e_pf *pf = vf->pf; int i; i40e_vc_notify_vf_reset(vf); @@ -147,6 +148,11 @@ static inline void i40e_vc_disable_vf(struct i40e_vf *vf) * ensure a reset. */ for (i = 0; i < 20; i++) { + /* If PF is in VFs releasing state reset VF is impossible, + * so leave it. + */ + if (test_bit(__I40E_VFS_RELEASING, pf->state)) + return; if (i40e_reset_vf(vf, false)) return; usleep_range(10000, 20000); @@ -1574,6 +1580,8 @@ void i40e_free_vfs(struct i40e_pf *pf) if (!pf->vf) return; + + set_bit(__I40E_VFS_RELEASING, pf->state); while (test_and_set_bit(__I40E_VF_DISABLE, pf->state)) usleep_range(1000, 2000); @@ -1631,6 +1639,7 @@ void i40e_free_vfs(struct i40e_pf *pf) } } clear_bit(__I40E_VF_DISABLE, pf->state); + clear_bit(__I40E_VFS_RELEASING, pf->state); } #ifdef CONFIG_PCI_IOV From f2916ae9a1bc80aa8e9e8a00b75682f5df6fd59c Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Thu, 18 Feb 2021 21:55:35 +0000 Subject: [PATCH 0410/1091] i40e: Fix oops at i40e_rebuild() Setup TC before the i40e_setup_pf_switch() call. Memory must be initialized for all the queues before using its resources. Previously it could be possible that a call: xdp_rxq_info_reg(&rx_ring->xdp_rxq, rx_ring->netdev, rx_ring->queue_index, rx_ring->q_vector->napi.napi_id); was made with q_vector being null. Oops could show up with the following sequence: - no driver loaded - FW LLDP agent is on (flag disable-fw-lldp:off) - link is up - DCB configured with number of Traffic Classes that will not divide completely the default number of queues (usually cpu cores) - driver load - set private flag: disable-fw-lldp:on Fixes: 4b208eaa8078 ("i40e: Add init and default config of software based DCB") Fixes: b02e5a0ebb17 ("xsk: Propagate napi_id to XDP socket Rx path") Signed-off-by: Aleksandr Loktionov Signed-off-by: Arkadiusz Kubalewski Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_main.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 17f3b800640e..f67f0cc9dadf 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -10573,12 +10573,6 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) goto end_core_reset; } - if (!lock_acquired) - rtnl_lock(); - ret = i40e_setup_pf_switch(pf, reinit); - if (ret) - goto end_unlock; - #ifdef CONFIG_I40E_DCB /* Enable FW to write a default DCB config on link-up * unless I40E_FLAG_TC_MQPRIO was enabled or DCB @@ -10607,6 +10601,11 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) } #endif /* CONFIG_I40E_DCB */ + if (!lock_acquired) + rtnl_lock(); + ret = i40e_setup_pf_switch(pf, reinit); + if (ret) + goto end_unlock; /* The driver only wants link up/down and module qualification * reports from firmware. Note the negative logic. From 72bbc226ed2ef0a46c165a482861fff00dd6d4e1 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Tue, 23 Mar 2021 21:40:11 +0100 Subject: [PATCH 0411/1091] s390/vdso: copy tod_steering_delta value to vdso_data page When converting the vdso assembler code to C it was forgotten to actually copy the tod_steering_delta value to vdso_data page. Which in turn means that tod clock steering will not work correctly. Fix this by simply copying the value whenever it is updated. Fixes: 4bff8cb54502 ("s390: convert to GENERIC_VDSO") Cc: # 5.10 Signed-off-by: Heiko Carstens --- arch/s390/kernel/time.c | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index 165da961f901..e37285a5101b 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -382,6 +382,7 @@ static void clock_sync_global(unsigned long delta) tod_steering_delta); tod_steering_end = now + (abs(tod_steering_delta) << 15); vdso_data->arch_data.tod_steering_end = tod_steering_end; + vdso_data->arch_data.tod_steering_delta = tod_steering_delta; /* Update LPAR offset. */ if (ptff_query(PTFF_QTO) && ptff(&qto, sizeof(qto), PTFF_QTO) == 0) From b24bacd67ffddd9192c4745500fd6f73dbfe565e Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 24 Mar 2021 20:22:42 +0100 Subject: [PATCH 0412/1091] s390/vdso: fix tod_steering_delta type The s390 specific vdso function __arch_get_hw_counter() is supposed to consider tod clock steering. If a tod clock steering event happens and the tod clock is set to a new value __arch_get_hw_counter() will not return the real tod clock value but slowly drift it from the old delta until the returned value finally matches the real tod clock value again. Unfortunately the type of tod_steering_delta unsigned while it is supposed to be signed. It depends on if tod_steering_delta is negative or positive in which direction the vdso code drifts the clock value. Worst case is now that instead of drifting the clock slowly it will jump into the opposite direction by a factor of two. Fix this by simply making tod_steering_delta signed. Fixes: 4bff8cb54502 ("s390: convert to GENERIC_VDSO") Cc: # 5.10 Signed-off-by: Heiko Carstens --- arch/s390/include/asm/vdso/data.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/include/asm/vdso/data.h b/arch/s390/include/asm/vdso/data.h index 7b3cdb4a5f48..73ee89142666 100644 --- a/arch/s390/include/asm/vdso/data.h +++ b/arch/s390/include/asm/vdso/data.h @@ -6,7 +6,7 @@ #include struct arch_vdso_data { - __u64 tod_steering_delta; + __s64 tod_steering_delta; __u64 tod_steering_end; }; From 5b43bd184530af6b868d8273b0a743a138d37ee8 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Wed, 24 Mar 2021 20:23:55 +0100 Subject: [PATCH 0413/1091] s390/vdso: fix initializing and updating of vdso_data Li Wang reported that clock_gettime(CLOCK_MONOTONIC_RAW, ...) returns incorrect values when time is provided via vdso instead of system call: vdso_ts_nsec = 4484351380985507, vdso_ts.tv_sec = 4484351, vdso_ts.tv_nsec = 380985507 sys_ts_nsec = 1446923235377, sys_ts.tv_sec = 1446, sys_ts.tv_nsec = 923235377 Within the s390 specific vdso function __arch_get_hw_counter() reads tod clock steering values from the arch_data member of the passed in vdso_data structure. Problem is that only for the CS_HRES_COARSE vdso_data arch_data is initialized and gets updated. The CS_RAW specific vdso_data does not contain any valid tod_clock_steering information, which explains the different values. Fix this by initializing and updating all vdso_datas. Reported-by: Li Wang Tested-by: Li Wang Fixes: 1ba2d6c0fd4e ("s390/vdso: simplify __arch_get_hw_counter()") Link: https://lore.kernel.org/linux-s390/YFnxr1ZlMIOIqjfq@osiris Signed-off-by: Heiko Carstens --- arch/s390/kernel/time.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/arch/s390/kernel/time.c b/arch/s390/kernel/time.c index e37285a5101b..326cb8f75f58 100644 --- a/arch/s390/kernel/time.c +++ b/arch/s390/kernel/time.c @@ -80,10 +80,12 @@ void __init time_early_init(void) { struct ptff_qto qto; struct ptff_qui qui; + int cs; /* Initialize TOD steering parameters */ tod_steering_end = tod_clock_base.tod; - vdso_data->arch_data.tod_steering_end = tod_steering_end; + for (cs = 0; cs < CS_BASES; cs++) + vdso_data[cs].arch_data.tod_steering_end = tod_steering_end; if (!test_facility(28)) return; @@ -366,6 +368,7 @@ static void clock_sync_global(unsigned long delta) { unsigned long now, adj; struct ptff_qto qto; + int cs; /* Fixup the monotonic sched clock. */ tod_clock_base.eitod += delta; @@ -381,8 +384,10 @@ static void clock_sync_global(unsigned long delta) panic("TOD clock sync offset %li is too large to drift\n", tod_steering_delta); tod_steering_end = now + (abs(tod_steering_delta) << 15); - vdso_data->arch_data.tod_steering_end = tod_steering_end; - vdso_data->arch_data.tod_steering_delta = tod_steering_delta; + for (cs = 0; cs < CS_BASES; cs++) { + vdso_data[cs].arch_data.tod_steering_end = tod_steering_end; + vdso_data[cs].arch_data.tod_steering_delta = tod_steering_delta; + } /* Update LPAR offset. */ if (ptff_query(PTFF_QTO) && ptff(&qto, sizeof(qto), PTFF_QTO) == 0) From 7f6c411c9b50cfab41cc798e003eff27608c7016 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Thu, 25 Mar 2021 14:12:34 -0400 Subject: [PATCH 0414/1091] hostfs: fix memory handling in follow_link() 1) argument should not be freed in any case - the caller already has it as ->s_fs_info (and uses it a lot afterwards) 2) allocate readlink buffer with kmalloc() - the caller has no way to tell if it's got that (on absolute symlink) or a result of kasprintf(). Sure, for SLAB and SLUB kfree() works on results of kmem_cache_alloc(), but that's not documented anywhere, might change in the future *and* is already not true for SLOB. Fixes: 52b209f7b848 ("get rid of hostfs_read_inode()") Signed-off-by: Al Viro --- fs/hostfs/hostfs_kern.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/fs/hostfs/hostfs_kern.c b/fs/hostfs/hostfs_kern.c index 29e407762626..743a005a5c64 100644 --- a/fs/hostfs/hostfs_kern.c +++ b/fs/hostfs/hostfs_kern.c @@ -144,7 +144,7 @@ static char *follow_link(char *link) char *name, *resolved, *end; int n; - name = __getname(); + name = kmalloc(PATH_MAX, GFP_KERNEL); if (!name) { n = -ENOMEM; goto out_free; @@ -173,12 +173,11 @@ static char *follow_link(char *link) goto out_free; } - __putname(name); - kfree(link); + kfree(name); return resolved; out_free: - __putname(name); + kfree(name); return ERR_PTR(n); } From 479dc497db8322ae486f8ee49020f5600a77a680 Mon Sep 17 00:00:00 2001 From: Vladimir Oltean Date: Wed, 24 Mar 2021 11:56:39 +0200 Subject: [PATCH 0415/1091] net: dsa: only unset VLAN filtering when last port leaves last VLAN-aware bridge DSA is aware of switches with global VLAN filtering since the blamed commit, but it makes a bad decision when multiple bridges are spanning the same switch: ip link add br0 type bridge vlan_filtering 1 ip link add br1 type bridge vlan_filtering 1 ip link set swp2 master br0 ip link set swp3 master br0 ip link set swp4 master br1 ip link set swp5 master br1 ip link set swp5 nomaster ip link set swp4 nomaster [138665.939930] sja1105 spi0.1: port 3: dsa_core: VLAN filtering is a global setting [138665.947514] DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE When all ports leave br1, DSA blindly attempts to disable VLAN filtering on the switch, ignoring the fact that br0 still exists and is VLAN-aware too. It fails while doing that. This patch checks whether any port exists at all and is under a VLAN-aware bridge. Fixes: d371b7c92d19 ("net: dsa: Unset vlan_filtering when ports leave the bridge") Signed-off-by: Vladimir Oltean Tested-by: Florian Fainelli Reviewed-by: Florian Fainelli Reviewed-by: Kurt Kanzenbach Signed-off-by: David S. Miller --- net/dsa/switch.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/net/dsa/switch.c b/net/dsa/switch.c index 4b5da89dc27a..32963276452f 100644 --- a/net/dsa/switch.c +++ b/net/dsa/switch.c @@ -107,7 +107,7 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, bool unset_vlan_filtering = br_vlan_enabled(info->br); struct dsa_switch_tree *dst = ds->dst; struct netlink_ext_ack extack = {0}; - int err, i; + int err, port; if (dst->index == info->tree_index && ds->index == info->sw_index && ds->ops->port_bridge_join) @@ -124,13 +124,16 @@ static int dsa_switch_bridge_leave(struct dsa_switch *ds, * it. That is a good thing, because that lets us handle it and also * handle the case where the switch's vlan_filtering setting is global * (not per port). When that happens, the correct moment to trigger the - * vlan_filtering callback is only when the last port left this bridge. + * vlan_filtering callback is only when the last port leaves the last + * VLAN-aware bridge. */ if (unset_vlan_filtering && ds->vlan_filtering_is_global) { - for (i = 0; i < ds->num_ports; i++) { - if (i == info->port) - continue; - if (dsa_to_port(ds, i)->bridge_dev == info->br) { + for (port = 0; port < ds->num_ports; port++) { + struct net_device *bridge_dev; + + bridge_dev = dsa_to_port(ds, port)->bridge_dev; + + if (bridge_dev && br_vlan_enabled(bridge_dev)) { unset_vlan_filtering = false; break; } From de9c7854e6e1589f639c6352112956d08243b659 Mon Sep 17 00:00:00 2001 From: Daniel Mack Date: Wed, 24 Mar 2021 14:05:36 +0100 Subject: [PATCH 0416/1091] net: axienet: allow setups without MDIO In setups with fixed-link settings there is no mdio node in DTS. axienet_probe() already handles that gracefully but lp->mii_bus is then NULL. Fix code that tries to blindly grab the MDIO lock by introducing two helper functions that make the locking conditional. Signed-off-by: Daniel Mack Reviewed-by: Radhey Shyam Pandey Signed-off-by: David S. Miller --- drivers/net/ethernet/xilinx/xilinx_axienet.h | 12 ++++++++++++ drivers/net/ethernet/xilinx/xilinx_axienet_main.c | 12 ++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet.h b/drivers/net/ethernet/xilinx/xilinx_axienet.h index 1e966a39967e..aca7f82f6791 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet.h +++ b/drivers/net/ethernet/xilinx/xilinx_axienet.h @@ -504,6 +504,18 @@ static inline u32 axinet_ior_read_mcr(struct axienet_local *lp) return axienet_ior(lp, XAE_MDIO_MCR_OFFSET); } +static inline void axienet_lock_mii(struct axienet_local *lp) +{ + if (lp->mii_bus) + mutex_lock(&lp->mii_bus->mdio_lock); +} + +static inline void axienet_unlock_mii(struct axienet_local *lp) +{ + if (lp->mii_bus) + mutex_unlock(&lp->mii_bus->mdio_lock); +} + /** * axienet_iow - Memory mapped Axi Ethernet register write * @lp: Pointer to axienet local structure diff --git a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c index 5d677db0aee5..f8f8654ea728 100644 --- a/drivers/net/ethernet/xilinx/xilinx_axienet_main.c +++ b/drivers/net/ethernet/xilinx/xilinx_axienet_main.c @@ -1053,9 +1053,9 @@ static int axienet_open(struct net_device *ndev) * including the MDIO. MDIO must be disabled before resetting. * Hold MDIO bus lock to avoid MDIO accesses during the reset. */ - mutex_lock(&lp->mii_bus->mdio_lock); + axienet_lock_mii(lp); ret = axienet_device_reset(ndev); - mutex_unlock(&lp->mii_bus->mdio_lock); + axienet_unlock_mii(lp); ret = phylink_of_phy_connect(lp->phylink, lp->dev->of_node, 0); if (ret) { @@ -1148,9 +1148,9 @@ static int axienet_stop(struct net_device *ndev) } /* Do a reset to ensure DMA is really stopped */ - mutex_lock(&lp->mii_bus->mdio_lock); + axienet_lock_mii(lp); __axienet_device_reset(lp); - mutex_unlock(&lp->mii_bus->mdio_lock); + axienet_unlock_mii(lp); cancel_work_sync(&lp->dma_err_task); @@ -1709,9 +1709,9 @@ static void axienet_dma_err_handler(struct work_struct *work) * including the MDIO. MDIO must be disabled before resetting. * Hold MDIO bus lock to avoid MDIO accesses during the reset. */ - mutex_lock(&lp->mii_bus->mdio_lock); + axienet_lock_mii(lp); __axienet_device_reset(lp); - mutex_unlock(&lp->mii_bus->mdio_lock); + axienet_unlock_mii(lp); for (i = 0; i < lp->tx_bd_num; i++) { cur_p = &lp->tx_bd_v[i]; From 3ed14d8d47bff8cd70c357da9b72b1f698bf553b Mon Sep 17 00:00:00 2001 From: Dinh Nguyen Date: Wed, 24 Mar 2021 08:52:19 -0500 Subject: [PATCH 0417/1091] dt-bindings: net: micrel-ksz90x1.txt: correct documentation Correct the Micrel phy documentation for the ksz9021 and ksz9031 phys for how the phy skews are set. Signed-off-by: Dinh Nguyen Signed-off-by: David S. Miller --- .../bindings/net/micrel-ksz90x1.txt | 96 ++++++++++++++++++- 1 file changed, 94 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/net/micrel-ksz90x1.txt b/Documentation/devicetree/bindings/net/micrel-ksz90x1.txt index b921731cd970..df9e844dd6bc 100644 --- a/Documentation/devicetree/bindings/net/micrel-ksz90x1.txt +++ b/Documentation/devicetree/bindings/net/micrel-ksz90x1.txt @@ -65,6 +65,71 @@ KSZ9031: step is 60ps. The default value is the neutral setting, so setting rxc-skew-ps=<0> actually results in -900 picoseconds adjustment. + The KSZ9031 hardware supports a range of skew values from negative to + positive, where the specific range is property dependent. All values + specified in the devicetree are offset by the minimum value so they + can be represented as positive integers in the devicetree since it's + difficult to represent a negative number in the devictree. + + The following 5-bit values table apply to rxc-skew-ps and txc-skew-ps. + + Pad Skew Value Delay (ps) Devicetree Value + ------------------------------------------------------ + 0_0000 -900ps 0 + 0_0001 -840ps 60 + 0_0010 -780ps 120 + 0_0011 -720ps 180 + 0_0100 -660ps 240 + 0_0101 -600ps 300 + 0_0110 -540ps 360 + 0_0111 -480ps 420 + 0_1000 -420ps 480 + 0_1001 -360ps 540 + 0_1010 -300ps 600 + 0_1011 -240ps 660 + 0_1100 -180ps 720 + 0_1101 -120ps 780 + 0_1110 -60ps 840 + 0_1111 0ps 900 + 1_0000 60ps 960 + 1_0001 120ps 1020 + 1_0010 180ps 1080 + 1_0011 240ps 1140 + 1_0100 300ps 1200 + 1_0101 360ps 1260 + 1_0110 420ps 1320 + 1_0111 480ps 1380 + 1_1000 540ps 1440 + 1_1001 600ps 1500 + 1_1010 660ps 1560 + 1_1011 720ps 1620 + 1_1100 780ps 1680 + 1_1101 840ps 1740 + 1_1110 900ps 1800 + 1_1111 960ps 1860 + + The following 4-bit values table apply to the txdX-skew-ps, rxdX-skew-ps + data pads, and the rxdv-skew-ps, txen-skew-ps control pads. + + Pad Skew Value Delay (ps) Devicetree Value + ------------------------------------------------------ + 0000 -420ps 0 + 0001 -360ps 60 + 0010 -300ps 120 + 0011 -240ps 180 + 0100 -180ps 240 + 0101 -120ps 300 + 0110 -60ps 360 + 0111 0ps 420 + 1000 60ps 480 + 1001 120ps 540 + 1010 180ps 600 + 1011 240ps 660 + 1100 300ps 720 + 1101 360ps 780 + 1110 420ps 840 + 1111 480ps 900 + Optional properties: Maximum value of 1860, default value 900: @@ -120,11 +185,21 @@ KSZ9131: Examples: + /* Attach to an Ethernet device with autodetected PHY */ + &enet { + rxc-skew-ps = <1800>; + rxdv-skew-ps = <0>; + txc-skew-ps = <1800>; + txen-skew-ps = <0>; + status = "okay"; + }; + + /* Attach to an explicitly-specified PHY */ mdio { phy0: ethernet-phy@0 { - rxc-skew-ps = <3000>; + rxc-skew-ps = <1800>; rxdv-skew-ps = <0>; - txc-skew-ps = <3000>; + txc-skew-ps = <1800>; txen-skew-ps = <0>; reg = <0>; }; @@ -133,3 +208,20 @@ Examples: phy = <&phy0>; phy-mode = "rgmii-id"; }; + +References + + Micrel ksz9021rl/rn Data Sheet, Revision 1.2. Dated 2/13/2014. + http://www.micrel.com/_PDF/Ethernet/datasheets/ksz9021rl-rn_ds.pdf + + Micrel ksz9031rnx Data Sheet, Revision 2.1. Dated 11/20/2014. + http://www.micrel.com/_PDF/Ethernet/datasheets/KSZ9031RNX.pdf + +Notes: + + Note that a previous version of the Micrel ksz9021rl/rn Data Sheet + was missing extended register 106 (transmit data pad skews), and + incorrectly specified the ps per step as 200ps/step instead of + 120ps/step. The latest update to this document reflects the latest + revision of the Micrel specification even though usage in the kernel + still reflects that incorrect document. From 3e6fdeb28f4c331acbd27bdb0effc4befd4ef8e8 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Wed, 24 Mar 2021 20:36:04 +0100 Subject: [PATCH 0418/1091] net: dsa: lantiq_gswip: Let GSWIP automatically set the xMII clock The xMII interface clock depends on the PHY interface (MII, RMII, RGMII) as well as the current link speed. Explicitly configure the GSWIP to automatically select the appropriate xMII interface clock. This fixes an issue seen by some users where ports using an external RMII or RGMII PHY were deaf (no RX or TX traffic could be seen). Most likely this is due to an "invalid" xMII clock being selected either by the bootloader or hardware-defaults. Fixes: 14fceff4771e51 ("net: dsa: Add Lantiq / Intel DSA driver for vrx200") Signed-off-by: Martin Blumenstingl Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/lantiq_gswip.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 52e865a3912c..809dfa3be6bb 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -799,10 +799,15 @@ static int gswip_setup(struct dsa_switch *ds) /* Configure the MDIO Clock 2.5 MHz */ gswip_mdio_mask(priv, 0xff, 0x09, GSWIP_MDIO_MDC_CFG1); - /* Disable the xMII link */ - for (i = 0; i < priv->hw_info->max_ports; i++) + for (i = 0; i < priv->hw_info->max_ports; i++) { + /* Disable the xMII link */ gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, i); + /* Automatically select the xMII interface clock */ + gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_RATE_MASK, + GSWIP_MII_CFG_RATE_AUTO, i); + } + /* enable special tag insertion on cpu port */ gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN, GSWIP_FDMA_PCTRLp(cpu_port)); From d75135082698140a26a56defe1bbc1b06f26a41f Mon Sep 17 00:00:00 2001 From: Shyam Sundar S K Date: Thu, 25 Mar 2021 08:39:12 +0530 Subject: [PATCH 0419/1091] amd-xgbe: Update DMA coherency values Based on the IOMMU configuration, the current cache control settings can result in possible coherency issues. The hardware team has recommended new settings for the PCI device path to eliminate the issue. Fixes: 6f595959c095 ("amd-xgbe: Adjust register settings to improve performance") Signed-off-by: Shyam Sundar S K Acked-by: Tom Lendacky Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/xgbe/xgbe.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/amd/xgbe/xgbe.h b/drivers/net/ethernet/amd/xgbe/xgbe.h index ba8321ec1ee7..3305979a9f7c 100644 --- a/drivers/net/ethernet/amd/xgbe/xgbe.h +++ b/drivers/net/ethernet/amd/xgbe/xgbe.h @@ -180,9 +180,9 @@ #define XGBE_DMA_SYS_AWCR 0x30303030 /* DMA cache settings - PCI device */ -#define XGBE_DMA_PCI_ARCR 0x00000003 -#define XGBE_DMA_PCI_AWCR 0x13131313 -#define XGBE_DMA_PCI_AWARCR 0x00000313 +#define XGBE_DMA_PCI_ARCR 0x000f0f0f +#define XGBE_DMA_PCI_AWCR 0x0f0f0f0f +#define XGBE_DMA_PCI_AWARCR 0x00000f0f /* DMA channel interrupt modes */ #define XGBE_IRQ_MODE_EDGE 0 From c33b1cc62ac05c1dbb1cdafe2eb66da01c76ca8d Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:10 +0800 Subject: [PATCH 0420/1091] nfc: fix refcount leak in llcp_sock_bind() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nfc_llcp_local_get() is invoked in llcp_sock_bind(), but nfc_llcp_local_put() is not invoked in subsequent failure branches. As a result, refcount leakage occurs. To fix it, add calling nfc_llcp_local_put(). fix CVE-2020-25670 Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.6 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index d257ed3b732a..68832ee4b9f8 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -108,11 +108,13 @@ static int llcp_sock_bind(struct socket *sock, struct sockaddr *addr, int alen) llcp_sock->service_name_len, GFP_KERNEL); if (!llcp_sock->service_name) { + nfc_llcp_local_put(llcp_sock->local); ret = -ENOMEM; goto put_dev; } llcp_sock->ssap = nfc_llcp_get_sdp_ssap(local, llcp_sock); if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); kfree(llcp_sock->service_name); llcp_sock->service_name = NULL; ret = -EADDRINUSE; From 8a4cd82d62b5ec7e5482333a72b58a4eea4979f0 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:11 +0800 Subject: [PATCH 0421/1091] nfc: fix refcount leak in llcp_sock_connect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit nfc_llcp_local_get() is invoked in llcp_sock_connect(), but nfc_llcp_local_put() is not invoked in subsequent failure branches. As a result, refcount leakage occurs. To fix it, add calling nfc_llcp_local_put(). fix CVE-2020-25671 Fixes: c7aa12252f51 ("NFC: Take a reference on the LLCP local pointer when creating a socket") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.6 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 68832ee4b9f8..9e2799ee1595 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -704,6 +704,7 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, llcp_sock->local = nfc_llcp_local_get(local); llcp_sock->ssap = nfc_llcp_get_local_ssap(local); if (llcp_sock->ssap == LLCP_SAP_MAX) { + nfc_llcp_local_put(llcp_sock->local); ret = -ENOMEM; goto put_dev; } @@ -748,6 +749,7 @@ sock_unlink: sock_llcp_release: nfc_llcp_put_ssap(local, llcp_sock->ssap); + nfc_llcp_local_put(llcp_sock->local); put_dev: nfc_put_device(dev); From 7574fcdbdcb335763b6b322f6928dc0fd5730451 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:12 +0800 Subject: [PATCH 0422/1091] nfc: fix memory leak in llcp_sock_connect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In llcp_sock_connect(), use kmemdup to allocate memory for "llcp_sock->service_name". The memory is not released in the sock_unlink label of the subsequent failure branch. As a result, memory leakage occurs. fix CVE-2020-25672 Fixes: d646960f7986 ("NFC: Initial LLCP support") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.3 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 9e2799ee1595..59172614b249 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -746,6 +746,8 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, sock_unlink: nfc_llcp_sock_unlink(&local->connecting_sockets, sk); + kfree(llcp_sock->service_name); + llcp_sock->service_name = NULL; sock_llcp_release: nfc_llcp_put_ssap(local, llcp_sock->ssap); From 4b5db93e7f2afbdfe3b78e37879a85290187e6f1 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Thu, 25 Mar 2021 11:51:13 +0800 Subject: [PATCH 0423/1091] nfc: Avoid endless loops caused by repeated llcp_sock_connect() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When sock_wait_state() returns -EINPROGRESS, "sk->sk_state" is LLCP_CONNECTING. In this case, llcp_sock_connect() is repeatedly invoked, nfc_llcp_sock_link() will add sk to local->connecting_sockets twice. sk->sk_node->next will point to itself, that will make an endless loop and hang-up the system. To fix it, check whether sk->sk_state is LLCP_CONNECTING in llcp_sock_connect() to avoid repeated invoking. Fixes: b4011239a08e ("NFC: llcp: Fix non blocking sockets connections") Reported-by: "kiyin(尹亮)" Link: https://www.openwall.com/lists/oss-security/2020/11/01/1 Cc: #v3.11 Signed-off-by: Xiaoming Ni Signed-off-by: David S. Miller --- net/nfc/llcp_sock.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/nfc/llcp_sock.c b/net/nfc/llcp_sock.c index 59172614b249..a3b46f888803 100644 --- a/net/nfc/llcp_sock.c +++ b/net/nfc/llcp_sock.c @@ -673,6 +673,10 @@ static int llcp_sock_connect(struct socket *sock, struct sockaddr *_addr, ret = -EISCONN; goto error; } + if (sk->sk_state == LLCP_CONNECTING) { + ret = -EINPROGRESS; + goto error; + } dev = nfc_get_device(addr->dev_idx); if (dev == NULL) { From 30a93d2b7d5a7cbb53ac19c9364a256d1aa6c08a Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Thu, 25 Mar 2021 16:35:32 +0100 Subject: [PATCH 0424/1091] vxlan: do not modify the shared tunnel info when PMTU triggers an ICMP reply When the interface is part of a bridge or an Open vSwitch port and a packet exceed a PMTU estimate, an ICMP reply is sent to the sender. When using the external mode (collect metadata) the source and destination addresses are reversed, so that Open vSwitch can match the packet against an existing (reverse) flow. But inverting the source and destination addresses in the shared ip_tunnel_info will make following packets of the flow to use a wrong destination address (packets will be tunnelled to itself), if the flow isn't updated. Which happens with Open vSwitch, until the flow times out. Fixes this by uncloning the skb's ip_tunnel_info before inverting its source and destination addresses, so that the modification will only be made for the PTMU packet, not the following ones. Fixes: fc68c99577cc ("vxlan: Support for PMTU discovery on directly bridged links") Tested-by: Eelco Chaudron Reviewed-by: Eelco Chaudron Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/vxlan.c | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/drivers/net/vxlan.c b/drivers/net/vxlan.c index 666dd201c3d5..53dbc67e8a34 100644 --- a/drivers/net/vxlan.c +++ b/drivers/net/vxlan.c @@ -2725,12 +2725,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto tx_error; } else if (err) { if (info) { + struct ip_tunnel_info *unclone; struct in_addr src, dst; + unclone = skb_tunnel_info_unclone(skb); + if (unlikely(!unclone)) + goto tx_error; + src = remote_ip.sin.sin_addr; dst = local_ip.sin.sin_addr; - info->key.u.ipv4.src = src.s_addr; - info->key.u.ipv4.dst = dst.s_addr; + unclone->key.u.ipv4.src = src.s_addr; + unclone->key.u.ipv4.dst = dst.s_addr; } vxlan_encap_bypass(skb, vxlan, vxlan, vni, false); dst_release(ndst); @@ -2781,12 +2786,17 @@ static void vxlan_xmit_one(struct sk_buff *skb, struct net_device *dev, goto tx_error; } else if (err) { if (info) { + struct ip_tunnel_info *unclone; struct in6_addr src, dst; + unclone = skb_tunnel_info_unclone(skb); + if (unlikely(!unclone)) + goto tx_error; + src = remote_ip.sin6.sin6_addr; dst = local_ip.sin6.sin6_addr; - info->key.u.ipv6.src = src; - info->key.u.ipv6.dst = dst; + unclone->key.u.ipv6.src = src; + unclone->key.u.ipv6.dst = dst; } vxlan_encap_bypass(skb, vxlan, vxlan, vni, false); From 68c1a943ef37bafde5ea2383e8ca224c7169ee31 Mon Sep 17 00:00:00 2001 From: Antoine Tenart Date: Thu, 25 Mar 2021 16:35:33 +0100 Subject: [PATCH 0425/1091] geneve: do not modify the shared tunnel info when PMTU triggers an ICMP reply When the interface is part of a bridge or an Open vSwitch port and a packet exceed a PMTU estimate, an ICMP reply is sent to the sender. When using the external mode (collect metadata) the source and destination addresses are reversed, so that Open vSwitch can match the packet against an existing (reverse) flow. But inverting the source and destination addresses in the shared ip_tunnel_info will make following packets of the flow to use a wrong destination address (packets will be tunnelled to itself), if the flow isn't updated. Which happens with Open vSwitch, until the flow times out. Fixes this by uncloning the skb's ip_tunnel_info before inverting its source and destination addresses, so that the modification will only be made for the PTMU packet, not the following ones. Fixes: c1a800e88dbf ("geneve: Support for PMTU discovery on directly bridged links") Tested-by: Eelco Chaudron Reviewed-by: Eelco Chaudron Signed-off-by: Antoine Tenart Signed-off-by: David S. Miller --- drivers/net/geneve.c | 24 ++++++++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 4ac0373326ef..d5b1e48e0c09 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -908,8 +908,16 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, info = skb_tunnel_info(skb); if (info) { - info->key.u.ipv4.dst = fl4.saddr; - info->key.u.ipv4.src = fl4.daddr; + struct ip_tunnel_info *unclone; + + unclone = skb_tunnel_info_unclone(skb); + if (unlikely(!unclone)) { + dst_release(&rt->dst); + return -ENOMEM; + } + + unclone->key.u.ipv4.dst = fl4.saddr; + unclone->key.u.ipv4.src = fl4.daddr; } if (!pskb_may_pull(skb, ETH_HLEN)) { @@ -993,8 +1001,16 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, struct ip_tunnel_info *info = skb_tunnel_info(skb); if (info) { - info->key.u.ipv6.dst = fl6.saddr; - info->key.u.ipv6.src = fl6.daddr; + struct ip_tunnel_info *unclone; + + unclone = skb_tunnel_info_unclone(skb); + if (unlikely(!unclone)) { + dst_release(dst); + return -ENOMEM; + } + + unclone->key.u.ipv6.dst = fl6.saddr; + unclone->key.u.ipv6.src = fl6.daddr; } if (!pskb_may_pull(skb, ETH_HLEN)) { From 3a87571f0ffc51ba3bf3ecdb6032861d0154b164 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Thu, 25 Mar 2021 11:14:53 -0700 Subject: [PATCH 0426/1091] sch_red: fix off-by-one checks in red_check_params() This fixes following syzbot report: UBSAN: shift-out-of-bounds in ./include/net/red.h:237:23 shift exponent 32 is too large for 32-bit type 'unsigned int' CPU: 1 PID: 8418 Comm: syz-executor170 Not tainted 5.12.0-rc4-next-20210324-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x141/0x1d7 lib/dump_stack.c:120 ubsan_epilogue+0xb/0x5a lib/ubsan.c:148 __ubsan_handle_shift_out_of_bounds.cold+0xb1/0x181 lib/ubsan.c:327 red_set_parms include/net/red.h:237 [inline] choke_change.cold+0x3c/0xc8 net/sched/sch_choke.c:414 qdisc_create+0x475/0x12f0 net/sched/sch_api.c:1247 tc_modify_qdisc+0x4c8/0x1a50 net/sched/sch_api.c:1663 rtnetlink_rcv_msg+0x44e/0xad0 net/core/rtnetlink.c:5553 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2502 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2350 ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2433 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x43f039 Code: 28 c3 e8 2a 14 00 00 66 2e 0f 1f 84 00 00 00 00 00 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <48> 3d 01 f0 ff ff 73 01 c3 48 c7 c1 c0 ff ff ff f7 d8 64 89 01 48 RSP: 002b:00007ffdfa725168 EFLAGS: 00000246 ORIG_RAX: 000000000000002e RAX: ffffffffffffffda RBX: 0000000000400488 RCX: 000000000043f039 RDX: 0000000000000000 RSI: 0000000020000040 RDI: 0000000000000004 RBP: 0000000000403020 R08: 0000000000400488 R09: 0000000000400488 R10: 0000000000400488 R11: 0000000000000246 R12: 00000000004030b0 R13: 0000000000000000 R14: 00000000004ac018 R15: 0000000000400488 Fixes: 8afa10cbe281 ("net_sched: red: Avoid illegal values") Signed-off-by: Eric Dumazet Reported-by: syzbot Signed-off-by: David S. Miller --- include/net/red.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/net/red.h b/include/net/red.h index 0b39eff1d50a..be11dbd26492 100644 --- a/include/net/red.h +++ b/include/net/red.h @@ -171,9 +171,9 @@ static inline void red_set_vars(struct red_vars *v) static inline bool red_check_params(u32 qth_min, u32 qth_max, u8 Wlog, u8 Scell_log, u8 *stab) { - if (fls(qth_min) + Wlog > 32) + if (fls(qth_min) + Wlog >= 32) return false; - if (fls(qth_max) + Wlog > 32) + if (fls(qth_max) + Wlog >= 32) return false; if (Scell_log >= 32) return false; From 6032ebb54c60cae24329f6aba3ce0c1ca8ad6abe Mon Sep 17 00:00:00 2001 From: Pedro Tammela Date: Thu, 25 Mar 2021 12:01:15 -0300 Subject: [PATCH 0427/1091] libbpf: Fix bail out from 'ringbuf_process_ring()' on error The current code bails out with negative and positive returns. If the callback returns a positive return code, 'ring_buffer__consume()' and 'ring_buffer__poll()' will return a spurious number of records consumed, but mostly important will continue the processing loop. This patch makes positive returns from the callback a no-op. Fixes: bf99c936f947 ("libbpf: Add BPF ring buffer support") Signed-off-by: Pedro Tammela Signed-off-by: Andrii Nakryiko Link: https://lore.kernel.org/bpf/20210325150115.138750-1-pctammela@mojatatu.com --- tools/lib/bpf/ringbuf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/lib/bpf/ringbuf.c b/tools/lib/bpf/ringbuf.c index 8caaafe7e312..e7a8d847161f 100644 --- a/tools/lib/bpf/ringbuf.c +++ b/tools/lib/bpf/ringbuf.c @@ -227,7 +227,7 @@ static int ringbuf_process_ring(struct ring* r) if ((len & BPF_RINGBUF_DISCARD_BIT) == 0) { sample = (void *)len_ptr + BPF_RINGBUF_HDR_SZ; err = r->sample_cb(r->ctx, sample, len); - if (err) { + if (err < 0) { /* update consumer pos and bail out */ smp_store_release(r->consumer_pos, cons_pos); From 52762efa2b256ed1c5274e5177cbd52ee11a2f6a Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Mon, 22 Mar 2021 18:46:56 -0700 Subject: [PATCH 0428/1091] gpu/xen: Fix a use after free in xen_drm_drv_init In function displback_changed, has the call chain displback_connect(front_info)->xen_drm_drv_init(front_info). We can see that drm_info is assigned to front_info->drm_info and drm_info is freed in fail branch in xen_drm_drv_init(). Later displback_disconnect(front_info) is called and it calls xen_drm_drv_fini(front_info) cause a use after free by drm_info = front_info->drm_info statement. My patch has done two things. First fixes the fail label which drm_info = kzalloc() failed and still free the drm_info. Second sets front_info->drm_info to NULL to avoid uaf. Signed-off-by: Lv Yunlong Reviewed-by: Oleksandr Andrushchenko Signed-off-by: Oleksandr Andrushchenko Link: https://patchwork.freedesktop.org/patch/msgid/20210323014656.10068-1-lyl2019@mail.ustc.edu.cn --- drivers/gpu/drm/xen/xen_drm_front.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front.c b/drivers/gpu/drm/xen/xen_drm_front.c index 30d9adf31c84..9f14d99c763c 100644 --- a/drivers/gpu/drm/xen/xen_drm_front.c +++ b/drivers/gpu/drm/xen/xen_drm_front.c @@ -521,7 +521,7 @@ static int xen_drm_drv_init(struct xen_drm_front_info *front_info) drm_dev = drm_dev_alloc(&xen_drm_driver, dev); if (IS_ERR(drm_dev)) { ret = PTR_ERR(drm_dev); - goto fail; + goto fail_dev; } drm_info->drm_dev = drm_dev; @@ -551,8 +551,10 @@ fail_modeset: drm_kms_helper_poll_fini(drm_dev); drm_mode_config_cleanup(drm_dev); drm_dev_put(drm_dev); -fail: +fail_dev: kfree(drm_info); + front_info->drm_info = NULL; +fail: return ret; } From 014305d001987a0eeada6bac610a8665f92aae24 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Thu, 25 Mar 2021 14:19:01 +0800 Subject: [PATCH 0429/1091] drivers: gpu: drm: xen_drm_front_drm_info is declared twice struct xen_drm_front_drm_info has been declared. Remove the duplicate. Signed-off-by: Wan Jiabing Reviewed-by: Oleksandr Andrushchenko Signed-off-by: Oleksandr Andrushchenko Link: https://patchwork.freedesktop.org/patch/msgid/20210325061901.851273-1-wanjiabing@vivo.com --- drivers/gpu/drm/xen/xen_drm_front_conn.h | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/xen/xen_drm_front_conn.h b/drivers/gpu/drm/xen/xen_drm_front_conn.h index 3adacba9a23b..e5f4314899ee 100644 --- a/drivers/gpu/drm/xen/xen_drm_front_conn.h +++ b/drivers/gpu/drm/xen/xen_drm_front_conn.h @@ -16,7 +16,6 @@ struct drm_connector; struct xen_drm_front_drm_info; -struct xen_drm_front_drm_info; int xen_drm_front_conn_init(struct xen_drm_front_drm_info *drm_info, struct drm_connector *connector); From 53f1d31708f6240e4615b0927df31f182e389e2f Mon Sep 17 00:00:00 2001 From: "Aneesh Kumar K.V" Date: Fri, 26 Mar 2021 12:37:55 +0530 Subject: [PATCH 0430/1091] powerpc/mm/book3s64: Use the correct storage key value when calling H_PROTECT H_PROTECT expects the flag value to include flags: AVPN, pp0, pp1, pp2, key0-key4, Noexec, CMO Option flags This patch updates hpte_updatepp() to fetch the storage key value from the linux page table and use the same in H_PROTECT hcall. native_hpte_updatepp() is not updated because the kernel doesn't clear the existing storage key value there. The kernel also doesn't use hpte_updatepp() callback for updating storage keys. This fixes the below kernel crash observed with KUAP enabled. BUG: Unable to handle kernel data access on write at 0xc009fffffc440000 Faulting instruction address: 0xc0000000000b7030 Key fault AMR: 0xfcffffffffffffff IAMR: 0xc0000077bc498100 Found HPTE: v = 0x40070adbb6fffc05 r = 0x1ffffffffff1194 Oops: Kernel access of bad area, sig: 11 [#1] LE PAGE_SIZE=64K MMU=Hash SMP NR_CPUS=2048 NUMA pSeries ... CFAR: c000000000010100 DAR: c009fffffc440000 DSISR: 02200000 IRQMASK: 0 ... NIP memset+0x68/0x104 LR pcpu_alloc+0x54c/0xb50 Call Trace: pcpu_alloc+0x55c/0xb50 (unreliable) blk_stat_alloc_callback+0x94/0x150 blk_mq_init_allocated_queue+0x64/0x560 blk_mq_init_queue+0x54/0xb0 scsi_mq_alloc_queue+0x30/0xa0 scsi_alloc_sdev+0x1cc/0x300 scsi_probe_and_add_lun+0xb50/0x1020 __scsi_scan_target+0x17c/0x790 scsi_scan_channel+0x90/0xe0 scsi_scan_host_selected+0x148/0x1f0 do_scan_async+0x2c/0x2a0 async_run_entry_fn+0x78/0x220 process_one_work+0x264/0x540 worker_thread+0xa8/0x600 kthread+0x190/0x1a0 ret_from_kernel_thread+0x5c/0x6c With KUAP enabled the kernel uses storage key 3 for all its translations. But as shown by the debug print, in this specific case we have the hash page table entry created with key value 0. Found HPTE: v = 0x40070adbb6fffc05 r = 0x1ffffffffff1194 and DSISR indicates a key fault. This can happen due to parallel fault on the same EA by different CPUs: CPU 0 CPU 1 fault on X H_PAGE_BUSY set fault on X finish fault handling and clear H_PAGE_BUSY check for H_PAGE_BUSY continue with fault handling. This implies CPU1 will end up calling hpte_updatepp for address X and the kernel updated the hash pte entry with key 0 Fixes: d94b827e89dc ("powerpc/book3s64/kuap: Use Key 3 for kernel mapping with hash translation") Reported-by: Murilo Opsfelder Araujo Signed-off-by: Aneesh Kumar K.V Debugged-by: Michael Ellerman Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/20210326070755.304625-1-aneesh.kumar@linux.ibm.com --- arch/powerpc/platforms/pseries/lpar.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/powerpc/platforms/pseries/lpar.c b/arch/powerpc/platforms/pseries/lpar.c index 764170fdb0f7..3805519a6469 100644 --- a/arch/powerpc/platforms/pseries/lpar.c +++ b/arch/powerpc/platforms/pseries/lpar.c @@ -887,7 +887,8 @@ static long pSeries_lpar_hpte_updatepp(unsigned long slot, want_v = hpte_encode_avpn(vpn, psize, ssize); - flags = (newpp & 7) | H_AVPN; + flags = (newpp & (HPTE_R_PP | HPTE_R_N | HPTE_R_KEY_LO)) | H_AVPN; + flags |= (newpp & HPTE_R_KEY_HI) >> 48; if (mmu_has_feature(MMU_FTR_KERNEL_RO)) /* Move pp0 into bit 8 (IBM 55) */ flags |= (newpp & HPTE_R_PP0) >> 55; From 1cc5ed25bdade86de2650a82b2730108a76de20c Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Wed, 24 Mar 2021 17:06:54 -0600 Subject: [PATCH 0431/1091] usbip: vhci_hcd fix shift out-of-bounds in vhci_hub_control() Fix shift out-of-bounds in vhci_hub_control() SetPortFeature handling. UBSAN: shift-out-of-bounds in drivers/usb/usbip/vhci_hcd.c:605:42 shift exponent 768 is too large for 32-bit type 'int' Reported-by: syzbot+3dea30b047f41084de66@syzkaller.appspotmail.com Cc: stable@vger.kernel.org Signed-off-by: Shuah Khan Link: https://lore.kernel.org/r/20210324230654.34798-1-skhan@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vhci_hcd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index 3209b5ddd30c..a20a8380ca0c 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -594,6 +594,8 @@ static int vhci_hub_control(struct usb_hcd *hcd, u16 typeReq, u16 wValue, pr_err("invalid port number %d\n", wIndex); goto error; } + if (wValue >= 32) + goto error; if (hcd->speed == HCD_USB3) { if ((vhci_hcd->port_status[rhport] & USB_SS_PORT_STAT_POWER) != 0) { From 5aef629704ad4d983ecf5c8a25840f16e45b6d59 Mon Sep 17 00:00:00 2001 From: Wesley Cheng Date: Wed, 24 Mar 2021 11:31:04 -0700 Subject: [PATCH 0432/1091] usb: dwc3: gadget: Clear DEP flags after stop transfers in ep disable Ensure that dep->flags are cleared until after stop active transfers is completed. Otherwise, the ENDXFER command will not be executed during ep disable. Fixes: f09ddcfcb8c5 ("usb: dwc3: gadget: Prevent EP queuing while stopping transfers") Cc: stable Reported-and-tested-by: Andy Shevchenko Tested-by: Marek Szyprowski Signed-off-by: Wesley Cheng Link: https://lore.kernel.org/r/1616610664-16495-1-git-send-email-wcheng@codeaurora.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc3/gadget.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/usb/dwc3/gadget.c b/drivers/usb/dwc3/gadget.c index 4c15c3fce303..c7ef218e7a8c 100644 --- a/drivers/usb/dwc3/gadget.c +++ b/drivers/usb/dwc3/gadget.c @@ -791,10 +791,6 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) reg &= ~DWC3_DALEPENA_EP(dep->number); dwc3_writel(dwc->regs, DWC3_DALEPENA, reg); - dep->stream_capable = false; - dep->type = 0; - dep->flags = 0; - /* Clear out the ep descriptors for non-ep0 */ if (dep->number > 1) { dep->endpoint.comp_desc = NULL; @@ -803,6 +799,10 @@ static int __dwc3_gadget_ep_disable(struct dwc3_ep *dep) dwc3_remove_requests(dwc, dep); + dep->stream_capable = false; + dep->type = 0; + dep->flags = 0; + return 0; } From 6f978a30c9bb12dab1302d0f06951ee290f5e600 Mon Sep 17 00:00:00 2001 From: Chunfeng Yun Date: Tue, 23 Mar 2021 15:02:46 +0800 Subject: [PATCH 0433/1091] usb: xhci-mtk: fix broken streams issue on 0.96 xHCI The MediaTek 0.96 xHCI controller on some platforms does not support bulk stream even HCCPARAMS says supporting, due to MaxPSASize is set a default value 1 by mistake, here use XHCI_BROKEN_STREAMS quirk to fix it. Fixes: 94a631d91ad3 ("usb: xhci-mtk: check hcc_params after adding primary hcd") Cc: stable Signed-off-by: Chunfeng Yun Link: https://lore.kernel.org/r/1616482975-17841-4-git-send-email-chunfeng.yun@mediatek.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/host/xhci-mtk.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/drivers/usb/host/xhci-mtk.c b/drivers/usb/host/xhci-mtk.c index fe010cc61f19..2f27dc0d9c6b 100644 --- a/drivers/usb/host/xhci-mtk.c +++ b/drivers/usb/host/xhci-mtk.c @@ -397,6 +397,13 @@ static void xhci_mtk_quirks(struct device *dev, struct xhci_hcd *xhci) xhci->quirks |= XHCI_SPURIOUS_SUCCESS; if (mtk->lpm_support) xhci->quirks |= XHCI_LPM_SUPPORT; + + /* + * MTK xHCI 0.96: PSA is 1 by default even if doesn't support stream, + * and it's 3 when support it. + */ + if (xhci->hci_version < 0x100 && HCC_MAX_PSA(xhci->hcc_params) == 4) + xhci->quirks |= XHCI_BROKEN_STREAMS; } /* called during probe() after chip reset completes */ @@ -548,7 +555,8 @@ static int xhci_mtk_probe(struct platform_device *pdev) if (ret) goto put_usb3_hcd; - if (HCC_MAX_PSA(xhci->hcc_params) >= 4) + if (HCC_MAX_PSA(xhci->hcc_params) >= 4 && + !(xhci->quirks & XHCI_BROKEN_STREAMS)) xhci->shared_hcd->can_do_streams = 1; ret = usb_add_hcd(xhci->shared_hcd, irq, IRQF_SHARED); From 92af4fc6ec331228aca322ca37c8aea7b150a151 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 24 Mar 2021 09:11:41 +0200 Subject: [PATCH 0434/1091] usb: musb: Fix suspend with devices connected for a64 Pinephone running on Allwinner A64 fails to suspend with USB devices connected as reported by Bhushan Shah . Reverting commit 5fbf7a253470 ("usb: musb: fix idling for suspend after disconnect interrupt") fixes the issue. Let's add suspend checks also for suspend after disconnect interrupt quirk handling like we already do elsewhere. Fixes: 5fbf7a253470 ("usb: musb: fix idling for suspend after disconnect interrupt") Reported-by: Bhushan Shah Tested-by: Bhushan Shah Signed-off-by: Tony Lindgren Link: https://lore.kernel.org/r/20210324071142.42264-1-tony@atomide.com Cc: stable Signed-off-by: Greg Kroah-Hartman --- drivers/usb/musb/musb_core.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c index 1cd87729ba60..fc0457db62e1 100644 --- a/drivers/usb/musb/musb_core.c +++ b/drivers/usb/musb/musb_core.c @@ -2004,10 +2004,14 @@ static void musb_pm_runtime_check_session(struct musb *musb) MUSB_DEVCTL_HR; switch (devctl & ~s) { case MUSB_QUIRK_B_DISCONNECT_99: - musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n"); - schedule_delayed_work(&musb->irq_work, - msecs_to_jiffies(1000)); - break; + if (musb->quirk_retries && !musb->flush_irq_work) { + musb_dbg(musb, "Poll devctl in case of suspend after disconnect\n"); + schedule_delayed_work(&musb->irq_work, + msecs_to_jiffies(1000)); + musb->quirk_retries--; + break; + } + fallthrough; case MUSB_QUIRK_B_INVALID_VBUS_91: if (musb->quirk_retries && !musb->flush_irq_work) { musb_dbg(musb, From 5e3bbae8ee3d677a0aa2919dc62b5c60ea01ba61 Mon Sep 17 00:00:00 2001 From: Artur Petrosyan Date: Fri, 26 Mar 2021 14:24:46 +0400 Subject: [PATCH 0435/1091] usb: dwc2: Fix HPRT0.PrtSusp bit setting for HiKey 960 board. Increased the waiting timeout for HPRT0.PrtSusp register field to be set, because on HiKey 960 board HPRT0.PrtSusp wasn't generated with the existing timeout. Cc: # 4.18 Fixes: 22bb5cfdf13a ("usb: dwc2: Fix host exit from hibernation flow.") Signed-off-by: Artur Petrosyan Acked-by: Minas Harutyunyan Link: https://lore.kernel.org/r/20210326102447.8F7FEA005D@mailhost.synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc2/hcd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index fc3269f5faf1..40e5655921bf 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -5398,7 +5398,7 @@ int dwc2_host_enter_hibernation(struct dwc2_hsotg *hsotg) dwc2_writel(hsotg, hprt0, HPRT0); /* Wait for the HPRT0.PrtSusp register field to be set */ - if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 3000)) + if (dwc2_hsotg_wait_bit_set(hsotg, HPRT0, HPRT0_SUSP, 5000)) dev_warn(hsotg->dev, "Suspend wasn't generated\n"); /* From 93f672804bf2d7a49ef3fd96827ea6290ca1841e Mon Sep 17 00:00:00 2001 From: Artur Petrosyan Date: Fri, 26 Mar 2021 14:25:09 +0400 Subject: [PATCH 0436/1091] usb: dwc2: Prevent core suspend when port connection flag is 0 In host mode port connection status flag is "0" when loading the driver. After loading the driver system asserts suspend which is handled by "_dwc2_hcd_suspend()" function. Before the system suspend the port connection status is "0". As result need to check the "port_connect_status" if it is "0", then skipping entering to suspend. Cc: # 5.2 Fixes: 6f6d70597c15 ("usb: dwc2: bus suspend/resume for hosts with DWC2_POWER_DOWN_PARAM_NONE") Signed-off-by: Artur Petrosyan Link: https://lore.kernel.org/r/20210326102510.BDEDEA005D@mailhost.synopsys.com Signed-off-by: Greg Kroah-Hartman --- drivers/usb/dwc2/hcd.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/usb/dwc2/hcd.c b/drivers/usb/dwc2/hcd.c index 40e5655921bf..1a9789ec5847 100644 --- a/drivers/usb/dwc2/hcd.c +++ b/drivers/usb/dwc2/hcd.c @@ -4322,7 +4322,8 @@ static int _dwc2_hcd_suspend(struct usb_hcd *hcd) if (hsotg->op_state == OTG_STATE_B_PERIPHERAL) goto unlock; - if (hsotg->params.power_down > DWC2_POWER_DOWN_PARAM_PARTIAL) + if (hsotg->params.power_down != DWC2_POWER_DOWN_PARAM_PARTIAL || + hsotg->flags.b.port_connect_status == 0) goto skip_power_saving; /* From 29d96eb261345c8d888e248ae79484e681be2faa Mon Sep 17 00:00:00 2001 From: Roja Rani Yarubandi Date: Wed, 24 Mar 2021 15:48:35 +0530 Subject: [PATCH 0437/1091] soc: qcom-geni-se: Cleanup the code to remove proxy votes This reverts commit 048eb908a1f2 ("soc: qcom-geni-se: Add interconnect support to fix earlycon crash") ICC core and platforms drivers supports sync_state feature, which ensures that the default ICC BW votes from the bootloader is not removed until all it's consumers are probes. The proxy votes were needed in case other QUP child drivers I2C, SPI probes before UART, they can turn off the QUP-CORE clock which is shared resources for all QUP driver, this causes unclocked access to HW from earlycon. Given above support from ICC there is no longer need to maintain proxy votes on QUP-CORE ICC node from QUP wrapper driver for early console usecase, the default votes won't be removed until real console is probed. Cc: stable@vger.kernel.org Fixes: 266cd33b5913 ("interconnect: qcom: Ensure that the floor bandwidth value is enforced") Fixes: 7d3b0b0d8184 ("interconnect: qcom: Use icc_sync_state") Signed-off-by: Roja Rani Yarubandi Signed-off-by: Akash Asthana Reviewed-by: Matthias Kaehlcke Link: https://lore.kernel.org/r/20210324101836.25272-2-rojay@codeaurora.org Signed-off-by: Greg Kroah-Hartman --- drivers/soc/qcom/qcom-geni-se.c | 74 --------------------------- drivers/tty/serial/qcom_geni_serial.c | 7 --- include/linux/qcom-geni-se.h | 2 - 3 files changed, 83 deletions(-) diff --git a/drivers/soc/qcom/qcom-geni-se.c b/drivers/soc/qcom/qcom-geni-se.c index f42954e2c98e..1fd29f93ff6d 100644 --- a/drivers/soc/qcom/qcom-geni-se.c +++ b/drivers/soc/qcom/qcom-geni-se.c @@ -3,7 +3,6 @@ #include #include -#include #include #include #include @@ -92,14 +91,11 @@ struct geni_wrapper { struct device *dev; void __iomem *base; struct clk_bulk_data ahb_clks[NUM_AHB_CLKS]; - struct geni_icc_path to_core; }; static const char * const icc_path_names[] = {"qup-core", "qup-config", "qup-memory"}; -static struct geni_wrapper *earlycon_wrapper; - #define QUP_HW_VER_REG 0x4 /* Common SE registers */ @@ -843,44 +839,11 @@ int geni_icc_disable(struct geni_se *se) } EXPORT_SYMBOL(geni_icc_disable); -void geni_remove_earlycon_icc_vote(void) -{ - struct platform_device *pdev; - struct geni_wrapper *wrapper; - struct device_node *parent; - struct device_node *child; - - if (!earlycon_wrapper) - return; - - wrapper = earlycon_wrapper; - parent = of_get_next_parent(wrapper->dev->of_node); - for_each_child_of_node(parent, child) { - if (!of_device_is_compatible(child, "qcom,geni-se-qup")) - continue; - - pdev = of_find_device_by_node(child); - if (!pdev) - continue; - - wrapper = platform_get_drvdata(pdev); - icc_put(wrapper->to_core.path); - wrapper->to_core.path = NULL; - - } - of_node_put(parent); - - earlycon_wrapper = NULL; -} -EXPORT_SYMBOL(geni_remove_earlycon_icc_vote); - static int geni_se_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; struct resource *res; struct geni_wrapper *wrapper; - struct console __maybe_unused *bcon; - bool __maybe_unused has_earlycon = false; int ret; wrapper = devm_kzalloc(dev, sizeof(*wrapper), GFP_KERNEL); @@ -903,43 +866,6 @@ static int geni_se_probe(struct platform_device *pdev) } } -#ifdef CONFIG_SERIAL_EARLYCON - for_each_console(bcon) { - if (!strcmp(bcon->name, "qcom_geni")) { - has_earlycon = true; - break; - } - } - if (!has_earlycon) - goto exit; - - wrapper->to_core.path = devm_of_icc_get(dev, "qup-core"); - if (IS_ERR(wrapper->to_core.path)) - return PTR_ERR(wrapper->to_core.path); - /* - * Put minmal BW request on core clocks on behalf of early console. - * The vote will be removed earlycon exit function. - * - * Note: We are putting vote on each QUP wrapper instead only to which - * earlycon is connected because QUP core clock of different wrapper - * share same voltage domain. If core1 is put to 0, then core2 will - * also run at 0, if not voted. Default ICC vote will be removed ASA - * we touch any of the core clock. - * core1 = core2 = max(core1, core2) - */ - ret = icc_set_bw(wrapper->to_core.path, GENI_DEFAULT_BW, - GENI_DEFAULT_BW); - if (ret) { - dev_err(&pdev->dev, "%s: ICC BW voting failed for core: %d\n", - __func__, ret); - return ret; - } - - if (of_get_compatible_child(pdev->dev.of_node, "qcom,geni-debug-uart")) - earlycon_wrapper = wrapper; - of_node_put(pdev->dev.of_node); -exit: -#endif dev_set_drvdata(dev, wrapper); dev_dbg(dev, "GENI SE Driver probed\n"); return devm_of_platform_populate(dev); diff --git a/drivers/tty/serial/qcom_geni_serial.c b/drivers/tty/serial/qcom_geni_serial.c index 291649f02821..0d85b55ea823 100644 --- a/drivers/tty/serial/qcom_geni_serial.c +++ b/drivers/tty/serial/qcom_geni_serial.c @@ -1177,12 +1177,6 @@ static inline void qcom_geni_serial_enable_early_read(struct geni_se *se, struct console *con) { } #endif -static int qcom_geni_serial_earlycon_exit(struct console *con) -{ - geni_remove_earlycon_icc_vote(); - return 0; -} - static struct qcom_geni_private_data earlycon_private_data; static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev, @@ -1233,7 +1227,6 @@ static int __init qcom_geni_serial_earlycon_setup(struct earlycon_device *dev, writel(stop_bit_len, uport->membase + SE_UART_TX_STOP_BIT_LEN); dev->con->write = qcom_geni_serial_earlycon_write; - dev->con->exit = qcom_geni_serial_earlycon_exit; dev->con->setup = NULL; qcom_geni_serial_enable_early_read(&se, dev->con); diff --git a/include/linux/qcom-geni-se.h b/include/linux/qcom-geni-se.h index ec2ad4b0fe14..c4fdb4463f7d 100644 --- a/include/linux/qcom-geni-se.h +++ b/include/linux/qcom-geni-se.h @@ -460,7 +460,5 @@ void geni_icc_set_tag(struct geni_se *se, u32 tag); int geni_icc_enable(struct geni_se *se); int geni_icc_disable(struct geni_se *se); - -void geni_remove_earlycon_icc_vote(void); #endif #endif From a846738f8c3788d846ed1f587270d2f2e3d32432 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Fri, 26 Mar 2021 16:33:53 +0100 Subject: [PATCH 0438/1091] xen-blkback: don't leak persistent grants from xen_blkbk_map() The fix for XSA-365 zapped too many of the ->persistent_gnt[] entries. Ones successfully obtained should not be overwritten, but instead left for xen_blkbk_unmap_prepare() to pick up and put. This is XSA-371. Signed-off-by: Jan Beulich Cc: stable@vger.kernel.org Reviewed-by: Juergen Gross Reviewed-by: Wei Liu Signed-off-by: Juergen Gross --- drivers/block/xen-blkback/blkback.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/block/xen-blkback/blkback.c b/drivers/block/xen-blkback/blkback.c index da16121140ca..3874233f7194 100644 --- a/drivers/block/xen-blkback/blkback.c +++ b/drivers/block/xen-blkback/blkback.c @@ -891,7 +891,7 @@ next: out: for (i = last_map; i < num; i++) { /* Don't zap current batch's valid persistent grants. */ - if(i >= last_map + segs_to_map) + if(i >= map_until) pages[i]->persistent_gnt = NULL; pages[i]->handle = BLKBACK_INVALID_HANDLE; } From a95d8f581901c560ff1b63bc02107eb34a6efb1b Mon Sep 17 00:00:00 2001 From: Geert Uytterhoeven Date: Fri, 26 Mar 2021 13:07:21 +0100 Subject: [PATCH 0439/1091] cpufreq: Fix scaling_{available,boost}_frequencies_show() comments The function names in the comment blocks for the functions scaling_available_frequencies_show() and scaling_boost_frequencies_show() do not match the actual names. Fixes: 6f19efc0a1ca08bc ("cpufreq: Add boost frequency support in core") Signed-off-by: Geert Uytterhoeven Signed-off-by: Rafael J. Wysocki --- drivers/cpufreq/freq_table.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/cpufreq/freq_table.c b/drivers/cpufreq/freq_table.c index d3f756f7b5a0..67e56cf638ef 100644 --- a/drivers/cpufreq/freq_table.c +++ b/drivers/cpufreq/freq_table.c @@ -267,7 +267,7 @@ struct freq_attr cpufreq_freq_attr_##_name##_freqs = \ __ATTR_RO(_name##_frequencies) /* - * show_scaling_available_frequencies - show available normal frequencies for + * scaling_available_frequencies_show - show available normal frequencies for * the specified CPU */ static ssize_t scaling_available_frequencies_show(struct cpufreq_policy *policy, @@ -279,7 +279,7 @@ cpufreq_attr_available_freq(scaling_available); EXPORT_SYMBOL_GPL(cpufreq_freq_attr_scaling_available_freqs); /* - * show_available_boost_freqs - show available boost frequencies for + * scaling_boost_frequencies_show - show available boost frequencies for * the specified CPU */ static ssize_t scaling_boost_frequencies_show(struct cpufreq_policy *policy, From 12aa8a9467b354ef893ce0fc5719a4de4949a9fb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Mar 2021 11:03:13 +0100 Subject: [PATCH 0440/1091] bpf: Enforce that struct_ops programs be GPL-only MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the introduction of the struct_ops program type, it became possible to implement kernel functionality in BPF, making it viable to use BPF in place of a regular kernel module for these particular operations. Thus far, the only user of this mechanism is for implementing TCP congestion control algorithms. These are clearly marked as GPL-only when implemented as modules (as seen by the use of EXPORT_SYMBOL_GPL for tcp_register_congestion_control()), so it seems like an oversight that this was not carried over to BPF implementations. Since this is the only user of the struct_ops mechanism, just enforcing GPL-only for the struct_ops program type seems like the simplest way to fix this. Fixes: 0baf26b0fcd7 ("bpf: tcp: Support tcp_congestion_ops in bpf") Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Daniel Borkmann Acked-by: Martin KaFai Lau Link: https://lore.kernel.org/bpf/20210326100314.121853-1-toke@redhat.com --- kernel/bpf/verifier.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 44e4ec1640f1..3a738724a380 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -12158,6 +12158,11 @@ static int check_struct_ops_btf_id(struct bpf_verifier_env *env) u32 btf_id, member_idx; const char *mname; + if (!prog->gpl_compatible) { + verbose(env, "struct ops programs must have a GPL compatible license\n"); + return -EINVAL; + } + btf_id = prog->aux->attach_btf_id; st_ops = bpf_struct_ops_find(btf_id); if (!st_ops) { From d8e8052e42d0f8ff59898b9b4142b16958627ac9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Toke=20H=C3=B8iland-J=C3=B8rgensen?= Date: Fri, 26 Mar 2021 11:03:14 +0100 Subject: [PATCH 0441/1091] bpf/selftests: Test that kernel rejects a TCP CC with an invalid license MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This adds a selftest to check that the verifier rejects a TCP CC struct_ops with a non-GPL license. Signed-off-by: Toke Høiland-Jørgensen Signed-off-by: Daniel Borkmann Acked-by: Martin KaFai Lau Link: https://lore.kernel.org/bpf/20210326100314.121853-2-toke@redhat.com --- .../selftests/bpf/prog_tests/bpf_tcp_ca.c | 44 +++++++++++++++++++ .../selftests/bpf/progs/bpf_tcp_nogpl.c | 19 ++++++++ 2 files changed, 63 insertions(+) create mode 100644 tools/testing/selftests/bpf/progs/bpf_tcp_nogpl.c diff --git a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c index 37c5494a0381..e25917f04602 100644 --- a/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c +++ b/tools/testing/selftests/bpf/prog_tests/bpf_tcp_ca.c @@ -6,6 +6,7 @@ #include #include "bpf_dctcp.skel.h" #include "bpf_cubic.skel.h" +#include "bpf_tcp_nogpl.skel.h" #define min(a, b) ((a) < (b) ? (a) : (b)) @@ -227,10 +228,53 @@ static void test_dctcp(void) bpf_dctcp__destroy(dctcp_skel); } +static char *err_str; +static bool found; + +static int libbpf_debug_print(enum libbpf_print_level level, + const char *format, va_list args) +{ + char *log_buf; + + if (level != LIBBPF_WARN || + strcmp(format, "libbpf: \n%s\n")) { + vprintf(format, args); + return 0; + } + + log_buf = va_arg(args, char *); + if (!log_buf) + goto out; + if (err_str && strstr(log_buf, err_str) != NULL) + found = true; +out: + printf(format, log_buf); + return 0; +} + +static void test_invalid_license(void) +{ + libbpf_print_fn_t old_print_fn; + struct bpf_tcp_nogpl *skel; + + err_str = "struct ops programs must have a GPL compatible license"; + found = false; + old_print_fn = libbpf_set_print(libbpf_debug_print); + + skel = bpf_tcp_nogpl__open_and_load(); + ASSERT_NULL(skel, "bpf_tcp_nogpl"); + ASSERT_EQ(found, true, "expected_err_msg"); + + bpf_tcp_nogpl__destroy(skel); + libbpf_set_print(old_print_fn); +} + void test_bpf_tcp_ca(void) { if (test__start_subtest("dctcp")) test_dctcp(); if (test__start_subtest("cubic")) test_cubic(); + if (test__start_subtest("invalid_license")) + test_invalid_license(); } diff --git a/tools/testing/selftests/bpf/progs/bpf_tcp_nogpl.c b/tools/testing/selftests/bpf/progs/bpf_tcp_nogpl.c new file mode 100644 index 000000000000..2ecd833dcd41 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/bpf_tcp_nogpl.c @@ -0,0 +1,19 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include +#include +#include +#include +#include "bpf_tcp_helpers.h" + +char _license[] SEC("license") = "X"; + +void BPF_STRUCT_OPS(nogpltcp_init, struct sock *sk) +{ +} + +SEC(".struct_ops") +struct tcp_congestion_ops bpf_nogpltcp = { + .init = (void *)nogpltcp_init, + .name = "bpf_nogpltcp", +}; From d6fe1cf89026d3111112ee29ef8d93cd7a8aaa24 Mon Sep 17 00:00:00 2001 From: Xu Kuohai Date: Thu, 25 Mar 2021 13:41:41 +0000 Subject: [PATCH 0442/1091] bpf: Fix a spelling typo in bpf_atomic_alu_string disasm The name string for BPF_XOR is "xor", not "or". Fix it. Fixes: 981f94c3e921 ("bpf: Add bitwise atomic instructions") Signed-off-by: Xu Kuohai Signed-off-by: Daniel Borkmann Acked-by: Brendan Jackman Link: https://lore.kernel.org/bpf/20210325134141.8533-1-xukuohai@huawei.com --- kernel/bpf/disasm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/bpf/disasm.c b/kernel/bpf/disasm.c index 3acc7e0b6916..faa54d58972c 100644 --- a/kernel/bpf/disasm.c +++ b/kernel/bpf/disasm.c @@ -84,7 +84,7 @@ static const char *const bpf_atomic_alu_string[16] = { [BPF_ADD >> 4] = "add", [BPF_AND >> 4] = "and", [BPF_OR >> 4] = "or", - [BPF_XOR >> 4] = "or", + [BPF_XOR >> 4] = "xor", }; static const char *const bpf_ldst_string[] = { From cf97d7af246831ea23c216f17205f91319afc85f Mon Sep 17 00:00:00 2001 From: Pawel Laszczak Date: Mon, 22 Mar 2021 06:47:14 +0100 Subject: [PATCH 0443/1091] usb: cdnsp: Fixes issue with dequeuing requests after disabling endpoint Patch fixes the bug: BUG: kernel NULL pointer dereference, address: 0000000000000050 PGD 0 P4D 0 Oops: 0002 [#1] SMP PTI CPU: 0 PID: 4137 Comm: uvc-gadget Tainted: G OE 5.10.0-next-20201214+ #3 Hardware name: ASUS All Series/Q87T, BIOS 0908 07/22/2014 RIP: 0010:cdnsp_remove_request+0xe9/0x530 [cdnsp_udc_pci] Code: 01 00 00 31 f6 48 89 df e8 64 d4 ff ff 48 8b 43 08 48 8b 13 45 31 f6 48 89 42 08 48 89 10 b8 98 ff ff ff 48 89 1b 48 89 5b 08 <41> 83 6d 50 01 41 83 af d0 00 00 00 01 41 f6 84 24 78 20 00 00 08 RSP: 0018:ffffb68d00d07b60 EFLAGS: 00010046 RAX: 00000000ffffff98 RBX: ffff9d29c57fbf00 RCX: 0000000000001400 RDX: ffff9d29c57fbf00 RSI: 0000000000000000 RDI: ffff9d29c57fbf00 RBP: ffffb68d00d07bb0 R08: ffff9d2ad9510a00 R09: ffff9d2ac011c000 R10: ffff9d2a12b6e760 R11: 0000000000000000 R12: ffff9d29d3fb8000 R13: 0000000000000000 R14: 0000000000000000 R15: ffff9d29d3fb88c0 FS: 0000000000000000(0000) GS:ffff9d2adba00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000050 CR3: 0000000102164005 CR4: 00000000001706f0 Call Trace: cdnsp_ep_dequeue+0x3c/0x90 [cdnsp_udc_pci] cdnsp_gadget_ep_dequeue+0x3f/0x80 [cdnsp_udc_pci] usb_ep_dequeue+0x21/0x70 [udc_core] uvcg_video_enable+0x19d/0x220 [usb_f_uvc] uvc_v4l2_release+0x49/0x90 [usb_f_uvc] v4l2_release+0xa5/0x100 [videodev] __fput+0x99/0x250 ____fput+0xe/0x10 task_work_run+0x75/0xb0 do_exit+0x370/0xb80 do_group_exit+0x43/0xa0 get_signal+0x12d/0x820 arch_do_signal_or_restart+0xb2/0x870 ? __switch_to_asm+0x36/0x70 ? kern_select+0xc6/0x100 exit_to_user_mode_prepare+0xfc/0x170 syscall_exit_to_user_mode+0x2a/0x40 do_syscall_64+0x43/0x80 entry_SYSCALL_64_after_hwframe+0x44/0xa9 RIP: 0033:0x7fe969cf5dd7 Code: Unable to access opcode bytes at RIP 0x7fe969cf5dad. Problem occurs for UVC class. During disconnecting the UVC class disable endpoints and then start dequeuing all requests. This leads to situation where requests are removed twice. The first one in cdnsp_gadget_ep_disable and the second in cdnsp_gadget_ep_dequeue function. Patch adds condition in cdnsp_gadget_ep_dequeue function which allows dequeue requests only from enabled endpoint. Fixes: 3d82904559f4 ("usb: cdnsp: cdns3 Add main part of Cadence USBSSP DRD Driver") Signed-off-by: Pawel Laszczak Signed-off-by: Peter Chen --- drivers/usb/cdns3/cdnsp-gadget.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/usb/cdns3/cdnsp-gadget.c b/drivers/usb/cdns3/cdnsp-gadget.c index f2ebbacd932e..d7d4bdd57f46 100644 --- a/drivers/usb/cdns3/cdnsp-gadget.c +++ b/drivers/usb/cdns3/cdnsp-gadget.c @@ -1128,6 +1128,10 @@ static int cdnsp_gadget_ep_dequeue(struct usb_ep *ep, return -ESHUTDOWN; } + /* Requests has been dequeued during disabling endpoint. */ + if (!(pep->ep_state & EP_ENABLED)) + return 0; + spin_lock_irqsave(&pdev->lock, flags); ret = cdnsp_ep_dequeue(pep, to_cdnsp_request(request)); spin_unlock_irqrestore(&pdev->lock, flags); From 861de02e5f3f2a104eecc5af1d248cb7bf8c5f75 Mon Sep 17 00:00:00 2001 From: Jiri Olsa Date: Fri, 26 Mar 2021 11:59:00 +0100 Subject: [PATCH 0444/1091] bpf: Take module reference for trampoline in module Currently module can be unloaded even if there's a trampoline register in it. It's easily reproduced by running in parallel: # while :; do ./test_progs -t module_attach; done # while :; do rmmod bpf_testmod; sleep 0.5; done Taking the module reference in case the trampoline's ip is within the module code. Releasing it when the trampoline's ip is unregistered. Signed-off-by: Jiri Olsa Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20210326105900.151466-1-jolsa@kernel.org --- include/linux/bpf.h | 2 ++ kernel/bpf/trampoline.c | 30 ++++++++++++++++++++++++++++++ 2 files changed, 32 insertions(+) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 3625f019767d..fdac0534ce79 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -40,6 +40,7 @@ struct bpf_local_storage; struct bpf_local_storage_map; struct kobject; struct mem_cgroup; +struct module; extern struct idr btf_idr; extern spinlock_t btf_idr_lock; @@ -623,6 +624,7 @@ struct bpf_trampoline { /* Executable image of trampoline */ struct bpf_tramp_image *cur_image; u64 selector; + struct module *mod; }; struct bpf_attach_target_info { diff --git a/kernel/bpf/trampoline.c b/kernel/bpf/trampoline.c index 1f3a4be4b175..4aa8b52adf25 100644 --- a/kernel/bpf/trampoline.c +++ b/kernel/bpf/trampoline.c @@ -9,6 +9,7 @@ #include #include #include +#include /* dummy _ops. The verifier will operate on target program's ops. */ const struct bpf_verifier_ops bpf_extension_verifier_ops = { @@ -87,6 +88,26 @@ out: return tr; } +static int bpf_trampoline_module_get(struct bpf_trampoline *tr) +{ + struct module *mod; + int err = 0; + + preempt_disable(); + mod = __module_text_address((unsigned long) tr->func.addr); + if (mod && !try_module_get(mod)) + err = -ENOENT; + preempt_enable(); + tr->mod = mod; + return err; +} + +static void bpf_trampoline_module_put(struct bpf_trampoline *tr) +{ + module_put(tr->mod); + tr->mod = NULL; +} + static int is_ftrace_location(void *ip) { long addr; @@ -108,6 +129,9 @@ static int unregister_fentry(struct bpf_trampoline *tr, void *old_addr) ret = unregister_ftrace_direct((long)ip, (long)old_addr); else ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, old_addr, NULL); + + if (!ret) + bpf_trampoline_module_put(tr); return ret; } @@ -134,10 +158,16 @@ static int register_fentry(struct bpf_trampoline *tr, void *new_addr) return ret; tr->func.ftrace_managed = ret; + if (bpf_trampoline_module_get(tr)) + return -ENOENT; + if (tr->func.ftrace_managed) ret = register_ftrace_direct((long)ip, (long)new_addr); else ret = bpf_arch_text_poke(ip, BPF_MOD_CALL, NULL, new_addr); + + if (ret) + bpf_trampoline_module_put(tr); return ret; } From 4e53d1701b574b1ee9d500b4913a1ece2fac8911 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 26 Mar 2021 10:05:25 -0600 Subject: [PATCH 0445/1091] tomoyo: don't special case PF_IO_WORKER for PF_KTHREAD Since commit 3bfe6106693b6b4b ("io-wq: fork worker threads from original task") stopped using PF_KTHREAD flag for the io_uring PF_IO_WORKER threads, tomoyo_kernel_service() no longer needs to check PF_IO_WORKER flag. (This is a 5.12+ patch. Please don't send to stable kernels.) Signed-off-by: Jens Axboe Signed-off-by: Tetsuo Handa --- security/tomoyo/network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/security/tomoyo/network.c b/security/tomoyo/network.c index 478f757ff843..8dc61335f65e 100644 --- a/security/tomoyo/network.c +++ b/security/tomoyo/network.c @@ -613,7 +613,7 @@ static int tomoyo_check_unix_address(struct sockaddr *addr, static bool tomoyo_kernel_service(void) { /* Nothing to do if I am a kernel service. */ - return (current->flags & (PF_KTHREAD | PF_IO_WORKER)) == PF_KTHREAD; + return current->flags & PF_KTHREAD; } /** From 781bab3238c21c8cc6d1999a6ee43de76252fdfd Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Fri, 26 Mar 2021 15:19:27 -0700 Subject: [PATCH 0446/1091] Input: elants_i2c - fix division by zero if firmware reports zero phys size Touchscreen firmware of ASUS Transformer TF700T reports zeros for the phys size. Hence check whether the size is zero and don't set the resolution in this case. Reported-by: Jasper Korten Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210302100824.3423-1-digetx@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 4c2b579f6c8b..78172c31529a 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1441,7 +1441,7 @@ static int elants_i2c_probe(struct i2c_client *client, touchscreen_parse_properties(ts->input, true, &ts->prop); - if (ts->chip_id == EKTF3624) { + if (ts->chip_id == EKTF3624 && ts->phy_x && ts->phy_y) { /* calculate resolution from size */ ts->x_res = DIV_ROUND_CLOSEST(ts->prop.max_x, ts->phy_x); ts->y_res = DIV_ROUND_CLOSEST(ts->prop.max_y, ts->phy_y); From 84d572e634e28827d105746c922d8ada425e2d8b Mon Sep 17 00:00:00 2001 From: Matthew Rosato Date: Thu, 25 Mar 2021 09:41:52 -0400 Subject: [PATCH 0447/1091] MAINTAINERS: add backups for s390 vfio drivers Add a backup for s390 vfio-pci, an additional backup for vfio-ccw and replace the backup for vfio-ap as Pierre is focusing on other areas. Signed-off-by: Matthew Rosato Acked-by: Eric Farman Acked-by: Halil Pasic Acked-by: Pierre Morel Acked-by: Jason J. Herne Link: https://lore.kernel.org/r/1616679712-7139-1-git-send-email-mjrosato@linux.ibm.com Signed-off-by: Christian Borntraeger Signed-off-by: Heiko Carstens --- MAINTAINERS | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 9e876927c60d..68a562374b85 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -15634,8 +15634,8 @@ F: Documentation/s390/pci.rst S390 VFIO AP DRIVER M: Tony Krowiak -M: Pierre Morel M: Halil Pasic +M: Jason Herne L: linux-s390@vger.kernel.org S: Supported W: http://www.ibm.com/developerworks/linux/linux390/ @@ -15647,6 +15647,7 @@ F: drivers/s390/crypto/vfio_ap_private.h S390 VFIO-CCW DRIVER M: Cornelia Huck M: Eric Farman +M: Matthew Rosato R: Halil Pasic L: linux-s390@vger.kernel.org L: kvm@vger.kernel.org @@ -15657,6 +15658,7 @@ F: include/uapi/linux/vfio_ccw.h S390 VFIO-PCI DRIVER M: Matthew Rosato +M: Eric Farman L: linux-s390@vger.kernel.org L: kvm@vger.kernel.org S: Supported From 5a978dcfc0f054e4f6983a0a26355a65e34708cb Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Sat, 27 Mar 2021 09:59:30 +0000 Subject: [PATCH 0448/1091] io_uring: always go for cancellation spin on exec Always try to do cancellation in __io_uring_task_cancel() at least once, so it actually goes and cleans its sqpoll tasks (i.e. via io_sqpoll_cancel_sync()), otherwise sqpoll task may submit new requests after cancellation and it's racy for many reasons. Fixes: 521d6a737a31c ("io_uring: cancel sqpoll via task_work") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/0a21bd6d794bb1629bc906dd57a57b2c2985a8ac.1616839147.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- fs/io_uring.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fs/io_uring.c b/fs/io_uring.c index 1949b80677e7..a4a944da95a0 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -9002,6 +9002,8 @@ void __io_uring_task_cancel(void) /* make sure overflow events are dropped */ atomic_inc(&tctx->in_idle); + __io_uring_files_cancel(NULL); + do { /* read completions before cancelations */ inflight = tctx_inflight(tctx); From 1b479fb801602b22512f53c19b1f93a4fc5d5d9d Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Sun, 28 Mar 2021 00:50:08 -0700 Subject: [PATCH 0449/1091] drivers/net/wan/hdlc_fr: Fix a double free in pvc_xmit In pvc_xmit, if __skb_pad(skb, pad, false) failed, it will free the skb in the first time and goto drop. But the same skb is freed by kfree_skb(skb) in the second time in drop. Maintaining the original function unchanged, my patch adds a new label out to avoid the double free if __skb_pad() failed. Fixes: f5083d0cee08a ("drivers/net/wan/hdlc_fr: Improvements to the code of pvc_xmit") Signed-off-by: Lv Yunlong Signed-off-by: David S. Miller --- drivers/net/wan/hdlc_fr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wan/hdlc_fr.c b/drivers/net/wan/hdlc_fr.c index 0720f5f92caa..4d9dc7d15908 100644 --- a/drivers/net/wan/hdlc_fr.c +++ b/drivers/net/wan/hdlc_fr.c @@ -415,7 +415,7 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev) if (pad > 0) { /* Pad the frame with zeros */ if (__skb_pad(skb, pad, false)) - goto drop; + goto out; skb_put(skb, pad); } } @@ -448,8 +448,9 @@ static netdev_tx_t pvc_xmit(struct sk_buff *skb, struct net_device *dev) return NETDEV_TX_OK; drop: - dev->stats.tx_dropped++; kfree_skb(skb); +out: + dev->stats.tx_dropped++; return NETDEV_TX_OK; } From 5cfad4f45806f6f898b63b8c77cea7452c704cb3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Oliver=20St=C3=A4bler?= Date: Wed, 24 Mar 2021 14:28:41 +0100 Subject: [PATCH 0450/1091] arm64: dts: imx8mm/q: Fix pad control of SD1_DATA0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Fix address of the pad control register (IOMUXC_SW_PAD_CTL_PAD_SD1_DATA0) for SD1_DATA0_GPIO2_IO2. This seems to be a typo but it leads to an exception when pinctrl is applied due to wrong memory address access. Signed-off-by: Oliver Stäbler Reviewed-by: Fabio Estevam Acked-by: Rob Herring Fixes: c1c9d41319c3 ("dt-bindings: imx: Add pinctrl binding doc for imx8mm") Fixes: 748f908cc882 ("arm64: add basic DTS for i.MX8MQ") Signed-off-by: Shawn Guo --- arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h | 2 +- arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h b/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h index 5ccc4cc91959..a003e6af3353 100644 --- a/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h +++ b/arch/arm64/boot/dts/freescale/imx8mm-pinfunc.h @@ -124,7 +124,7 @@ #define MX8MM_IOMUXC_SD1_CMD_USDHC1_CMD 0x0A4 0x30C 0x000 0x0 0x0 #define MX8MM_IOMUXC_SD1_CMD_GPIO2_IO1 0x0A4 0x30C 0x000 0x5 0x0 #define MX8MM_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x0A8 0x310 0x000 0x0 0x0 -#define MX8MM_IOMUXC_SD1_DATA0_GPIO2_IO2 0x0A8 0x31 0x000 0x5 0x0 +#define MX8MM_IOMUXC_SD1_DATA0_GPIO2_IO2 0x0A8 0x310 0x000 0x5 0x0 #define MX8MM_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x0AC 0x314 0x000 0x0 0x0 #define MX8MM_IOMUXC_SD1_DATA1_GPIO2_IO3 0x0AC 0x314 0x000 0x5 0x0 #define MX8MM_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x0B0 0x318 0x000 0x0 0x0 diff --git a/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h b/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h index b94b02080a34..68e8fa172974 100644 --- a/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h +++ b/arch/arm64/boot/dts/freescale/imx8mq-pinfunc.h @@ -130,7 +130,7 @@ #define MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD 0x0A4 0x30C 0x000 0x0 0x0 #define MX8MQ_IOMUXC_SD1_CMD_GPIO2_IO1 0x0A4 0x30C 0x000 0x5 0x0 #define MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0 0x0A8 0x310 0x000 0x0 0x0 -#define MX8MQ_IOMUXC_SD1_DATA0_GPIO2_IO2 0x0A8 0x31 0x000 0x5 0x0 +#define MX8MQ_IOMUXC_SD1_DATA0_GPIO2_IO2 0x0A8 0x310 0x000 0x5 0x0 #define MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1 0x0AC 0x314 0x000 0x0 0x0 #define MX8MQ_IOMUXC_SD1_DATA1_GPIO2_IO3 0x0AC 0x314 0x000 0x5 0x0 #define MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2 0x0B0 0x318 0x000 0x0 0x0 From 56cfe6f820a6315291eb5a1b82bb49633b993d3b Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Sun, 28 Mar 2021 22:57:48 -0700 Subject: [PATCH 0451/1091] Input: elants_i2c - drop zero-checking of ABS_MT_TOUCH_MAJOR resolution Drop unnecessary zero-checking of ABS_MT_TOUCH_MAJOR resolution since there is no difference between setting resolution to 0 vs not setting it at all. This change makes code cleaner a tad. Suggested-by: Dmitry Torokhov Signed-off-by: Dmitry Osipenko Link: https://lore.kernel.org/r/20210328235507.19240-1-digetx@gmail.com Signed-off-by: Dmitry Torokhov --- drivers/input/touchscreen/elants_i2c.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/input/touchscreen/elants_i2c.c b/drivers/input/touchscreen/elants_i2c.c index 78172c31529a..5f7706febcb0 100644 --- a/drivers/input/touchscreen/elants_i2c.c +++ b/drivers/input/touchscreen/elants_i2c.c @@ -1449,8 +1449,7 @@ static int elants_i2c_probe(struct i2c_client *client, input_abs_set_res(ts->input, ABS_MT_POSITION_X, ts->x_res); input_abs_set_res(ts->input, ABS_MT_POSITION_Y, ts->y_res); - if (ts->major_res > 0) - input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, ts->major_res); + input_abs_set_res(ts->input, ABS_MT_TOUCH_MAJOR, ts->major_res); error = input_mt_init_slots(ts->input, MAX_CONTACT_NUM, INPUT_MT_DIRECT | INPUT_MT_DROP_UNUSED); From c7dbf4c08868d9db89b8bfe8f8245ca61b01ed2f Mon Sep 17 00:00:00 2001 From: Steffen Klassert Date: Fri, 26 Mar 2021 09:44:48 +0100 Subject: [PATCH 0452/1091] xfrm: Provide private skb extensions for segmented and hw offloaded ESP packets Commit 94579ac3f6d0 ("xfrm: Fix double ESP trailer insertion in IPsec crypto offload.") added a XFRM_XMIT flag to avoid duplicate ESP trailer insertion on HW offload. This flag is set on the secpath that is shared amongst segments. This lead to a situation where some segments are not transformed correctly when segmentation happens at layer 3. Fix this by using private skb extensions for segmented and hw offloaded ESP packets. Fixes: 94579ac3f6d0 ("xfrm: Fix double ESP trailer insertion in IPsec crypto offload.") Signed-off-by: Steffen Klassert --- net/ipv4/esp4_offload.c | 11 ++++++++++- net/ipv6/esp6_offload.c | 11 ++++++++++- net/xfrm/xfrm_device.c | 2 -- 3 files changed, 20 insertions(+), 4 deletions(-) diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c index ed3de486ea34..33687cf58286 100644 --- a/net/ipv4/esp4_offload.c +++ b/net/ipv4/esp4_offload.c @@ -314,8 +314,17 @@ static int esp_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features_ ip_hdr(skb)->tot_len = htons(skb->len); ip_send_check(ip_hdr(skb)); - if (hw_offload) + if (hw_offload) { + if (!skb_ext_add(skb, SKB_EXT_SEC_PATH)) + return -ENOMEM; + + xo = xfrm_offload(skb); + if (!xo) + return -EINVAL; + + xo->flags |= XFRM_XMIT; return 0; + } err = esp_output_tail(x, skb, &esp); if (err) diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c index f35203ab39f5..4af56affaafd 100644 --- a/net/ipv6/esp6_offload.c +++ b/net/ipv6/esp6_offload.c @@ -348,8 +348,17 @@ static int esp6_xmit(struct xfrm_state *x, struct sk_buff *skb, netdev_features ipv6_hdr(skb)->payload_len = htons(len); - if (hw_offload) + if (hw_offload) { + if (!skb_ext_add(skb, SKB_EXT_SEC_PATH)) + return -ENOMEM; + + xo = xfrm_offload(skb); + if (!xo) + return -EINVAL; + + xo->flags |= XFRM_XMIT; return 0; + } err = esp6_output_tail(x, skb, &esp); if (err) diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c index edf11893dbe8..6d6917b68856 100644 --- a/net/xfrm/xfrm_device.c +++ b/net/xfrm/xfrm_device.c @@ -134,8 +134,6 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur return skb; } - xo->flags |= XFRM_XMIT; - if (skb_is_gso(skb) && unlikely(x->xso.dev != dev)) { struct sk_buff *segs; From 9e9714742fb70467464359693a73b911a630226f Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 25 Mar 2021 13:58:48 +0100 Subject: [PATCH 0453/1091] can: bcm/raw: fix msg_namelen values depending on CAN_REQUIRED_SIZE Since commit f5223e9eee65 ("can: extend sockaddr_can to include j1939 members") the sockaddr_can has been extended in size and a new CAN_REQUIRED_SIZE macro has been introduced to calculate the protocol specific needed size. The ABI for the msg_name and msg_namelen has not been adapted to the new CAN_REQUIRED_SIZE macro for the other CAN protocols which leads to a problem when an existing binary reads the (increased) struct sockaddr_can in msg_name. Fixes: f5223e9eee65 ("can: extend sockaddr_can to include j1939 members") Reported-by: Richard Weinberger Tested-by: Richard Weinberger Acked-by: Kurt Van Dijck Link: https://lore.kernel.org/linux-can/1135648123.112255.1616613706554.JavaMail.zimbra@nod.at/T/#t Link: https://lore.kernel.org/r/20210325125850.1620-1-socketcan@hartkopp.net Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- net/can/bcm.c | 10 ++++++---- net/can/raw.c | 14 ++++++++------ 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/net/can/bcm.c b/net/can/bcm.c index 0e5c37be4a2b..909b9e684e04 100644 --- a/net/can/bcm.c +++ b/net/can/bcm.c @@ -86,6 +86,8 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Oliver Hartkopp "); MODULE_ALIAS("can-proto-2"); +#define BCM_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_ifindex) + /* * easy access to the first 64 bit of can(fd)_frame payload. cp->data is * 64 bit aligned so the offset has to be multiples of 8 which is ensured @@ -1292,7 +1294,7 @@ static int bcm_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) /* no bound device as default => check msg_name */ DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name); - if (msg->msg_namelen < CAN_REQUIRED_SIZE(*addr, can_ifindex)) + if (msg->msg_namelen < BCM_MIN_NAMELEN) return -EINVAL; if (addr->can_family != AF_CAN) @@ -1534,7 +1536,7 @@ static int bcm_connect(struct socket *sock, struct sockaddr *uaddr, int len, struct net *net = sock_net(sk); int ret = 0; - if (len < CAN_REQUIRED_SIZE(*addr, can_ifindex)) + if (len < BCM_MIN_NAMELEN) return -EINVAL; lock_sock(sk); @@ -1616,8 +1618,8 @@ static int bcm_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, sock_recv_ts_and_drops(msg, sk, skb); if (msg->msg_name) { - __sockaddr_check_size(sizeof(struct sockaddr_can)); - msg->msg_namelen = sizeof(struct sockaddr_can); + __sockaddr_check_size(BCM_MIN_NAMELEN); + msg->msg_namelen = BCM_MIN_NAMELEN; memcpy(msg->msg_name, skb->cb, msg->msg_namelen); } diff --git a/net/can/raw.c b/net/can/raw.c index 37b47a39a3ed..139d9471ddcf 100644 --- a/net/can/raw.c +++ b/net/can/raw.c @@ -60,6 +60,8 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Urs Thuermann "); MODULE_ALIAS("can-proto-1"); +#define RAW_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_ifindex) + #define MASK_ALL 0 /* A raw socket has a list of can_filters attached to it, each receiving @@ -394,7 +396,7 @@ static int raw_bind(struct socket *sock, struct sockaddr *uaddr, int len) int err = 0; int notify_enetdown = 0; - if (len < CAN_REQUIRED_SIZE(*addr, can_ifindex)) + if (len < RAW_MIN_NAMELEN) return -EINVAL; if (addr->can_family != AF_CAN) return -EINVAL; @@ -475,11 +477,11 @@ static int raw_getname(struct socket *sock, struct sockaddr *uaddr, if (peer) return -EOPNOTSUPP; - memset(addr, 0, sizeof(*addr)); + memset(addr, 0, RAW_MIN_NAMELEN); addr->can_family = AF_CAN; addr->can_ifindex = ro->ifindex; - return sizeof(*addr); + return RAW_MIN_NAMELEN; } static int raw_setsockopt(struct socket *sock, int level, int optname, @@ -739,7 +741,7 @@ static int raw_sendmsg(struct socket *sock, struct msghdr *msg, size_t size) if (msg->msg_name) { DECLARE_SOCKADDR(struct sockaddr_can *, addr, msg->msg_name); - if (msg->msg_namelen < CAN_REQUIRED_SIZE(*addr, can_ifindex)) + if (msg->msg_namelen < RAW_MIN_NAMELEN) return -EINVAL; if (addr->can_family != AF_CAN) @@ -832,8 +834,8 @@ static int raw_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, sock_recv_ts_and_drops(msg, sk, skb); if (msg->msg_name) { - __sockaddr_check_size(sizeof(struct sockaddr_can)); - msg->msg_namelen = sizeof(struct sockaddr_can); + __sockaddr_check_size(RAW_MIN_NAMELEN); + msg->msg_namelen = RAW_MIN_NAMELEN; memcpy(msg->msg_name, skb->cb, msg->msg_namelen); } From f522d9559b07854c231cf8f0b8cb5a3578f8b44e Mon Sep 17 00:00:00 2001 From: Oliver Hartkopp Date: Thu, 25 Mar 2021 13:58:49 +0100 Subject: [PATCH 0454/1091] can: isotp: fix msg_namelen values depending on CAN_REQUIRED_SIZE Since commit f5223e9eee65 ("can: extend sockaddr_can to include j1939 members") the sockaddr_can has been extended in size and a new CAN_REQUIRED_SIZE macro has been introduced to calculate the protocol specific needed size. The ABI for the msg_name and msg_namelen has not been adapted to the new CAN_REQUIRED_SIZE macro for the other CAN protocols which leads to a problem when an existing binary reads the (increased) struct sockaddr_can in msg_name. Fixes: e057dd3fc20f ("can: add ISO 15765-2:2016 transport protocol") Reported-by: Richard Weinberger Acked-by: Kurt Van Dijck Link: https://lore.kernel.org/linux-can/1135648123.112255.1616613706554.JavaMail.zimbra@nod.at/T/#t Link: https://lore.kernel.org/r/20210325125850.1620-2-socketcan@hartkopp.net Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- net/can/isotp.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/net/can/isotp.c b/net/can/isotp.c index 15ea1234d457..9f94ad3caee9 100644 --- a/net/can/isotp.c +++ b/net/can/isotp.c @@ -77,6 +77,8 @@ MODULE_LICENSE("Dual BSD/GPL"); MODULE_AUTHOR("Oliver Hartkopp "); MODULE_ALIAS("can-proto-6"); +#define ISOTP_MIN_NAMELEN CAN_REQUIRED_SIZE(struct sockaddr_can, can_addr.tp) + #define SINGLE_MASK(id) (((id) & CAN_EFF_FLAG) ? \ (CAN_EFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG) : \ (CAN_SFF_MASK | CAN_EFF_FLAG | CAN_RTR_FLAG)) @@ -986,7 +988,8 @@ static int isotp_recvmsg(struct socket *sock, struct msghdr *msg, size_t size, sock_recv_timestamp(msg, sk, skb); if (msg->msg_name) { - msg->msg_namelen = sizeof(struct sockaddr_can); + __sockaddr_check_size(ISOTP_MIN_NAMELEN); + msg->msg_namelen = ISOTP_MIN_NAMELEN; memcpy(msg->msg_name, skb->cb, msg->msg_namelen); } @@ -1056,7 +1059,7 @@ static int isotp_bind(struct socket *sock, struct sockaddr *uaddr, int len) int notify_enetdown = 0; int do_rx_reg = 1; - if (len < CAN_REQUIRED_SIZE(struct sockaddr_can, can_addr.tp)) + if (len < ISOTP_MIN_NAMELEN) return -EINVAL; /* do not register frame reception for functional addressing */ @@ -1152,13 +1155,13 @@ static int isotp_getname(struct socket *sock, struct sockaddr *uaddr, int peer) if (peer) return -EOPNOTSUPP; - memset(addr, 0, sizeof(*addr)); + memset(addr, 0, ISOTP_MIN_NAMELEN); addr->can_family = AF_CAN; addr->can_ifindex = so->ifindex; addr->can_addr.tp.rx_id = so->rxid; addr->can_addr.tp.tx_id = so->txid; - return sizeof(*addr); + return ISOTP_MIN_NAMELEN; } static int isotp_setsockopt(struct socket *sock, int level, int optname, From f5076c6ba02e8e24c61c40bbf48078929bc0fc79 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Mon, 22 Mar 2021 10:44:54 +0100 Subject: [PATCH 0455/1091] can: uapi: can.h: mark union inside struct can_frame packed In commit ea7800565a12 ("can: add optional DLC element to Classical CAN frame structure") the struct can_frame::can_dlc was put into an anonymous union with another u8 variable. For various reasons some members in struct can_frame and canfd_frame including the first 8 byes of data are expected to have the same memory layout. This is enforced by a BUILD_BUG_ON check in af_can.c. Since the above mentioned commit this check fails on ARM kernels compiled with the ARM OABI (which means CONFIG_AEABI not set). In this case -mabi=apcs-gnu is passed to the compiler, which leads to a structure size boundary of 32, instead of 8 compared to CONFIG_AEABI enabled. This means the the union in struct can_frame takes 4 bytes instead of the expected 1. Rong Chen illustrates the problem with pahole in the ARM OABI case: | struct can_frame { | canid_t can_id; /* 0 4 */ | union { | __u8 len; /* 4 1 */ | __u8 can_dlc; /* 4 1 */ | }; /* 4 4 */ | __u8 __pad; /* 8 1 */ | __u8 __res0; /* 9 1 */ | __u8 len8_dlc; /* 10 1 */ | | /* XXX 5 bytes hole, try to pack */ | | __u8 data[8] | __attribute__((__aligned__(8))); /* 16 8 */ | | /* size: 24, cachelines: 1, members: 6 */ | /* sum members: 19, holes: 1, sum holes: 5 */ | /* forced alignments: 1, forced holes: 1, sum forced holes: 5 */ | /* last cacheline: 24 bytes */ | } __attribute__((__aligned__(8))); Marking the anonymous union as __attribute__((packed)) fixes the BUILD_BUG_ON problem on these compilers. Fixes: ea7800565a12 ("can: add optional DLC element to Classical CAN frame structure") Reported-by: kernel test robot Suggested-by: Rong Chen Link: https://lore.kernel.org/linux-can/2c82ec23-3551-61b5-1bd8-178c3407ee83@hartkopp.net/ Link: https://lore.kernel.org/r/20210325125850.1620-3-socketcan@hartkopp.net Signed-off-by: Oliver Hartkopp Signed-off-by: Marc Kleine-Budde --- include/uapi/linux/can.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/uapi/linux/can.h b/include/uapi/linux/can.h index f75238ac6dce..c7535352fef6 100644 --- a/include/uapi/linux/can.h +++ b/include/uapi/linux/can.h @@ -113,7 +113,7 @@ struct can_frame { */ __u8 len; __u8 can_dlc; /* deprecated */ - }; + } __attribute__((packed)); /* disable padding added in some ABIs */ __u8 __pad; /* padding */ __u8 __res0; /* reserved / padding */ __u8 len8_dlc; /* optional DLC for 8 byte payload length (9 .. 15) */ From 6161a435c1910d07ee00cc25af010889010e1f08 Mon Sep 17 00:00:00 2001 From: Tian Tao Date: Mon, 15 Mar 2021 14:41:26 +0800 Subject: [PATCH 0456/1091] drm/exynos/decon5433: Remove the unused include statements This driver doesn't reference of_gpio.h, so drop it. Signed-off-by: Tian Tao Signed-off-by: Inki Dae --- drivers/gpu/drm/exynos/exynos5433_drm_decon.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c index 1f79bc2a881e..1510e4e2973c 100644 --- a/drivers/gpu/drm/exynos/exynos5433_drm_decon.c +++ b/drivers/gpu/drm/exynos/exynos5433_drm_decon.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include #include From 51520426f4bc3e61cbbf7a39ccf4e411b665002d Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Mon, 29 Mar 2021 11:39:29 +0100 Subject: [PATCH 0457/1091] io_uring: handle setup-failed ctx in kill_timeouts general protection fault, probably for non-canonical address 0xdffffc0000000018: 0000 [#1] KASAN: null-ptr-deref in range [0x00000000000000c0-0x00000000000000c7] RIP: 0010:io_commit_cqring+0x37f/0xc10 fs/io_uring.c:1318 Call Trace: io_kill_timeouts+0x2b5/0x320 fs/io_uring.c:8606 io_ring_ctx_wait_and_kill+0x1da/0x400 fs/io_uring.c:8629 io_uring_create fs/io_uring.c:9572 [inline] io_uring_setup+0x10da/0x2ae0 fs/io_uring.c:9599 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xae It can get into wait_and_kill() before setting up ctx->rings, and hence io_commit_cqring() fails. Mimic poll cancel and do it only when we completed events, there can't be any requests if it failed before initialising rings. Fixes: 80c4cbdb5ee60 ("io_uring: do post-completion chore on t-out cancel") Reported-by: syzbot+0e905eb8228070c457a0@syzkaller.appspotmail.com Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/660261a48f0e7abf260c8e43c87edab3c16736fa.1617014345.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- fs/io_uring.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index a4a944da95a0..088a9d3c420a 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -8603,9 +8603,9 @@ static bool io_kill_timeouts(struct io_ring_ctx *ctx, struct task_struct *tsk, canceled++; } } - io_commit_cqring(ctx); + if (canceled != 0) + io_commit_cqring(ctx); spin_unlock_irq(&ctx->completion_lock); - if (canceled != 0) io_cqring_ev_posted(ctx); return canceled != 0; From 0803a5cb5b7cf369c3e2af4108ee44d0b6e1c197 Mon Sep 17 00:00:00 2001 From: YueHaibing Date: Mon, 29 Mar 2021 23:05:24 +0800 Subject: [PATCH 0458/1091] ASoC: dwc: Fix -Wmissing-prototypes warnings MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit while CONFIG_SND_DESIGNWARE_PCM is not set, building with W=1 shows this: sound/soc/dwc/local.h:127:6: warning: no previous prototype for ‘dw_pcm_push_tx’ [-Wmissing-prototypes] void dw_pcm_push_tx(struct dw_i2s_dev *dev) { } ^~~~~~~~~~~~~~ sound/soc/dwc/local.h:128:6: warning: no previous prototype for ‘dw_pcm_pop_rx’ [-Wmissing-prototypes] void dw_pcm_pop_rx(struct dw_i2s_dev *dev) { } ^~~~~~~~~~~~~ sound/soc/dwc/local.h:129:5: warning: no previous prototype for ‘dw_pcm_register’ [-Wmissing-prototypes] int dw_pcm_register(struct platform_device *pdev) ^~~~~~~~~~~~~~~ Change these to inline functions to fix the warnings. Signed-off-by: YueHaibing Link: https://lore.kernel.org/r/20210329150524.18184-1-yuehaibing@huawei.com Signed-off-by: Mark Brown --- sound/soc/dwc/local.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/dwc/local.h b/sound/soc/dwc/local.h index 91dc70a826f8..1c361eb6127e 100644 --- a/sound/soc/dwc/local.h +++ b/sound/soc/dwc/local.h @@ -124,9 +124,9 @@ void dw_pcm_push_tx(struct dw_i2s_dev *dev); void dw_pcm_pop_rx(struct dw_i2s_dev *dev); int dw_pcm_register(struct platform_device *pdev); #else -void dw_pcm_push_tx(struct dw_i2s_dev *dev) { } -void dw_pcm_pop_rx(struct dw_i2s_dev *dev) { } -int dw_pcm_register(struct platform_device *pdev) +static inline void dw_pcm_push_tx(struct dw_i2s_dev *dev) { } +static inline void dw_pcm_pop_rx(struct dw_i2s_dev *dev) { } +static inline int dw_pcm_register(struct platform_device *pdev) { return -EINVAL; } From 23f23db29ac996a824dce2b3a800c7a002f1c480 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 26 Mar 2021 22:14:30 +0530 Subject: [PATCH 0459/1091] ASoC: amd: update spdx license for acp machine driver update SPDX license for acp machine driver. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/1616777074-5151-1-git-send-email-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/acp-da7219-max98357a.c | 29 +++++----------------------- 1 file changed, 5 insertions(+), 24 deletions(-) diff --git a/sound/soc/amd/acp-da7219-max98357a.c b/sound/soc/amd/acp-da7219-max98357a.c index e65e007fc604..84e3906abd4f 100644 --- a/sound/soc/amd/acp-da7219-max98357a.c +++ b/sound/soc/amd/acp-da7219-max98357a.c @@ -1,27 +1,8 @@ -/* - * Machine driver for AMD ACP Audio engine using DA7219 & MAX98357 codec - * - * Copyright 2017 Advanced Micro Devices, Inc. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR - * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, - * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR - * OTHER DEALINGS IN THE SOFTWARE. - * - */ +// SPDX-License-Identifier: MIT +// +// Machine driver for AMD ACP Audio engine using DA7219, RT5682 & MAX98357 codec +// +//Copyright 2017-2021 Advanced Micro Devices, Inc. #include #include From d463cead11ace05c81de31a0fb9c2507c5c1d0a2 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Fri, 26 Mar 2021 22:14:31 +0530 Subject: [PATCH 0460/1091] ASoC: amd: fix acpi dependency kernel warning Fix ACPI dependency kernel warning produced by powerpc allyesconfig. sound/soc/amd/acp-da7219-max98357a.c:684:28: warning: 'cz_rt5682_card' defined but not used [-Wunused-variable] sound/soc/amd/acp-da7219-max98357a.c:671:28: warning: 'cz_card' defined but not used [-Wunused-variable] Reported-by: Stephen Rothwell Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/1616777074-5151-2-git-send-email-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 43f5d29d7c53..256c19275d45 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -11,7 +11,7 @@ config SND_SOC_AMD_CZ_DA7219MX98357_MACH select SND_SOC_MAX98357A select SND_SOC_ADAU7002 select REGULATOR - depends on SND_SOC_AMD_ACP && I2C && GPIOLIB + depends on SND_SOC_AMD_ACP && I2C && GPIOLIB && ACPI help This option enables machine driver for DA7219, RT5682 and MAX9835. From 502e5321d89214a34a7b8bda697fc98d14b51cae Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Mon, 29 Mar 2021 11:34:28 +0800 Subject: [PATCH 0461/1091] ASoC: fsl_rpmsg: initialise pointers to NULL This fixes the following sparse warnings: sound/soc/fsl/fsl_rpmsg.c:45:45: sparse: sparse: Using plain integer as NULL pointer sound/soc/fsl/fsl_rpmsg.c:45:56: sparse: sparse: Using plain integer as NULL pointer Fixes: b73d9e6225e8 ("ASoC: fsl_rpmsg: Add CPU DAI driver for audio base on rpmsg") Signed-off-by: Shengjiu Wang Reported-by: kernel test robot Link: https://lore.kernel.org/r/1616988868-971-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_rpmsg.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/fsl/fsl_rpmsg.c b/sound/soc/fsl/fsl_rpmsg.c index 2d09d8850e2c..ea5c973e2e84 100644 --- a/sound/soc/fsl/fsl_rpmsg.c +++ b/sound/soc/fsl/fsl_rpmsg.c @@ -42,7 +42,7 @@ static int fsl_rpmsg_hw_params(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct fsl_rpmsg *rpmsg = snd_soc_dai_get_drvdata(dai); - struct clk *p = rpmsg->mclk, *pll = 0, *npll = 0; + struct clk *p = rpmsg->mclk, *pll = NULL, *npll = NULL; u64 rate = params_rate(params); int ret = 0; From c1c03888f1e89e669aa6da0c9a491f02fd6a999e Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Fri, 26 Mar 2021 18:51:48 +0200 Subject: [PATCH 0462/1091] ASoC: SOF: parse multiple SSP DAI and hw configs ASoC parses multiple hw_configs defined in topology. However currently in SOF only the first config is used and others are discarded. First change SOF driver to parse and save possible multiple configs in ssp case. Also save the default config value provided by ASoC. Functionality with only one defined config stays the same. Signed-off-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210326165150.255533-1-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 8 +- sound/soc/sof/sof-audio.h | 2 + sound/soc/sof/topology.c | 188 ++++++++++++++++++++++---------------- 3 files changed, 115 insertions(+), 83 deletions(-) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index 61c3fe17342d..c3dc533f2627 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -673,10 +673,10 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa /* read rate and channels from topology */ switch (dai->dai_config->type) { case SOF_DAI_INTEL_SSP: - rate->min = dai->dai_config->ssp.fsync_rate; - rate->max = dai->dai_config->ssp.fsync_rate; - channels->min = dai->dai_config->ssp.tdm_slots; - channels->max = dai->dai_config->ssp.tdm_slots; + rate->min = dai->dai_config[dai->current_config].ssp.fsync_rate; + rate->max = dai->dai_config[dai->current_config].ssp.fsync_rate; + channels->min = dai->dai_config[dai->current_config].ssp.tdm_slots; + channels->max = dai->dai_config[dai->current_config].ssp.tdm_slots; dev_dbg(component->dev, "rate_min: %d rate_max: %d\n", rate->min, rate->max); diff --git a/sound/soc/sof/sof-audio.h b/sound/soc/sof/sof-audio.h index dc930fc2f4b5..dc274e63ed9a 100644 --- a/sound/soc/sof/sof-audio.h +++ b/sound/soc/sof/sof-audio.h @@ -112,6 +112,8 @@ struct snd_sof_dai { const char *cpu_dai_name; struct sof_ipc_comp_dai comp_dai; + int number_configs; + int current_config; struct sof_ipc_dai_config *dai_config; struct list_head list; /* list in sdev dai list */ }; diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 10f99620eb31..036202768b75 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -2811,12 +2811,14 @@ static void sof_dai_set_format(struct snd_soc_tplg_hw_config *hw_config, * name. Note that the function can only be used for the case that all DAIs * have a common DAI config for now. */ -static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, - struct snd_soc_dai_link *link, - struct sof_ipc_dai_config *config) +static int sof_set_dai_config_multi(struct snd_sof_dev *sdev, u32 size, + struct snd_soc_dai_link *link, + struct sof_ipc_dai_config *config, + int num_conf, int curr_conf) { struct snd_sof_dai *dai; int found = 0; + int i; list_for_each_entry(dai, &sdev->dai_list, list) { if (!dai->name) @@ -2832,19 +2834,27 @@ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, * dai config's dai_index match to the component's * dai_index. */ - config->dai_index = dai->comp_dai.dai_index; + for (i = 0; i < num_conf; i++) + config[i].dai_index = dai->comp_dai.dai_index; + dev_dbg(sdev->dev, "set DAI config for %s index %d\n", + dai->name, config[curr_conf].dai_index); /* send message to DSP */ ret = sof_ipc_tx_message(sdev->ipc, - config->hdr.cmd, config, size, + config[curr_conf].hdr.cmd, + &config[curr_conf], size, &reply, sizeof(reply)); if (ret < 0) { - dev_err(sdev->dev, "error: failed to set DAI config for %s index %d\n", - dai->name, config->dai_index); + dev_err(sdev->dev, + "error: failed to set DAI config for %s index %d\n", + dai->name, config[curr_conf].dai_index); return ret; } - dai->dai_config = kmemdup(config, size, GFP_KERNEL); + + dai->number_configs = num_conf; + dai->current_config = curr_conf; + dai->dai_config = kmemdup(config, size * num_conf, GFP_KERNEL); if (!dai->dai_config) return -ENOMEM; @@ -2868,64 +2878,81 @@ static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, return 0; } +static int sof_set_dai_config(struct snd_sof_dev *sdev, u32 size, + struct snd_soc_dai_link *link, + struct sof_ipc_dai_config *config) +{ + return sof_set_dai_config_multi(sdev, size, link, config, 1, 0); +} + static int sof_link_ssp_load(struct snd_soc_component *scomp, int index, struct snd_soc_dai_link *link, struct snd_soc_tplg_link_config *cfg, struct snd_soc_tplg_hw_config *hw_config, - struct sof_ipc_dai_config *config) + struct sof_ipc_dai_config *config, int curr_conf) { struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); struct snd_soc_tplg_private *private = &cfg->priv; + int num_conf = le32_to_cpu(cfg->num_hw_configs); u32 size = sizeof(*config); int ret; + int i; - /* handle master/slave and inverted clocks */ - sof_dai_set_format(hw_config, config); + /* + * Parse common data, we should have 1 common data per hw_config. + */ + ret = sof_parse_token_sets(scomp, &config->ssp, ssp_tokens, + ARRAY_SIZE(ssp_tokens), private->array, + le32_to_cpu(private->size), + num_conf, size); - /* init IPC */ - memset(&config->ssp, 0, sizeof(struct sof_ipc_dai_ssp_params)); - config->hdr.size = size; - - ret = sof_parse_tokens(scomp, &config->ssp, ssp_tokens, - ARRAY_SIZE(ssp_tokens), private->array, - le32_to_cpu(private->size)); if (ret != 0) { dev_err(scomp->dev, "error: parse ssp tokens failed %d\n", le32_to_cpu(private->size)); return ret; } - config->ssp.mclk_rate = le32_to_cpu(hw_config->mclk_rate); - config->ssp.bclk_rate = le32_to_cpu(hw_config->bclk_rate); - config->ssp.fsync_rate = le32_to_cpu(hw_config->fsync_rate); - config->ssp.tdm_slots = le32_to_cpu(hw_config->tdm_slots); - config->ssp.tdm_slot_width = le32_to_cpu(hw_config->tdm_slot_width); - config->ssp.mclk_direction = hw_config->mclk_direction; - config->ssp.rx_slots = le32_to_cpu(hw_config->rx_slots); - config->ssp.tx_slots = le32_to_cpu(hw_config->tx_slots); + /* process all possible hw configs */ + for (i = 0; i < num_conf; i++) { - dev_dbg(scomp->dev, "tplg: config SSP%d fmt 0x%x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d\n", - config->dai_index, config->format, - config->ssp.mclk_rate, config->ssp.bclk_rate, - config->ssp.fsync_rate, config->ssp.sample_valid_bits, - config->ssp.tdm_slot_width, config->ssp.tdm_slots, - config->ssp.mclk_id, config->ssp.quirks); + /* handle master/slave and inverted clocks */ + sof_dai_set_format(&hw_config[i], &config[i]); - /* validate SSP fsync rate and channel count */ - if (config->ssp.fsync_rate < 8000 || config->ssp.fsync_rate > 192000) { - dev_err(scomp->dev, "error: invalid fsync rate for SSP%d\n", - config->dai_index); - return -EINVAL; - } + config[i].hdr.size = size; - if (config->ssp.tdm_slots < 1 || config->ssp.tdm_slots > 8) { - dev_err(scomp->dev, "error: invalid channel count for SSP%d\n", - config->dai_index); - return -EINVAL; + /* copy differentiating hw configs to ipc structs */ + config[i].ssp.mclk_rate = le32_to_cpu(hw_config[i].mclk_rate); + config[i].ssp.bclk_rate = le32_to_cpu(hw_config[i].bclk_rate); + config[i].ssp.fsync_rate = le32_to_cpu(hw_config[i].fsync_rate); + config[i].ssp.tdm_slots = le32_to_cpu(hw_config[i].tdm_slots); + config[i].ssp.tdm_slot_width = le32_to_cpu(hw_config[i].tdm_slot_width); + config[i].ssp.mclk_direction = hw_config[i].mclk_direction; + config[i].ssp.rx_slots = le32_to_cpu(hw_config[i].rx_slots); + config[i].ssp.tx_slots = le32_to_cpu(hw_config[i].tx_slots); + + dev_dbg(scomp->dev, "tplg: config SSP%d fmt 0x%x mclk %d bclk %d fclk %d width (%d)%d slots %d mclk id %d quirks %d\n", + config[i].dai_index, config[i].format, + config[i].ssp.mclk_rate, config[i].ssp.bclk_rate, + config[i].ssp.fsync_rate, config[i].ssp.sample_valid_bits, + config[i].ssp.tdm_slot_width, config[i].ssp.tdm_slots, + config[i].ssp.mclk_id, config[i].ssp.quirks); + + /* validate SSP fsync rate and channel count */ + if (config[i].ssp.fsync_rate < 8000 || config[i].ssp.fsync_rate > 192000) { + dev_err(scomp->dev, "error: invalid fsync rate for SSP%d\n", + config[i].dai_index); + return -EINVAL; + } + + if (config[i].ssp.tdm_slots < 1 || config[i].ssp.tdm_slots > 8) { + dev_err(scomp->dev, "error: invalid channel count for SSP%d\n", + config[i].dai_index); + return -EINVAL; + } } /* set config for all DAI's with name matching the link name */ - ret = sof_set_dai_config(sdev, size, link, config); + ret = sof_set_dai_config_multi(sdev, size, link, config, num_conf, curr_conf); if (ret < 0) dev_err(scomp->dev, "error: failed to save DAI config for SSP%d\n", config->dai_index); @@ -3216,11 +3243,13 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, struct snd_soc_tplg_link_config *cfg) { struct snd_soc_tplg_private *private = &cfg->priv; - struct sof_ipc_dai_config config; struct snd_soc_tplg_hw_config *hw_config; - int num_hw_configs; + struct sof_ipc_dai_config common_config; + struct sof_ipc_dai_config *config; + int curr_conf; + int num_conf; int ret; - int i = 0; + int i; if (!link->platforms) { dev_err(scomp->dev, "error: no platforms\n"); @@ -3257,13 +3286,11 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, return -EINVAL; } - /* Send BE DAI link configurations to DSP */ - memset(&config, 0, sizeof(config)); + memset(&common_config, 0, sizeof(common_config)); /* get any common DAI tokens */ - ret = sof_parse_tokens(scomp, &config, dai_link_tokens, - ARRAY_SIZE(dai_link_tokens), private->array, - le32_to_cpu(private->size)); + ret = sof_parse_tokens(scomp, &common_config, dai_link_tokens, ARRAY_SIZE(dai_link_tokens), + private->array, le32_to_cpu(private->size)); if (ret != 0) { dev_err(scomp->dev, "error: parse link tokens failed %d\n", le32_to_cpu(private->size)); @@ -3274,71 +3301,74 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, * DAI links are expected to have at least 1 hw_config. * But some older topologies might have no hw_config for HDA dai links. */ - num_hw_configs = le32_to_cpu(cfg->num_hw_configs); - if (!num_hw_configs) { - if (config.type != SOF_DAI_INTEL_HDA) { + hw_config = cfg->hw_config; + num_conf = le32_to_cpu(cfg->num_hw_configs); + if (!num_conf) { + if (common_config.type != SOF_DAI_INTEL_HDA) { dev_err(scomp->dev, "error: unexpected DAI config count %d!\n", le32_to_cpu(cfg->num_hw_configs)); return -EINVAL; } + num_conf = 1; + curr_conf = 0; } else { dev_dbg(scomp->dev, "tplg: %d hw_configs found, default id: %d!\n", cfg->num_hw_configs, le32_to_cpu(cfg->default_hw_config_id)); - for (i = 0; i < num_hw_configs; i++) { - if (cfg->hw_config[i].id == cfg->default_hw_config_id) + for (curr_conf = 0; curr_conf < num_conf; curr_conf++) { + if (hw_config[curr_conf].id == cfg->default_hw_config_id) break; } - if (i == num_hw_configs) { + if (curr_conf == num_conf) { dev_err(scomp->dev, "error: default hw_config id: %d not found!\n", le32_to_cpu(cfg->default_hw_config_id)); return -EINVAL; } } - /* configure dai IPC message */ - hw_config = &cfg->hw_config[i]; + /* Reserve memory for all hw configs, eventually freed by widget */ + config = kcalloc(num_conf, sizeof(*config), GFP_KERNEL); + if (!config) + return -ENOMEM; - config.hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG; - config.format = le32_to_cpu(hw_config->fmt); + /* Copy common data to all config ipc structs */ + for (i = 0; i < num_conf; i++) { + config[i].hdr.cmd = SOF_IPC_GLB_DAI_MSG | SOF_IPC_DAI_CONFIG; + config[i].format = hw_config[i].fmt; + config[i].type = common_config.type; + config[i].dai_index = common_config.dai_index; + } /* now load DAI specific data and send IPC - type comes from token */ - switch (config.type) { + switch (common_config.type) { case SOF_DAI_INTEL_SSP: - ret = sof_link_ssp_load(scomp, index, link, cfg, hw_config, - &config); + ret = sof_link_ssp_load(scomp, index, link, cfg, hw_config, config, curr_conf); break; case SOF_DAI_INTEL_DMIC: - ret = sof_link_dmic_load(scomp, index, link, cfg, hw_config, - &config); + ret = sof_link_dmic_load(scomp, index, link, cfg, hw_config + curr_conf, config); break; case SOF_DAI_INTEL_HDA: - ret = sof_link_hda_load(scomp, index, link, cfg, hw_config, - &config); + ret = sof_link_hda_load(scomp, index, link, cfg, hw_config + curr_conf, config); break; case SOF_DAI_INTEL_ALH: - ret = sof_link_alh_load(scomp, index, link, cfg, hw_config, - &config); + ret = sof_link_alh_load(scomp, index, link, cfg, hw_config + curr_conf, config); break; case SOF_DAI_IMX_SAI: - ret = sof_link_sai_load(scomp, index, link, cfg, hw_config, - &config); + ret = sof_link_sai_load(scomp, index, link, cfg, hw_config + curr_conf, config); break; case SOF_DAI_IMX_ESAI: - ret = sof_link_esai_load(scomp, index, link, cfg, hw_config, - &config); + ret = sof_link_esai_load(scomp, index, link, cfg, hw_config + curr_conf, config); break; default: - dev_err(scomp->dev, "error: invalid DAI type %d\n", - config.type); + dev_err(scomp->dev, "error: invalid DAI type %d\n", common_config.type); ret = -EINVAL; break; } - if (ret < 0) - return ret; - return 0; + kfree(config); + + return ret; } static int sof_link_hda_unload(struct snd_sof_dev *sdev, From e12be9fbfb91173b3aa358466ce0474823be2695 Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Fri, 26 Mar 2021 18:51:49 +0200 Subject: [PATCH 0463/1091] ASoC: SOF: Intel: HDA: add hw params callback for SSP DAIs Currently SSP DAIs don't have hw params callback function as there wasn't anything to setup after initial topology loading. After enabling multiple DAI configs the current config can be sent in the callback. This patch changes the way SSP config ipc is sent to the dsp. Before it was only sent once in topology loading, but now it will be additionally sent always when stream is opened. Mechanism is similar as with HDA DAIs. Signed-off-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210326165150.255533-2-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/hda-dai.c | 44 +++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/sound/soc/sof/intel/hda-dai.c b/sound/soc/sof/intel/hda-dai.c index c6cb8c212eca..8d7bab433fb3 100644 --- a/sound/soc/sof/intel/hda-dai.c +++ b/sound/soc/sof/intel/hda-dai.c @@ -414,6 +414,44 @@ static struct snd_soc_cdai_ops sof_probe_compr_ops = { #endif #endif +static int ssp_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); + struct snd_soc_component *component = snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); + struct sof_ipc_dai_config *config; + struct snd_sof_dai *sof_dai; + struct sof_ipc_reply reply; + int ret; + + list_for_each_entry(sof_dai, &sdev->dai_list, list) { + if (!sof_dai->cpu_dai_name || !sof_dai->dai_config) + continue; + + if (!strcmp(dai->name, sof_dai->cpu_dai_name) && + substream->stream == sof_dai->comp_dai.direction) { + config = &sof_dai->dai_config[sof_dai->current_config]; + + /* send IPC */ + ret = sof_ipc_tx_message(sdev->ipc, config->hdr.cmd, config, + config->hdr.size, &reply, sizeof(reply)); + + if (ret < 0) + dev_err(sdev->dev, "error: failed to set DAI config for %s\n", + sof_dai->name); + return ret; + } + } + + return 0; +} + +static const struct snd_soc_dai_ops ssp_dai_ops = { + .hw_params = ssp_dai_hw_params, +}; + /* * common dai driver for skl+ platforms. * some products who use this DAI array only physically have a subset of @@ -422,6 +460,7 @@ static struct snd_soc_cdai_ops sof_probe_compr_ops = { struct snd_soc_dai_driver skl_dai[] = { { .name = "SSP0 Pin", + .ops = &ssp_dai_ops, .playback = { .channels_min = 1, .channels_max = 8, @@ -433,6 +472,7 @@ struct snd_soc_dai_driver skl_dai[] = { }, { .name = "SSP1 Pin", + .ops = &ssp_dai_ops, .playback = { .channels_min = 1, .channels_max = 8, @@ -444,6 +484,7 @@ struct snd_soc_dai_driver skl_dai[] = { }, { .name = "SSP2 Pin", + .ops = &ssp_dai_ops, .playback = { .channels_min = 1, .channels_max = 8, @@ -455,6 +496,7 @@ struct snd_soc_dai_driver skl_dai[] = { }, { .name = "SSP3 Pin", + .ops = &ssp_dai_ops, .playback = { .channels_min = 1, .channels_max = 8, @@ -466,6 +508,7 @@ struct snd_soc_dai_driver skl_dai[] = { }, { .name = "SSP4 Pin", + .ops = &ssp_dai_ops, .playback = { .channels_min = 1, .channels_max = 8, @@ -477,6 +520,7 @@ struct snd_soc_dai_driver skl_dai[] = { }, { .name = "SSP5 Pin", + .ops = &ssp_dai_ops, .playback = { .channels_min = 1, .channels_max = 8, From c943a586f6e49998b323afbd7f788afabf6ed89b Mon Sep 17 00:00:00 2001 From: Jaska Uimonen Date: Fri, 26 Mar 2021 18:51:50 +0200 Subject: [PATCH 0464/1091] ASoC: SOF: match SSP config with pcm hw params This patch adds a function to find a match between pcm hw params and SSP DAI config. Config is matched against sample rate and if match is found current config is set. If match isn't found last matched config is left as current i.e. current config is not touched. Functionality for SSP DAIs with 1 config remains the same as before. Signed-off-by: Jaska Uimonen Reviewed-by: Ranjani Sridharan Reviewed-by: Pierre-Louis Bossart Reviewed-by: Guennadi Liakhovetski Signed-off-by: Kai Vehmanen Link: https://lore.kernel.org/r/20210326165150.255533-3-kai.vehmanen@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index c3dc533f2627..d6b1c8b7bdfb 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -619,6 +619,31 @@ capture: return 0; } +static void ssp_dai_config_pcm_params_match(struct snd_sof_dev *sdev, const char *link_name, + struct snd_pcm_hw_params *params) +{ + struct sof_ipc_dai_config *config; + struct snd_sof_dai *dai; + int i; + + /* + * Search for all matching DAIs as we can have both playback and capture DAI + * associated with the same link. + */ + list_for_each_entry(dai, &sdev->dai_list, list) { + if (!dai->name || strcmp(link_name, dai->name)) + continue; + for (i = 0; i < dai->number_configs; i++) { + config = &dai->dai_config[i]; + if (config->ssp.fsync_rate == params_rate(params)) { + dev_dbg(sdev->dev, "DAI config %d matches pcm hw params\n", i); + dai->current_config = i; + break; + } + } + } +} + /* fixup the BE DAI link to match any values from topology */ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { @@ -631,6 +656,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa snd_soc_rtdcom_lookup(rtd, SOF_AUDIO_PCM_DRV_NAME); struct snd_sof_dai *dai = snd_sof_find_dai(component, (char *)rtd->dai_link->name); + struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(component); struct snd_soc_dpcm *dpcm; /* no topology exists for this BE, try a common configuration */ @@ -673,6 +699,9 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa /* read rate and channels from topology */ switch (dai->dai_config->type) { case SOF_DAI_INTEL_SSP: + /* search for config to pcm params match, if not found use default */ + ssp_dai_config_pcm_params_match(sdev, (char *)rtd->dai_link->name, params); + rate->min = dai->dai_config[dai->current_config].ssp.fsync_rate; rate->max = dai->dai_config[dai->current_config].ssp.fsync_rate; channels->min = dai->dai_config[dai->current_config].ssp.tdm_slots; From 08771bce330036d473be6ce851cd00bcd351ebf6 Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Fri, 26 Feb 2021 13:19:22 -0800 Subject: [PATCH 0465/1091] ice: Continue probe on link/PHY errors An incorrect NVM update procedure can result in the driver failing probe. In this case, the recommended resolution method is to update the NVM using the right procedure. However, if the driver fails probe, the user will not be able to update the NVM. So do not fail probe on link/PHY errors. Fixes: 1a3571b5938c ("ice: restore PHY settings on media insertion") Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_main.c | 15 ++++++--------- 1 file changed, 6 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 2c23c8f468a5..53e053c997eb 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -4192,28 +4192,25 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent) goto err_send_version_unroll; } + /* not a fatal error if this fails */ err = ice_init_nvm_phy_type(pf->hw.port_info); - if (err) { + if (err) dev_err(dev, "ice_init_nvm_phy_type failed: %d\n", err); - goto err_send_version_unroll; - } + /* not a fatal error if this fails */ err = ice_update_link_info(pf->hw.port_info); - if (err) { + if (err) dev_err(dev, "ice_update_link_info failed: %d\n", err); - goto err_send_version_unroll; - } ice_init_link_dflt_override(pf->hw.port_info); /* if media available, initialize PHY settings */ if (pf->hw.port_info->phy.link_info.link_info & ICE_AQ_MEDIA_AVAILABLE) { + /* not a fatal error if this fails */ err = ice_init_phy_user_cfg(pf->hw.port_info); - if (err) { + if (err) dev_err(dev, "ice_init_phy_user_cfg failed: %d\n", err); - goto err_send_version_unroll; - } if (!test_bit(ICE_FLAG_LINK_DOWN_ON_CLOSE_ENA, pf->flags)) { struct ice_vsi *vsi = ice_get_main_vsi(pf); From f88c529ac77b3c21819d2cf1dfcfae1937849743 Mon Sep 17 00:00:00 2001 From: Fabio Pricoco Date: Fri, 26 Feb 2021 13:19:24 -0800 Subject: [PATCH 0466/1091] ice: Increase control queue timeout 250 msec timeout is insufficient for some AQ commands. Advice from FW team was to increase the timeout. Increase to 1 second. Fixes: 7ec59eeac804 ("ice: Add support for control queues") Signed-off-by: Fabio Pricoco Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_controlq.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_controlq.h b/drivers/net/ethernet/intel/ice/ice_controlq.h index faaa08e8171b..68866f4f0eb0 100644 --- a/drivers/net/ethernet/intel/ice/ice_controlq.h +++ b/drivers/net/ethernet/intel/ice/ice_controlq.h @@ -31,8 +31,8 @@ enum ice_ctl_q { ICE_CTL_Q_MAILBOX, }; -/* Control Queue timeout settings - max delay 250ms */ -#define ICE_CTL_Q_SQ_CMD_TIMEOUT 2500 /* Count 2500 times */ +/* Control Queue timeout settings - max delay 1s */ +#define ICE_CTL_Q_SQ_CMD_TIMEOUT 10000 /* Count 10000 times */ #define ICE_CTL_Q_SQ_CMD_USEC 100 /* Check every 100usec */ #define ICE_CTL_Q_ADMIN_INIT_TIMEOUT 10 /* Count 10 times */ #define ICE_CTL_Q_ADMIN_INIT_MSEC 100 /* Check every 100msec */ From aeac8ce864d9c0836e12ed5b5cc80f62f3cccb7c Mon Sep 17 00:00:00 2001 From: Chinh T Cao Date: Fri, 26 Feb 2021 13:19:25 -0800 Subject: [PATCH 0467/1091] ice: Recognize 860 as iSCSI port in CEE mode iSCSI can use both TCP ports 860 and 3260. However, in our current implementation, the ice_aqc_opc_get_cee_dcb_cfg (0x0A07) AQ command doesn't provide a way to communicate the protocol port number to the AQ's caller. Thus, we assume that 3260 is the iSCSI port number at the AQ's caller layer. Rely on the dcbx-willing mode, desired QoS and remote QoS configuration to determine which port number that iSCSI will use. Fixes: 0ebd3ff13cca ("ice: Add code for DCB initialization part 2/4") Signed-off-by: Chinh T Cao Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_dcb.c | 38 +++++++++++++++++------ drivers/net/ethernet/intel/ice/ice_type.h | 1 + 2 files changed, 30 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_dcb.c b/drivers/net/ethernet/intel/ice/ice_dcb.c index e42727941ef5..211ac6f907ad 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb.c @@ -738,22 +738,27 @@ ice_aq_get_cee_dcb_cfg(struct ice_hw *hw, /** * ice_cee_to_dcb_cfg * @cee_cfg: pointer to CEE configuration struct - * @dcbcfg: DCB configuration struct + * @pi: port information structure * * Convert CEE configuration from firmware to DCB configuration */ static void ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, - struct ice_dcbx_cfg *dcbcfg) + struct ice_port_info *pi) { u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status); u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift; + u8 i, j, err, sync, oper, app_index, ice_app_sel_type; u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); - u8 i, err, sync, oper, app_index, ice_app_sel_type; u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift; + struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg; u16 ice_app_prot_id_type; - /* CEE PG data to ETS config */ + dcbcfg = &pi->qos_cfg.local_dcbx_cfg; + dcbcfg->dcbx_mode = ICE_DCBX_MODE_CEE; + dcbcfg->tlv_status = tlv_status; + + /* CEE PG data */ dcbcfg->etscfg.maxtcs = cee_cfg->oper_num_tc; /* Note that the FW creates the oper_prio_tc nibbles reversed @@ -780,10 +785,16 @@ ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, } } - /* CEE PFC data to ETS config */ + /* CEE PFC data */ dcbcfg->pfc.pfcena = cee_cfg->oper_pfc_en; dcbcfg->pfc.pfccap = ICE_MAX_TRAFFIC_CLASS; + /* CEE APP TLV data */ + if (dcbcfg->app_mode == ICE_DCBX_APPS_NON_WILLING) + cmp_dcbcfg = &pi->qos_cfg.desired_dcbx_cfg; + else + cmp_dcbcfg = &pi->qos_cfg.remote_dcbx_cfg; + app_index = 0; for (i = 0; i < 3; i++) { if (i == 0) { @@ -802,6 +813,18 @@ ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, ice_aqc_cee_app_shift = ICE_AQC_CEE_APP_ISCSI_S; ice_app_sel_type = ICE_APP_SEL_TCPIP; ice_app_prot_id_type = ICE_APP_PROT_ID_ISCSI; + + for (j = 0; j < cmp_dcbcfg->numapps; j++) { + u16 prot_id = cmp_dcbcfg->app[j].prot_id; + u8 sel = cmp_dcbcfg->app[j].selector; + + if (sel == ICE_APP_SEL_TCPIP && + (prot_id == ICE_APP_PROT_ID_ISCSI || + prot_id == ICE_APP_PROT_ID_ISCSI_860)) { + ice_app_prot_id_type = prot_id; + break; + } + } } else { /* FIP APP */ ice_aqc_cee_status_mask = ICE_AQC_CEE_FIP_STATUS_M; @@ -892,11 +915,8 @@ enum ice_status ice_get_dcb_cfg(struct ice_port_info *pi) ret = ice_aq_get_cee_dcb_cfg(pi->hw, &cee_cfg, NULL); if (!ret) { /* CEE mode */ - dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; - dcbx_cfg->dcbx_mode = ICE_DCBX_MODE_CEE; - dcbx_cfg->tlv_status = le32_to_cpu(cee_cfg.tlv_status); - ice_cee_to_dcb_cfg(&cee_cfg, dcbx_cfg); ret = ice_get_ieee_or_cee_dcb_cfg(pi, ICE_DCBX_MODE_CEE); + ice_cee_to_dcb_cfg(&cee_cfg, pi); } else if (pi->hw->adminq.sq_last_status == ICE_AQ_RC_ENOENT) { /* CEE mode not enabled try querying IEEE data */ dcbx_cfg = &pi->qos_cfg.local_dcbx_cfg; diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h index a6cb0c35748c..266036b7a49a 100644 --- a/drivers/net/ethernet/intel/ice/ice_type.h +++ b/drivers/net/ethernet/intel/ice/ice_type.h @@ -535,6 +535,7 @@ struct ice_dcb_app_priority_table { #define ICE_TLV_STATUS_ERR 0x4 #define ICE_APP_PROT_ID_FCOE 0x8906 #define ICE_APP_PROT_ID_ISCSI 0x0cbc +#define ICE_APP_PROT_ID_ISCSI_860 0x035c #define ICE_APP_PROT_ID_FIP 0x8914 #define ICE_APP_SEL_ETHTYPE 0x1 #define ICE_APP_SEL_TCPIP 0x2 From e95fc8573e07c5e4825df4650fd8b8c93fad27a7 Mon Sep 17 00:00:00 2001 From: Krzysztof Goreczny Date: Fri, 26 Feb 2021 13:19:26 -0800 Subject: [PATCH 0468/1091] ice: prevent ice_open and ice_stop during reset There is a possibility of race between ice_open or ice_stop calls performed by OS and reset handling routine both trying to modify VSI resources. Observed scenarios: - reset handler deallocates memory in ice_vsi_free_arrays and ice_open tries to access it in ice_vsi_cfg_txq leading to driver crash - reset handler deallocates memory in ice_vsi_free_arrays and ice_close tries to access it in ice_down leading to driver crash - reset handler clears port scheduler topology and sets port state to ICE_SCHED_PORT_STATE_INIT leading to ice_ena_vsi_txq fail in ice_open To prevent this additional checks in ice_open and ice_stop are introduced to make sure that OS is not allowed to alter VSI config while reset is in progress. Fixes: cdedef59deb0 ("ice: Configure VSIs for Tx/Rx") Signed-off-by: Krzysztof Goreczny Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice.h | 1 + drivers/net/ethernet/intel/ice/ice_lib.c | 4 ++-- drivers/net/ethernet/intel/ice/ice_main.c | 28 +++++++++++++++++++++++ 3 files changed, 31 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 357706444dd5..1d4518638215 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -642,6 +642,7 @@ int ice_fdir_create_dflt_rules(struct ice_pf *pf); int ice_aq_wait_for_event(struct ice_pf *pf, u16 opcode, unsigned long timeout, struct ice_rq_event_info *event); int ice_open(struct net_device *netdev); +int ice_open_internal(struct net_device *netdev); int ice_stop(struct net_device *netdev); void ice_service_task_schedule(struct ice_pf *pf); diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 8d4e2ad4328d..7ac2beaed95c 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -2620,7 +2620,7 @@ int ice_ena_vsi(struct ice_vsi *vsi, bool locked) if (!locked) rtnl_lock(); - err = ice_open(vsi->netdev); + err = ice_open_internal(vsi->netdev); if (!locked) rtnl_unlock(); @@ -2649,7 +2649,7 @@ void ice_dis_vsi(struct ice_vsi *vsi, bool locked) if (!locked) rtnl_lock(); - ice_stop(vsi->netdev); + ice_vsi_close(vsi); if (!locked) rtnl_unlock(); diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 53e053c997eb..255a07c1e33a 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -6632,6 +6632,28 @@ static void ice_tx_timeout(struct net_device *netdev, unsigned int txqueue) * Returns 0 on success, negative value on failure */ int ice_open(struct net_device *netdev) +{ + struct ice_netdev_priv *np = netdev_priv(netdev); + struct ice_pf *pf = np->vsi->back; + + if (ice_is_reset_in_progress(pf->state)) { + netdev_err(netdev, "can't open net device while reset is in progress"); + return -EBUSY; + } + + return ice_open_internal(netdev); +} + +/** + * ice_open_internal - Called when a network interface becomes active + * @netdev: network interface device structure + * + * Internal ice_open implementation. Should not be used directly except for ice_open and reset + * handling routine + * + * Returns 0 on success, negative value on failure + */ +int ice_open_internal(struct net_device *netdev) { struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_vsi *vsi = np->vsi; @@ -6712,6 +6734,12 @@ int ice_stop(struct net_device *netdev) { struct ice_netdev_priv *np = netdev_priv(netdev); struct ice_vsi *vsi = np->vsi; + struct ice_pf *pf = vsi->back; + + if (ice_is_reset_in_progress(pf->state)) { + netdev_err(netdev, "can't stop net device while reset is in progress"); + return -EBUSY; + } ice_vsi_close(vsi); From 59df14f9cc2326bd6432d60eca0df8201d9d3d4b Mon Sep 17 00:00:00 2001 From: Bruce Allan Date: Fri, 26 Feb 2021 13:19:27 -0800 Subject: [PATCH 0469/1091] ice: fix memory allocation call Fix the order of number of array members and member size parameters in a *calloc() call. Fixes: b3c3890489f6 ("ice: avoid unnecessary single-member variable-length structs") Signed-off-by: Bruce Allan Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_common.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 3d9475e222cd..a20edf1538a0 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -717,8 +717,8 @@ static enum ice_status ice_cfg_fw_log(struct ice_hw *hw, bool enable) if (!data) { data = devm_kcalloc(ice_hw_to_dev(hw), - sizeof(*data), ICE_AQC_FW_LOG_ID_MAX, + sizeof(*data), GFP_KERNEL); if (!data) return ICE_ERR_NO_MEMORY; From 1a1c130ab7575498eed5bcf7220037ae09cd1f8a Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 23 Mar 2021 20:26:52 +0100 Subject: [PATCH 0470/1091] ACPI: tables: x86: Reserve memory occupied by ACPI tables The following problem has been reported by George Kennedy: Since commit 7fef431be9c9 ("mm/page_alloc: place pages to tail in __free_pages_core()") the following use after free occurs intermittently when ACPI tables are accessed. BUG: KASAN: use-after-free in ibft_init+0x134/0xc49 Read of size 4 at addr ffff8880be453004 by task swapper/0/1 CPU: 3 PID: 1 Comm: swapper/0 Not tainted 5.12.0-rc1-7a7fd0d #1 Call Trace: dump_stack+0xf6/0x158 print_address_description.constprop.9+0x41/0x60 kasan_report.cold.14+0x7b/0xd4 __asan_report_load_n_noabort+0xf/0x20 ibft_init+0x134/0xc49 do_one_initcall+0xc4/0x3e0 kernel_init_freeable+0x5af/0x66b kernel_init+0x16/0x1d0 ret_from_fork+0x22/0x30 ACPI tables mapped via kmap() do not have their mapped pages reserved and the pages can be "stolen" by the buddy allocator. Apparently, on the affected system, the ACPI table in question is not located in "reserved" memory, like ACPI NVS or ACPI Data, that will not be used by the buddy allocator, so the memory occupied by that table has to be explicitly reserved to prevent the buddy allocator from using it. In order to address this problem, rearrange the initialization of the ACPI tables on x86 to locate the initial tables earlier and reserve the memory occupied by them. The other architectures using ACPI should not be affected by this change. Link: https://lore.kernel.org/linux-acpi/1614802160-29362-1-git-send-email-george.kennedy@oracle.com/ Reported-by: George Kennedy Tested-by: George Kennedy Signed-off-by: Rafael J. Wysocki Reviewed-by: Mike Rapoport Cc: 5.10+ # 5.10+ --- arch/x86/kernel/acpi/boot.c | 25 +++++++++++----------- arch/x86/kernel/setup.c | 8 +++---- drivers/acpi/tables.c | 42 ++++++++++++++++++++++++++++++++++--- include/linux/acpi.h | 9 +++++++- 4 files changed, 62 insertions(+), 22 deletions(-) diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c index 7bdc0239a943..14cd3186dc77 100644 --- a/arch/x86/kernel/acpi/boot.c +++ b/arch/x86/kernel/acpi/boot.c @@ -1554,10 +1554,18 @@ void __init acpi_boot_table_init(void) /* * Initialize the ACPI boot-time table parser. */ - if (acpi_table_init()) { + if (acpi_locate_initial_tables()) disable_acpi(); - return; - } + else + acpi_reserve_initial_tables(); +} + +int __init early_acpi_boot_init(void) +{ + if (acpi_disabled) + return 1; + + acpi_table_init_complete(); acpi_table_parse(ACPI_SIG_BOOT, acpi_parse_sbf); @@ -1570,18 +1578,9 @@ void __init acpi_boot_table_init(void) } else { printk(KERN_WARNING PREFIX "Disabling ACPI support\n"); disable_acpi(); - return; + return 1; } } -} - -int __init early_acpi_boot_init(void) -{ - /* - * If acpi_disabled, bail out - */ - if (acpi_disabled) - return 1; /* * Process the Multiple APIC Description Table (MADT), if present diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index d883176ef2ce..5ecd69a48393 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1045,6 +1045,9 @@ void __init setup_arch(char **cmdline_p) cleanup_highmap(); + /* Look for ACPI tables and reserve memory occupied by them. */ + acpi_boot_table_init(); + memblock_set_current_limit(ISA_END_ADDRESS); e820__memblock_setup(); @@ -1136,11 +1139,6 @@ void __init setup_arch(char **cmdline_p) early_platform_quirks(); - /* - * Parse the ACPI tables for possible boot-time SMP configuration. - */ - acpi_boot_table_init(); - early_acpi_boot_init(); initmem_init(); diff --git a/drivers/acpi/tables.c b/drivers/acpi/tables.c index e48690a006a4..9d581045acff 100644 --- a/drivers/acpi/tables.c +++ b/drivers/acpi/tables.c @@ -780,7 +780,7 @@ acpi_status acpi_os_table_override(struct acpi_table_header *existing_table, } /* - * acpi_table_init() + * acpi_locate_initial_tables() * * find RSDP, find and checksum SDT/XSDT. * checksum all tables, print SDT/XSDT @@ -788,7 +788,7 @@ acpi_status acpi_os_table_override(struct acpi_table_header *existing_table, * result: sdt_entry[] is initialized */ -int __init acpi_table_init(void) +int __init acpi_locate_initial_tables(void) { acpi_status status; @@ -803,9 +803,45 @@ int __init acpi_table_init(void) status = acpi_initialize_tables(initial_tables, ACPI_MAX_TABLES, 0); if (ACPI_FAILURE(status)) return -EINVAL; - acpi_table_initrd_scan(); + return 0; +} + +void __init acpi_reserve_initial_tables(void) +{ + int i; + + for (i = 0; i < ACPI_MAX_TABLES; i++) { + struct acpi_table_desc *table_desc = &initial_tables[i]; + u64 start = table_desc->address; + u64 size = table_desc->length; + + if (!start || !size) + break; + + pr_info("Reserving %4s table memory at [mem 0x%llx-0x%llx]\n", + table_desc->signature.ascii, start, start + size - 1); + + memblock_reserve(start, size); + } +} + +void __init acpi_table_init_complete(void) +{ + acpi_table_initrd_scan(); check_multiple_madt(); +} + +int __init acpi_table_init(void) +{ + int ret; + + ret = acpi_locate_initial_tables(); + if (ret) + return ret; + + acpi_table_init_complete(); + return 0; } diff --git a/include/linux/acpi.h b/include/linux/acpi.h index fcdaab723916..3bdcfc4401b7 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -222,10 +222,14 @@ void __iomem *__acpi_map_table(unsigned long phys, unsigned long size); void __acpi_unmap_table(void __iomem *map, unsigned long size); int early_acpi_boot_init(void); int acpi_boot_init (void); +void acpi_boot_table_prepare (void); void acpi_boot_table_init (void); int acpi_mps_check (void); int acpi_numa_init (void); +int acpi_locate_initial_tables (void); +void acpi_reserve_initial_tables (void); +void acpi_table_init_complete (void); int acpi_table_init (void); int acpi_table_parse(char *id, acpi_tbl_table_handler handler); int __init acpi_table_parse_entries(char *id, unsigned long table_size, @@ -814,9 +818,12 @@ static inline int acpi_boot_init(void) return 0; } +static inline void acpi_boot_table_prepare(void) +{ +} + static inline void acpi_boot_table_init(void) { - return; } static inline int acpi_mps_check(void) From c0c33442f7203704aef345647e14c2fb86071001 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 Mar 2021 12:56:18 +0200 Subject: [PATCH 0471/1091] PM: runtime: Fix ordering in pm_runtime_get_suppliers() rpm_active indicates how many times the supplier usage_count has been incremented. Consequently it must be updated after pm_runtime_get_sync() of the supplier, not before. Fixes: 4c06c4e6cf63 ("driver core: Fix possible supplier PM-usage counter imbalance") Signed-off-by: Adrian Hunter Cc: 5.1+ # 5.1+ Signed-off-by: Rafael J. Wysocki --- drivers/base/power/runtime.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index d54e540067bf..4fde37713c58 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1690,8 +1690,8 @@ void pm_runtime_get_suppliers(struct device *dev) device_links_read_lock_held()) if (link->flags & DL_FLAG_PM_RUNTIME) { link->supplier_preactivated = true; - refcount_inc(&link->rpm_active); pm_runtime_get_sync(link->supplier); + refcount_inc(&link->rpm_active); } device_links_read_unlock(idx); From 9dfacc54a8661bc8be6e08cffee59596ec59f263 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Fri, 26 Mar 2021 12:56:19 +0200 Subject: [PATCH 0472/1091] PM: runtime: Fix race getting/putting suppliers at probe pm_runtime_put_suppliers() must not decrement rpm_active unless the consumer is suspended. That is because, otherwise, it could suspend suppliers for an active consumer. That can happen as follows: static int driver_probe_device(struct device_driver *drv, struct device *dev) { int ret = 0; if (!device_is_registered(dev)) return -ENODEV; dev->can_match = true; pr_debug("bus: '%s': %s: matched device %s with driver %s\n", drv->bus->name, __func__, dev_name(dev), drv->name); pm_runtime_get_suppliers(dev); if (dev->parent) pm_runtime_get_sync(dev->parent); At this point, dev can runtime suspend so rpm_put_suppliers() can run, rpm_active becomes 1 (the lowest value). pm_runtime_barrier(dev); if (initcall_debug) ret = really_probe_debug(dev, drv); else ret = really_probe(dev, drv); Probe callback can have runtime resumed dev, and then runtime put so dev is awaiting autosuspend, but rpm_active is 2. pm_request_idle(dev); if (dev->parent) pm_runtime_put(dev->parent); pm_runtime_put_suppliers(dev); Now pm_runtime_put_suppliers() will put the supplier i.e. rpm_active 2 -> 1, but consumer can still be active. return ret; } Fix by checking the runtime status. For any status other than RPM_SUSPENDED, rpm_active can be considered to be "owned" by rpm_[get/put]_suppliers() and pm_runtime_put_suppliers() need do nothing. Reported-by: Asutosh Das Fixes: 4c06c4e6cf63 ("driver core: Fix possible supplier PM-usage counter imbalance") Signed-off-by: Adrian Hunter Cc: 5.1+ # 5.1+ Signed-off-by: Rafael J. Wysocki --- drivers/base/power/runtime.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/base/power/runtime.c b/drivers/base/power/runtime.c index 4fde37713c58..fe1dad68aee4 100644 --- a/drivers/base/power/runtime.c +++ b/drivers/base/power/runtime.c @@ -1704,6 +1704,8 @@ void pm_runtime_get_suppliers(struct device *dev) void pm_runtime_put_suppliers(struct device *dev) { struct device_link *link; + unsigned long flags; + bool put; int idx; idx = device_links_read_lock(); @@ -1712,7 +1714,11 @@ void pm_runtime_put_suppliers(struct device *dev) device_links_read_lock_held()) if (link->supplier_preactivated) { link->supplier_preactivated = false; - if (refcount_dec_not_one(&link->rpm_active)) + spin_lock_irqsave(&dev->power.lock, flags); + put = pm_runtime_status_suspended(dev) && + refcount_dec_not_one(&link->rpm_active); + spin_unlock_irqrestore(&dev->power.lock, flags); + if (put) pm_runtime_put(link->supplier); } From 741b7b743bbcb5a3848e4e55982064214f900d2f Mon Sep 17 00:00:00 2001 From: Dave Ertman Date: Fri, 26 Feb 2021 13:19:28 -0800 Subject: [PATCH 0473/1091] ice: remove DCBNL_DEVRESET bit from PF state The original purpose of the ICE_DCBNL_DEVRESET was to protect the driver during DCBNL device resets. But, the flow for DCBNL device resets now consists of only calls up the stack such as dev_close() and dev_open() that will result in NDO calls to the driver. These will be handled with state changes from the stack. Also, there is a problem of the dev_close and dev_open being blocked by checks for reset in progress also using the ICE_DCBNL_DEVRESET bit. Since the ICE_DCBNL_DEVRESET bit is not necessary for protecting the driver from DCBNL device resets and it is actually blocking changes coming from the DCBNL interface, remove the bit from the PF state and don't block driver function based on DCBNL reset in progress. Fixes: b94b013eb626 ("ice: Implement DCBNL support") Signed-off-by: Dave Ertman Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice.h | 1 - drivers/net/ethernet/intel/ice/ice_dcb_nl.c | 2 -- drivers/net/ethernet/intel/ice/ice_lib.c | 1 - 3 files changed, 4 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 1d4518638215..7934f0d17277 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -196,7 +196,6 @@ enum ice_state { __ICE_NEEDS_RESTART, __ICE_PREPARED_FOR_RESET, /* set by driver when prepared */ __ICE_RESET_OICR_RECV, /* set by driver after rcv reset OICR */ - __ICE_DCBNL_DEVRESET, /* set by dcbnl devreset */ __ICE_PFR_REQ, /* set by driver and peers */ __ICE_CORER_REQ, /* set by driver and peers */ __ICE_GLOBR_REQ, /* set by driver and peers */ diff --git a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c index 468a63f7eff9..4180f1f35fb8 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb_nl.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb_nl.c @@ -18,12 +18,10 @@ static void ice_dcbnl_devreset(struct net_device *netdev) while (ice_is_reset_in_progress(pf->state)) usleep_range(1000, 2000); - set_bit(__ICE_DCBNL_DEVRESET, pf->state); dev_close(netdev); netdev_state_change(netdev); dev_open(netdev, NULL); netdev_state_change(netdev); - clear_bit(__ICE_DCBNL_DEVRESET, pf->state); } /** diff --git a/drivers/net/ethernet/intel/ice/ice_lib.c b/drivers/net/ethernet/intel/ice/ice_lib.c index 7ac2beaed95c..d13c7fc8fb0a 100644 --- a/drivers/net/ethernet/intel/ice/ice_lib.c +++ b/drivers/net/ethernet/intel/ice/ice_lib.c @@ -3078,7 +3078,6 @@ err_vsi: bool ice_is_reset_in_progress(unsigned long *state) { return test_bit(__ICE_RESET_OICR_RECV, state) || - test_bit(__ICE_DCBNL_DEVRESET, state) || test_bit(__ICE_PFR_REQ, state) || test_bit(__ICE_CORER_REQ, state) || test_bit(__ICE_GLOBR_REQ, state); From 7a91d3f02b04b2fb18c2dfa8b6c4e5a40a2753f5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jacek=20Bu=C5=82atek?= Date: Fri, 26 Feb 2021 13:19:29 -0800 Subject: [PATCH 0474/1091] ice: Fix for dereference of NULL pointer MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add handling of allocation fault for ice_vsi_list_map_info. Also *fi should not be NULL pointer, it is a reference to raw data field, so remove this variable and use the reference directly. Fixes: 9daf8208dd4d ("ice: Add support for switch filter programming") Signed-off-by: Jacek Bułatek Co-developed-by: Haiyue Wang Signed-off-by: Haiyue Wang Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_switch.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 67c965a3f5d2..387d3f6cd71e 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -1238,6 +1238,9 @@ ice_add_update_vsi_list(struct ice_hw *hw, ice_create_vsi_list_map(hw, &vsi_handle_arr[0], 2, vsi_list_id); + if (!m_entry->vsi_list_info) + return ICE_ERR_NO_MEMORY; + /* If this entry was large action then the large action needs * to be updated to point to FWD to VSI list */ @@ -2220,6 +2223,7 @@ ice_vsi_uses_fltr(struct ice_fltr_mgmt_list_entry *fm_entry, u16 vsi_handle) return ((fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI && fm_entry->fltr_info.vsi_handle == vsi_handle) || (fm_entry->fltr_info.fltr_act == ICE_FWD_TO_VSI_LIST && + fm_entry->vsi_list_info && (test_bit(vsi_handle, fm_entry->vsi_list_info->vsi_map)))); } @@ -2292,14 +2296,12 @@ ice_add_to_vsi_fltr_list(struct ice_hw *hw, u16 vsi_handle, return ICE_ERR_PARAM; list_for_each_entry(fm_entry, lkup_list_head, list_entry) { - struct ice_fltr_info *fi; - - fi = &fm_entry->fltr_info; - if (!fi || !ice_vsi_uses_fltr(fm_entry, vsi_handle)) + if (!ice_vsi_uses_fltr(fm_entry, vsi_handle)) continue; status = ice_add_entry_to_vsi_fltr_list(hw, vsi_handle, - vsi_list_head, fi); + vsi_list_head, + &fm_entry->fltr_info); if (status) return status; } From 3176551979b92b02756979c0f1e2d03d1fc82b1e Mon Sep 17 00:00:00 2001 From: Anirudh Venkataramanan Date: Fri, 26 Feb 2021 13:19:30 -0800 Subject: [PATCH 0475/1091] ice: Use port number instead of PF ID for WoL As per the spec, the WoL control word read from the NVM should be interpreted as port numbers, and not PF numbers. So when checking if WoL supported, use the port number instead of the PF ID. Also, ice_is_wol_supported doesn't really need a pointer to the pf struct, but just needs a pointer to the hw instance. Fixes: 769c500dcc1e ("ice: Add advanced power mgmt for WoL") Signed-off-by: Anirudh Venkataramanan Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice.h | 2 +- drivers/net/ethernet/intel/ice/ice_ethtool.c | 4 ++-- drivers/net/ethernet/intel/ice/ice_main.c | 9 ++++----- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice.h b/drivers/net/ethernet/intel/ice/ice.h index 7934f0d17277..17101c45cbcd 100644 --- a/drivers/net/ethernet/intel/ice/ice.h +++ b/drivers/net/ethernet/intel/ice/ice.h @@ -623,7 +623,7 @@ int ice_schedule_reset(struct ice_pf *pf, enum ice_reset_req reset); void ice_print_link_msg(struct ice_vsi *vsi, bool isup); const char *ice_stat_str(enum ice_status stat_err); const char *ice_aq_str(enum ice_aq_err aq_err); -bool ice_is_wol_supported(struct ice_pf *pf); +bool ice_is_wol_supported(struct ice_hw *hw); int ice_fdir_write_fltr(struct ice_pf *pf, struct ice_fdir_fltr *input, bool add, bool is_tun); diff --git a/drivers/net/ethernet/intel/ice/ice_ethtool.c b/drivers/net/ethernet/intel/ice/ice_ethtool.c index 2dcfa685b763..32ba71a16165 100644 --- a/drivers/net/ethernet/intel/ice/ice_ethtool.c +++ b/drivers/net/ethernet/intel/ice/ice_ethtool.c @@ -3472,7 +3472,7 @@ static void ice_get_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) netdev_warn(netdev, "Wake on LAN is not supported on this interface!\n"); /* Get WoL settings based on the HW capability */ - if (ice_is_wol_supported(pf)) { + if (ice_is_wol_supported(&pf->hw)) { wol->supported = WAKE_MAGIC; wol->wolopts = pf->wol_ena ? WAKE_MAGIC : 0; } else { @@ -3492,7 +3492,7 @@ static int ice_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol) struct ice_vsi *vsi = np->vsi; struct ice_pf *pf = vsi->back; - if (vsi->type != ICE_VSI_PF || !ice_is_wol_supported(pf)) + if (vsi->type != ICE_VSI_PF || !ice_is_wol_supported(&pf->hw)) return -EOPNOTSUPP; /* only magic packet is supported */ diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 255a07c1e33a..9f1adff85be7 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -3537,15 +3537,14 @@ static int ice_init_interrupt_scheme(struct ice_pf *pf) } /** - * ice_is_wol_supported - get NVM state of WoL - * @pf: board private structure + * ice_is_wol_supported - check if WoL is supported + * @hw: pointer to hardware info * * Check if WoL is supported based on the HW configuration. * Returns true if NVM supports and enables WoL for this port, false otherwise */ -bool ice_is_wol_supported(struct ice_pf *pf) +bool ice_is_wol_supported(struct ice_hw *hw) { - struct ice_hw *hw = &pf->hw; u16 wol_ctrl; /* A bit set to 1 in the NVM Software Reserved Word 2 (WoL control @@ -3554,7 +3553,7 @@ bool ice_is_wol_supported(struct ice_pf *pf) if (ice_read_sr_word(hw, ICE_SR_NVM_WOL_CFG, &wol_ctrl)) return false; - return !(BIT(hw->pf_id) & wol_ctrl); + return !(BIT(hw->port_info->lport) & wol_ctrl); } /** From b7eeb52721fe417730fc5adc5cbeeb5fe349ab26 Mon Sep 17 00:00:00 2001 From: Robert Malz Date: Fri, 26 Feb 2021 13:19:32 -0800 Subject: [PATCH 0476/1091] ice: Cleanup fltr list in case of allocation issues When ice_remove_vsi_lkup_fltr is called, by calling ice_add_to_vsi_fltr_list local copy of vsi filter list is created. If any issues during creation of vsi filter list occurs it up for the caller to free already allocated memory. This patch ensures proper memory deallocation in these cases. Fixes: 80d144c9ac82 ("ice: Refactor switch rule management structures and functions") Signed-off-by: Robert Malz Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_switch.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ice/ice_switch.c b/drivers/net/ethernet/intel/ice/ice_switch.c index 387d3f6cd71e..834cbd3f7b31 100644 --- a/drivers/net/ethernet/intel/ice/ice_switch.c +++ b/drivers/net/ethernet/intel/ice/ice_switch.c @@ -2624,7 +2624,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, &remove_list_head); mutex_unlock(rule_lock); if (status) - return; + goto free_fltr_list; switch (lkup) { case ICE_SW_LKUP_MAC: @@ -2647,6 +2647,7 @@ ice_remove_vsi_lkup_fltr(struct ice_hw *hw, u16 vsi_handle, break; } +free_fltr_list: list_for_each_entry_safe(fm_entry, tmp, &remove_list_head, list_entry) { list_del(&fm_entry->list_entry); devm_kfree(ice_hw_to_dev(hw), fm_entry); From acc7baafeb0b52a5b91be64c4776f827a163dda1 Mon Sep 17 00:00:00 2001 From: Evan Quan Date: Tue, 23 Mar 2021 16:30:38 +0800 Subject: [PATCH 0477/1091] drm/amd/pm: no need to force MCLK to highest when no display connected Correct the check for vblank short. Signed-off-by: Evan Quan Reviewed-by: Alex Deucher Tested-by: Alex Deucher Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index 22b6a8e8bd21..d0ec83881fc5 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -3330,7 +3330,8 @@ static int smu7_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, disable_mclk_switching_for_display = ((1 < hwmgr->display_config->num_display) && !hwmgr->display_config->multi_monitor_in_sync) || - smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time); + (hwmgr->display_config->num_display && + smu7_vblank_too_short(hwmgr, hwmgr->display_config->min_vblank_time)); disable_mclk_switching = disable_mclk_switching_for_frame_lock || disable_mclk_switching_for_display; From 5e61b84f9d3ddfba73091f9fbc940caae1c9eb22 Mon Sep 17 00:00:00 2001 From: Nirmoy Das Date: Fri, 26 Mar 2021 16:08:10 +0100 Subject: [PATCH 0478/1091] drm/amdgpu: fix offset calculation in amdgpu_vm_bo_clear_mappings() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Offset calculation wasn't correct as start addresses are in pfn not in bytes. CC: stable@vger.kernel.org Signed-off-by: Nirmoy Das Reviewed-by: Christian König Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index ad91c0c3c423..10de2cf344d5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2409,7 +2409,7 @@ int amdgpu_vm_bo_clear_mappings(struct amdgpu_device *adev, after->start = eaddr + 1; after->last = tmp->last; after->offset = tmp->offset; - after->offset += after->start - tmp->start; + after->offset += (after->start - tmp->start) << PAGE_SHIFT; after->flags = tmp->flags; after->bo_va = tmp->bo_va; list_add(&after->list, &tmp->bo_va->invalids); From 7b9acbb6aad4f54623dcd4bd4b1a60fe0c727b09 Mon Sep 17 00:00:00 2001 From: Max Filippov Date: Sun, 7 Feb 2021 04:57:58 -0800 Subject: [PATCH 0479/1091] xtensa: fix uaccess-related livelock in do_page_fault If a uaccess (e.g. get_user()) triggers a fault and there's a fault signal pending, the handler will return to the uaccess without having performed a uaccess fault fixup, and so the CPU will immediately execute the uaccess instruction again, whereupon it will livelock bouncing between that instruction and the fault handler. https://lore.kernel.org/lkml/20210121123140.GD48431@C02TD0UTHF1T.local/ Cc: stable@vger.kernel.org Reported-by: Mark Rutland Signed-off-by: Max Filippov --- arch/xtensa/mm/fault.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/arch/xtensa/mm/fault.c b/arch/xtensa/mm/fault.c index 7666408ce12a..95a74890c7e9 100644 --- a/arch/xtensa/mm/fault.c +++ b/arch/xtensa/mm/fault.c @@ -112,8 +112,11 @@ good_area: */ fault = handle_mm_fault(vma, address, flags, regs); - if (fault_signal_pending(fault, regs)) + if (fault_signal_pending(fault, regs)) { + if (!user_mode(regs)) + goto bad_page_fault; return; + } if (unlikely(fault & VM_FAULT_ERROR)) { if (fault & VM_FAULT_OOM) From 2867b9746cef78745c594894aece6f8ef826e0b4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Sun, 14 Mar 2021 12:07:09 +0100 Subject: [PATCH 0480/1091] clk: socfpga: fix iomem pointer cast on 64-bit MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pointers should be cast with uintptr_t instead of integer. This fixes warning when compile testing on ARM64: drivers/clk/socfpga/clk-gate.c: In function ‘socfpga_clk_recalc_rate’: drivers/clk/socfpga/clk-gate.c:102:7: warning: cast from pointer to integer of different size [-Wpointer-to-int-cast] Fixes: b7cec13f082f ("clk: socfpga: Look for the GPIO_DB_CLK by its offset") Signed-off-by: Krzysztof Kozlowski Acked-by: Dinh Nguyen Link: https://lore.kernel.org/r/20210314110709.32599-1-krzysztof.kozlowski@canonical.com Signed-off-by: Stephen Boyd --- drivers/clk/socfpga/clk-gate.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/socfpga/clk-gate.c b/drivers/clk/socfpga/clk-gate.c index 43ecd507bf83..cf94a12459ea 100644 --- a/drivers/clk/socfpga/clk-gate.c +++ b/drivers/clk/socfpga/clk-gate.c @@ -99,7 +99,7 @@ static unsigned long socfpga_clk_recalc_rate(struct clk_hw *hwclk, val = readl(socfpgaclk->div_reg) >> socfpgaclk->shift; val &= GENMASK(socfpgaclk->width - 1, 0); /* Check for GPIO_DB_CLK by its offset */ - if ((int) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) + if ((uintptr_t) socfpgaclk->div_reg & SOCFPGA_GPIO_DB_CLK_OFFSET) div = val + 1; else div = (1 << val); From 66167c310deb4ac1725f81004fb4b504676ad0bf Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 29 Mar 2021 11:29:23 +0300 Subject: [PATCH 0481/1091] mlxsw: spectrum: Fix ECN marking in tunnel decapsulation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cited commit changed the behavior of the software data path with regards to the ECN marking of decapsulated packets. However, the commit did not change other callers of __INET_ECN_decapsulate(), namely mlxsw. The driver is using the function in order to ensure that the hardware and software data paths act the same with regards to the ECN marking of decapsulated packets. The discrepancy was uncovered by commit 5aa3c334a449 ("selftests: forwarding: vxlan_bridge_1d: Fix vxlan ecn decapsulate value") that aligned the selftest to the new behavior. Without this patch the selftest passes when used with veth pairs, but fails when used with mlxsw netdevs. Fix this by instructing the device to propagate the ECT(1) mark from the outer header to the inner header when the inner header is ECT(0), for both NVE and IP-in-IP tunnels. A helper is added in order not to duplicate the code between both tunnel types. Fixes: b723748750ec ("tunnel: Propagate ECT(1) when decapsulating as recommended by RFC6040") Signed-off-by: Ido Schimmel Reviewed-by: Petr Machata Acked-by: Toke Høiland-Jørgensen Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.h | 15 +++++++++++++++ .../net/ethernet/mellanox/mlxsw/spectrum_ipip.c | 7 +++---- .../net/ethernet/mellanox/mlxsw/spectrum_nve.c | 7 +++---- 3 files changed, 21 insertions(+), 8 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h index d9d9e1f488f9..ba28ac7e79bc 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.h +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.h @@ -21,6 +21,7 @@ #include #include #include +#include #include "port.h" #include "core.h" @@ -347,6 +348,20 @@ struct mlxsw_sp_port_type_speed_ops { u32 (*ptys_proto_cap_masked_get)(u32 eth_proto_cap); }; +static inline u8 mlxsw_sp_tunnel_ecn_decap(u8 outer_ecn, u8 inner_ecn, + bool *trap_en) +{ + bool set_ce = false; + + *trap_en = !!__INET_ECN_decapsulate(outer_ecn, inner_ecn, &set_ce); + if (set_ce) + return INET_ECN_CE; + else if (outer_ecn == INET_ECN_ECT_1 && inner_ecn == INET_ECN_ECT_0) + return INET_ECN_ECT_1; + else + return inner_ecn; +} + static inline struct net_device * mlxsw_sp_bridge_vxlan_dev_find(struct net_device *br_dev) { diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c index 6ccca39bae84..64a8f838eb53 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ipip.c @@ -335,12 +335,11 @@ static int mlxsw_sp_ipip_ecn_decap_init_one(struct mlxsw_sp *mlxsw_sp, u8 inner_ecn, u8 outer_ecn) { char tidem_pl[MLXSW_REG_TIDEM_LEN]; - bool trap_en, set_ce = false; u8 new_inner_ecn; + bool trap_en; - trap_en = __INET_ECN_decapsulate(outer_ecn, inner_ecn, &set_ce); - new_inner_ecn = set_ce ? INET_ECN_CE : inner_ecn; - + new_inner_ecn = mlxsw_sp_tunnel_ecn_decap(outer_ecn, inner_ecn, + &trap_en); mlxsw_reg_tidem_pack(tidem_pl, outer_ecn, inner_ecn, new_inner_ecn, trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tidem), tidem_pl); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c index e5ec595593f4..9eba8fa684ae 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_nve.c @@ -909,12 +909,11 @@ static int __mlxsw_sp_nve_ecn_decap_init(struct mlxsw_sp *mlxsw_sp, u8 inner_ecn, u8 outer_ecn) { char tndem_pl[MLXSW_REG_TNDEM_LEN]; - bool trap_en, set_ce = false; u8 new_inner_ecn; + bool trap_en; - trap_en = !!__INET_ECN_decapsulate(outer_ecn, inner_ecn, &set_ce); - new_inner_ecn = set_ce ? INET_ECN_CE : inner_ecn; - + new_inner_ecn = mlxsw_sp_tunnel_ecn_decap(outer_ecn, inner_ecn, + &trap_en); mlxsw_reg_tndem_pack(tndem_pl, outer_ecn, inner_ecn, new_inner_ecn, trap_en, trap_en ? MLXSW_TRAP_ID_DECAP_ECN0 : 0); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(tndem), tndem_pl); From 4bfd0de590300d3e3889ee9833bec8cc4059fae6 Mon Sep 17 00:00:00 2001 From: Ido Schimmel Date: Mon, 29 Mar 2021 11:29:27 +0300 Subject: [PATCH 0482/1091] selftests: forwarding: vxlan_bridge_1d: Add more ECN decap test cases Test that all possible combinations of inner and outer ECN bits result in the correct inner ECN marking according to RFC 6040 4.2. Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../selftests/net/forwarding/vxlan_bridge_1d.sh | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh index 0ccb1dda099a..eb307ca37bfa 100755 --- a/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh +++ b/tools/testing/selftests/net/forwarding/vxlan_bridge_1d.sh @@ -657,10 +657,21 @@ test_ecn_decap() { # In accordance with INET_ECN_decapsulate() __test_ecn_decap 00 00 0x00 + __test_ecn_decap 00 01 0x00 + __test_ecn_decap 00 02 0x00 + # 00 03 is tested in test_ecn_decap_error() + __test_ecn_decap 01 00 0x01 __test_ecn_decap 01 01 0x01 - __test_ecn_decap 02 01 0x01 + __test_ecn_decap 01 02 0x01 __test_ecn_decap 01 03 0x03 + __test_ecn_decap 02 00 0x02 + __test_ecn_decap 02 01 0x01 + __test_ecn_decap 02 02 0x02 __test_ecn_decap 02 03 0x03 + __test_ecn_decap 03 00 0x03 + __test_ecn_decap 03 01 0x03 + __test_ecn_decap 03 02 0x03 + __test_ecn_decap 03 03 0x03 test_ecn_decap_error } From 5954846d09e4a210b6c761ab09388cfd41f58342 Mon Sep 17 00:00:00 2001 From: Manivannan Sadhasivam Date: Mon, 29 Mar 2021 16:55:37 +0530 Subject: [PATCH 0483/1091] MAINTAINERS: Add entry for Qualcomm IPC Router (QRTR) driver Add MAINTAINERS entry for Qualcomm IPC Router (QRTR) driver. Signed-off-by: Manivannan Sadhasivam Signed-off-by: David S. Miller --- MAINTAINERS | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/MAINTAINERS b/MAINTAINERS index 8d23b0ec0c90..1cc3976040d5 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -14853,6 +14853,14 @@ L: linux-arm-msm@vger.kernel.org S: Maintained F: drivers/iommu/arm/arm-smmu/qcom_iommu.c +QUALCOMM IPC ROUTER (QRTR) DRIVER +M: Manivannan Sadhasivam +L: linux-arm-msm@vger.kernel.org +S: Maintained +F: include/trace/events/qrtr.h +F: include/uapi/linux/qrtr.h +F: net/qrtr/ + QUALCOMM IPCC MAILBOX DRIVER M: Manivannan Sadhasivam L: linux-arm-msm@vger.kernel.org From 63415767a2446136372e777cde5bb351f21ec21d Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Mon, 29 Mar 2021 05:36:48 -0700 Subject: [PATCH 0484/1091] ethernet: myri10ge: Fix a use after free in myri10ge_sw_tso In myri10ge_sw_tso, the skb_list_walk_safe macro will set (curr) = (segs) and (next) = (curr)->next. If status!=0 is true, the memory pointed by curr and segs will be free by dev_kfree_skb_any(curr). But later, the segs is used by segs = segs->next and causes a uaf. As (next) = (curr)->next, my patch replaces seg->next to next. Fixes: 536577f36ff7a ("net: myri10ge: use skb_list_walk_safe helper for gso segments") Signed-off-by: Lv Yunlong Signed-off-by: David S. Miller --- drivers/net/ethernet/myricom/myri10ge/myri10ge.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c index 1634ca6d4a8f..c84c8bf2bc20 100644 --- a/drivers/net/ethernet/myricom/myri10ge/myri10ge.c +++ b/drivers/net/ethernet/myricom/myri10ge/myri10ge.c @@ -2897,7 +2897,7 @@ static netdev_tx_t myri10ge_sw_tso(struct sk_buff *skb, dev_kfree_skb_any(curr); if (segs != NULL) { curr = segs; - segs = segs->next; + segs = next; curr->next = NULL; dev_kfree_skb_any(segs); } From bff5b62585123823842833ab20b1c0a7fa437f8c Mon Sep 17 00:00:00 2001 From: Claudiu Manoil Date: Mon, 29 Mar 2021 17:08:47 +0300 Subject: [PATCH 0485/1091] gianfar: Handle error code at MAC address change Handle return error code of eth_mac_addr(); Fixes: 3d23a05c75c7 ("gianfar: Enable changing mac addr when if up") Signed-off-by: Claudiu Manoil Signed-off-by: David S. Miller --- drivers/net/ethernet/freescale/gianfar.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index 1cf8ef717453..3ec4d9fddd52 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -363,7 +363,11 @@ static void gfar_set_mac_for_addr(struct net_device *dev, int num, static int gfar_set_mac_addr(struct net_device *dev, void *p) { - eth_mac_addr(dev, p); + int ret; + + ret = eth_mac_addr(dev, p); + if (ret) + return ret; gfar_set_mac_for_addr(dev, 0, dev->dev_addr); From e0146a108ce4d2c22b9510fd12268e3ee72a0161 Mon Sep 17 00:00:00 2001 From: Jason Gunthorpe Date: Mon, 29 Mar 2021 16:00:16 -0300 Subject: [PATCH 0486/1091] vfio/nvlink: Add missing SPAPR_TCE_IOMMU depends Compiling the nvlink stuff relies on the SPAPR_TCE_IOMMU otherwise there are compile errors: drivers/vfio/pci/vfio_pci_nvlink2.c:101:10: error: implicit declaration of function 'mm_iommu_put' [-Werror,-Wimplicit-function-declaration] ret = mm_iommu_put(data->mm, data->mem); As PPC only defines these functions when the config is set. Previously this wasn't a problem by chance as SPAPR_TCE_IOMMU was the only IOMMU that could have satisfied IOMMU_API on POWERNV. Fixes: 179209fa1270 ("vfio: IOMMU_API should be selected") Reported-by: kernel test robot Signed-off-by: Jason Gunthorpe Message-Id: <0-v1-83dba9768fc3+419-vfio_nvlink2_kconfig_jgg@nvidia.com> Signed-off-by: Alex Williamson --- drivers/vfio/pci/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig index ac3c1dd3edef..4abddbebd4b2 100644 --- a/drivers/vfio/pci/Kconfig +++ b/drivers/vfio/pci/Kconfig @@ -42,6 +42,6 @@ config VFIO_PCI_IGD config VFIO_PCI_NVLINK2 def_bool y - depends on VFIO_PCI && PPC_POWERNV + depends on VFIO_PCI && PPC_POWERNV && SPAPR_TCE_IOMMU help VFIO PCI support for P9 Witherspoon machine with NVIDIA V100 GPUs From fb6ec87f7229b92baa81b35cbc76f2626d5bfadb Mon Sep 17 00:00:00 2001 From: Maxim Kochetkov Date: Mon, 29 Mar 2021 18:30:16 +0300 Subject: [PATCH 0487/1091] net: dsa: Fix type was not set for devlink port If PHY is not available on DSA port (described at devicetree but absent or failed to detect) then kernel prints warning after 3700 secs: [ 3707.948771] ------------[ cut here ]------------ [ 3707.948784] Type was not set for devlink port. [ 3707.948894] WARNING: CPU: 1 PID: 17 at net/core/devlink.c:8097 0xc083f9d8 We should unregister the devlink port as a user port and re-register it as an unused port before executing "continue" in case of dsa_port_setup error. Fixes: 86f8b1c01a0a ("net: dsa: Do not make user port errors fatal") Signed-off-by: Maxim Kochetkov Reviewed-by: Vladimir Oltean Signed-off-by: David S. Miller --- net/dsa/dsa2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/net/dsa/dsa2.c b/net/dsa/dsa2.c index d142eb2b288b..3c3e56a1f34d 100644 --- a/net/dsa/dsa2.c +++ b/net/dsa/dsa2.c @@ -795,8 +795,14 @@ static int dsa_tree_setup_switches(struct dsa_switch_tree *dst) list_for_each_entry(dp, &dst->ports, list) { err = dsa_port_setup(dp); - if (err) + if (err) { + dsa_port_devlink_teardown(dp); + dp->type = DSA_PORT_TYPE_UNUSED; + err = dsa_port_devlink_setup(dp); + if (err) + goto teardown; continue; + } } return 0; From e5c359f70e4b5e7b6c2bf4b0ca2d2686d543a37b Mon Sep 17 00:00:00 2001 From: Taniya Das Date: Sat, 27 Mar 2021 07:11:05 +0530 Subject: [PATCH 0488/1091] clk: qcom: camcc: Update the clock ops for the SC7180 Some of the RCGs could be always ON from the XO source and could be used as the clock on signal for the GDSC to be operational. In the cases where the GDSCs are parked at different source with the source clock disabled, it could lead to the GDSC to be stuck at ON/OFF during gdsc disable/enable. Thus park the RCGs at XO during clock disable and update the rcg_ops to use the shared_ops. Fixes: 15d09e830bbc ("clk: qcom: camcc: Add camera clock controller driver for SC7180") Signed-off-by: Taniya Das Link: https://lore.kernel.org/r/1616809265-11912-1-git-send-email-tdas@codeaurora.org Signed-off-by: Stephen Boyd --- drivers/clk/qcom/camcc-sc7180.c | 50 ++++++++++++++++----------------- 1 file changed, 25 insertions(+), 25 deletions(-) diff --git a/drivers/clk/qcom/camcc-sc7180.c b/drivers/clk/qcom/camcc-sc7180.c index dbac5651ab85..9bcf2f8ed4de 100644 --- a/drivers/clk/qcom/camcc-sc7180.c +++ b/drivers/clk/qcom/camcc-sc7180.c @@ -304,7 +304,7 @@ static struct clk_rcg2 cam_cc_bps_clk_src = { .name = "cam_cc_bps_clk_src", .parent_data = cam_cc_parent_data_2, .num_parents = 5, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -325,7 +325,7 @@ static struct clk_rcg2 cam_cc_cci_0_clk_src = { .name = "cam_cc_cci_0_clk_src", .parent_data = cam_cc_parent_data_5, .num_parents = 3, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -339,7 +339,7 @@ static struct clk_rcg2 cam_cc_cci_1_clk_src = { .name = "cam_cc_cci_1_clk_src", .parent_data = cam_cc_parent_data_5, .num_parents = 3, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -360,7 +360,7 @@ static struct clk_rcg2 cam_cc_cphy_rx_clk_src = { .name = "cam_cc_cphy_rx_clk_src", .parent_data = cam_cc_parent_data_3, .num_parents = 6, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -379,7 +379,7 @@ static struct clk_rcg2 cam_cc_csi0phytimer_clk_src = { .name = "cam_cc_csi0phytimer_clk_src", .parent_data = cam_cc_parent_data_0, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -393,7 +393,7 @@ static struct clk_rcg2 cam_cc_csi1phytimer_clk_src = { .name = "cam_cc_csi1phytimer_clk_src", .parent_data = cam_cc_parent_data_0, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -407,7 +407,7 @@ static struct clk_rcg2 cam_cc_csi2phytimer_clk_src = { .name = "cam_cc_csi2phytimer_clk_src", .parent_data = cam_cc_parent_data_0, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -421,7 +421,7 @@ static struct clk_rcg2 cam_cc_csi3phytimer_clk_src = { .name = "cam_cc_csi3phytimer_clk_src", .parent_data = cam_cc_parent_data_0, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -443,7 +443,7 @@ static struct clk_rcg2 cam_cc_fast_ahb_clk_src = { .name = "cam_cc_fast_ahb_clk_src", .parent_data = cam_cc_parent_data_0, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -466,7 +466,7 @@ static struct clk_rcg2 cam_cc_icp_clk_src = { .name = "cam_cc_icp_clk_src", .parent_data = cam_cc_parent_data_2, .num_parents = 5, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -488,7 +488,7 @@ static struct clk_rcg2 cam_cc_ife_0_clk_src = { .name = "cam_cc_ife_0_clk_src", .parent_data = cam_cc_parent_data_4, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -510,7 +510,7 @@ static struct clk_rcg2 cam_cc_ife_0_csid_clk_src = { .name = "cam_cc_ife_0_csid_clk_src", .parent_data = cam_cc_parent_data_3, .num_parents = 6, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -524,7 +524,7 @@ static struct clk_rcg2 cam_cc_ife_1_clk_src = { .name = "cam_cc_ife_1_clk_src", .parent_data = cam_cc_parent_data_4, .num_parents = 4, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -538,7 +538,7 @@ static struct clk_rcg2 cam_cc_ife_1_csid_clk_src = { .name = "cam_cc_ife_1_csid_clk_src", .parent_data = cam_cc_parent_data_3, .num_parents = 6, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -553,7 +553,7 @@ static struct clk_rcg2 cam_cc_ife_lite_clk_src = { .parent_data = cam_cc_parent_data_4, .num_parents = 4, .flags = CLK_SET_RATE_PARENT, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -567,7 +567,7 @@ static struct clk_rcg2 cam_cc_ife_lite_csid_clk_src = { .name = "cam_cc_ife_lite_csid_clk_src", .parent_data = cam_cc_parent_data_3, .num_parents = 6, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -590,7 +590,7 @@ static struct clk_rcg2 cam_cc_ipe_0_clk_src = { .name = "cam_cc_ipe_0_clk_src", .parent_data = cam_cc_parent_data_2, .num_parents = 5, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -613,7 +613,7 @@ static struct clk_rcg2 cam_cc_jpeg_clk_src = { .name = "cam_cc_jpeg_clk_src", .parent_data = cam_cc_parent_data_2, .num_parents = 5, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -635,7 +635,7 @@ static struct clk_rcg2 cam_cc_lrme_clk_src = { .name = "cam_cc_lrme_clk_src", .parent_data = cam_cc_parent_data_6, .num_parents = 5, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -656,7 +656,7 @@ static struct clk_rcg2 cam_cc_mclk0_clk_src = { .name = "cam_cc_mclk0_clk_src", .parent_data = cam_cc_parent_data_1, .num_parents = 3, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -670,7 +670,7 @@ static struct clk_rcg2 cam_cc_mclk1_clk_src = { .name = "cam_cc_mclk1_clk_src", .parent_data = cam_cc_parent_data_1, .num_parents = 3, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -684,7 +684,7 @@ static struct clk_rcg2 cam_cc_mclk2_clk_src = { .name = "cam_cc_mclk2_clk_src", .parent_data = cam_cc_parent_data_1, .num_parents = 3, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -698,7 +698,7 @@ static struct clk_rcg2 cam_cc_mclk3_clk_src = { .name = "cam_cc_mclk3_clk_src", .parent_data = cam_cc_parent_data_1, .num_parents = 3, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -712,7 +712,7 @@ static struct clk_rcg2 cam_cc_mclk4_clk_src = { .name = "cam_cc_mclk4_clk_src", .parent_data = cam_cc_parent_data_1, .num_parents = 3, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; @@ -732,7 +732,7 @@ static struct clk_rcg2 cam_cc_slow_ahb_clk_src = { .parent_data = cam_cc_parent_data_0, .num_parents = 4, .flags = CLK_SET_RATE_PARENT | CLK_OPS_PARENT_ENABLE, - .ops = &clk_rcg2_ops, + .ops = &clk_rcg2_shared_ops, }, }; From 1bfb3dea965ff9f6226fd1709338f227363b6061 Mon Sep 17 00:00:00 2001 From: Rahul Lakkireddy Date: Sat, 27 Mar 2021 23:49:08 +0530 Subject: [PATCH 0489/1091] cxgb4: avoid collecting SGE_QBASE regs during traffic Accessing SGE_QBASE_MAP[0-3] and SGE_QBASE_INDEX registers can lead to SGE missing doorbells under heavy traffic. So, only collect them when adapter is idle. Also update the regdump range to skip collecting these registers. Fixes: 80a95a80d358 ("cxgb4: collect SGE PF/VF queue map") Signed-off-by: Rahul Lakkireddy Signed-off-by: David S. Miller --- .../net/ethernet/chelsio/cxgb4/cudbg_lib.c | 23 +++++++++++++++---- drivers/net/ethernet/chelsio/cxgb4/t4_hw.c | 3 ++- 2 files changed, 21 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c index 6c85a10f465c..23a2ebdfd503 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cudbg_lib.c @@ -1794,11 +1794,25 @@ int cudbg_collect_sge_indirect(struct cudbg_init *pdbg_init, struct cudbg_buffer temp_buff = { 0 }; struct sge_qbase_reg_field *sge_qbase; struct ireg_buf *ch_sge_dbg; + u8 padap_running = 0; int i, rc; + u32 size; - rc = cudbg_get_buff(pdbg_init, dbg_buff, - sizeof(*ch_sge_dbg) * 2 + sizeof(*sge_qbase), - &temp_buff); + /* Accessing SGE_QBASE_MAP[0-3] and SGE_QBASE_INDEX regs can + * lead to SGE missing doorbells under heavy traffic. So, only + * collect them when adapter is idle. + */ + for_each_port(padap, i) { + padap_running = netif_running(padap->port[i]); + if (padap_running) + break; + } + + size = sizeof(*ch_sge_dbg) * 2; + if (!padap_running) + size += sizeof(*sge_qbase); + + rc = cudbg_get_buff(pdbg_init, dbg_buff, size, &temp_buff); if (rc) return rc; @@ -1820,7 +1834,8 @@ int cudbg_collect_sge_indirect(struct cudbg_init *pdbg_init, ch_sge_dbg++; } - if (CHELSIO_CHIP_VERSION(padap->params.chip) > CHELSIO_T5) { + if (CHELSIO_CHIP_VERSION(padap->params.chip) > CHELSIO_T5 && + !padap_running) { sge_qbase = (struct sge_qbase_reg_field *)ch_sge_dbg; /* 1 addr reg SGE_QBASE_INDEX and 4 data reg * SGE_QBASE_MAP[0-3] diff --git a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c index 98829e482bfa..80882cfc370f 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c +++ b/drivers/net/ethernet/chelsio/cxgb4/t4_hw.c @@ -2090,7 +2090,8 @@ void t4_get_regs(struct adapter *adap, void *buf, size_t buf_size) 0x1190, 0x1194, 0x11a0, 0x11a4, 0x11b0, 0x11b4, - 0x11fc, 0x1274, + 0x11fc, 0x123c, + 0x1254, 0x1274, 0x1280, 0x133c, 0x1800, 0x18fc, 0x3000, 0x302c, From 6bf24dc0cc0cc43b29ba344b66d78590e687e046 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Sun, 28 Mar 2021 00:30:29 -0700 Subject: [PATCH 0490/1091] net:tipc: Fix a double free in tipc_sk_mcast_rcv In the if(skb_peek(arrvq) == skb) branch, it calls __skb_dequeue(arrvq) to get the skb by skb = skb_peek(arrvq). Then __skb_dequeue() unlinks the skb from arrvq and returns the skb which equals to skb_peek(arrvq). After __skb_dequeue(arrvq) finished, the skb is freed by kfree_skb(__skb_dequeue(arrvq)) in the first time. Unfortunately, the same skb is freed in the second time by kfree_skb(skb) after the branch completed. My patch removes kfree_skb() in the if(skb_peek(arrvq) == skb) branch, because this skb will be freed by kfree_skb(skb) finally. Fixes: cb1b728096f54 ("tipc: eliminate race condition at multicast reception") Signed-off-by: Lv Yunlong Signed-off-by: David S. Miller --- net/tipc/socket.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/tipc/socket.c b/net/tipc/socket.c index cebcc104dc70..022999e0202d 100644 --- a/net/tipc/socket.c +++ b/net/tipc/socket.c @@ -1265,7 +1265,7 @@ void tipc_sk_mcast_rcv(struct net *net, struct sk_buff_head *arrvq, spin_lock_bh(&inputq->lock); if (skb_peek(arrvq) == skb) { skb_queue_splice_tail_init(&tmpq, inputq); - kfree_skb(__skb_dequeue(arrvq)); + __skb_dequeue(arrvq); } spin_unlock_bh(&inputq->lock); __skb_queue_purge(&tmpq); From af9d316f3dd6d1385fbd1631b5103e620fc4298a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 29 Mar 2021 16:03:17 +0200 Subject: [PATCH 0491/1091] dt-bindings: net: ethernet-controller: fix typo in NVMEM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The correct property name is "nvmem-cell-names". This is what: 1. Was originally documented in the ethernet.txt 2. Is used in DTS files 3. Matches standard syntax for phandles 4. Linux net subsystem checks for Fixes: 9d3de3c58347 ("dt-bindings: net: Add YAML schemas for the generic Ethernet options") Signed-off-by: Rafał Miłecki Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/ethernet-controller.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/ethernet-controller.yaml b/Documentation/devicetree/bindings/net/ethernet-controller.yaml index 4b7d1e5d003c..e8f04687a3e0 100644 --- a/Documentation/devicetree/bindings/net/ethernet-controller.yaml +++ b/Documentation/devicetree/bindings/net/ethernet-controller.yaml @@ -49,7 +49,7 @@ properties: description: Reference to an nvmem node for the MAC address - nvmem-cells-names: + nvmem-cell-names: const: mac-address phy-connection-type: From 4cd7bd599e273bb75804a406b50cd2c58c40e2e0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= Date: Mon, 29 Mar 2021 17:33:28 +0200 Subject: [PATCH 0492/1091] dt-bindings: net: bcm4908-enet: fix Ethernet generic properties MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This binding file uses $ref: ethernet-controller.yaml# so it's required to use "unevaluatedProperties" (instead of "additionalProperties") to make Ethernet properties validate. Fixes: f08b5cf1eb1f ("dt-bindings: net: bcm4908-enet: include ethernet-controller.yaml") Signed-off-by: Rafał Miłecki Signed-off-by: David S. Miller --- Documentation/devicetree/bindings/net/brcm,bcm4908-enet.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/net/brcm,bcm4908-enet.yaml b/Documentation/devicetree/bindings/net/brcm,bcm4908-enet.yaml index 79c38ea14237..13c26f23a820 100644 --- a/Documentation/devicetree/bindings/net/brcm,bcm4908-enet.yaml +++ b/Documentation/devicetree/bindings/net/brcm,bcm4908-enet.yaml @@ -32,7 +32,7 @@ required: - interrupts - interrupt-names -additionalProperties: false +unevaluatedProperties: false examples: - | From 6e5a03bcba44e080a6bf300194a68ce9bb1e5184 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Mon, 29 Mar 2021 04:50:02 -0700 Subject: [PATCH 0493/1091] ethernet/netronome/nfp: Fix a use after free in nfp_bpf_ctrl_msg_rx In nfp_bpf_ctrl_msg_rx, if nfp_ccm_get_type(skb) == NFP_CCM_TYPE_BPF_BPF_EVENT is true, the skb will be freed. But the skb is still used by nfp_ccm_rx(&bpf->ccm, skb). My patch adds a return when the skb was freed. Fixes: bcf0cafab44fd ("nfp: split out common control message handling code") Signed-off-by: Lv Yunlong Reviewed-by: Jakub Kicinski Signed-off-by: David S. Miller --- drivers/net/ethernet/netronome/nfp/bpf/cmsg.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c b/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c index 0e2db6ea79e9..2ec62c8d86e1 100644 --- a/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c +++ b/drivers/net/ethernet/netronome/nfp/bpf/cmsg.c @@ -454,6 +454,7 @@ void nfp_bpf_ctrl_msg_rx(struct nfp_app *app, struct sk_buff *skb) dev_consume_skb_any(skb); else dev_kfree_skb_any(skb); + return; } nfp_ccm_rx(&bpf->ccm, skb); From 9e67600ed6b8565da4b85698ec659b5879a6c1c6 Mon Sep 17 00:00:00 2001 From: Gulam Mohamed Date: Thu, 25 Mar 2021 09:32:48 +0000 Subject: [PATCH 0494/1091] scsi: iscsi: Fix race condition between login and sync thread A kernel panic was observed due to a timing issue between the sync thread and the initiator processing a login response from the target. The session reopen can be invoked both from the session sync thread when iscsid restarts and from iscsid through the error handler. Before the initiator receives the response to a login, another reopen request can be sent from the error handler/sync session. When the initial login response is subsequently processed, the connection has been closed and the socket has been released. To fix this a new connection state, ISCSI_CONN_BOUND, is added: - Set the connection state value to ISCSI_CONN_DOWN upon iscsi_if_ep_disconnect() and iscsi_if_stop_conn() - Set the connection state to the newly created value ISCSI_CONN_BOUND after bind connection (transport->bind_conn()) - In iscsi_set_param(), return -ENOTCONN if the connection state is not either ISCSI_CONN_BOUND or ISCSI_CONN_UP Link: https://lore.kernel.org/r/20210325093248.284678-1-gulam.mohamed@oracle.com Reviewed-by: Mike Christie Signed-off-by: Gulam Mohamed Signed-off-by: Martin K. Petersen index 91074fd97f64..f4bf62b007a0 100644 --- drivers/scsi/scsi_transport_iscsi.c | 14 +++++++++++++- include/scsi/scsi_transport_iscsi.h | 1 + 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index 969d24d580e2..bebfb355abdf 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2471,6 +2471,7 @@ static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag) */ mutex_lock(&conn_mutex); conn->transport->stop_conn(conn, flag); + conn->state = ISCSI_CONN_DOWN; mutex_unlock(&conn_mutex); } @@ -2894,6 +2895,13 @@ iscsi_set_param(struct iscsi_transport *transport, struct iscsi_uevent *ev) default: err = transport->set_param(conn, ev->u.set_param.param, data, ev->u.set_param.len); + if ((conn->state == ISCSI_CONN_BOUND) || + (conn->state == ISCSI_CONN_UP)) { + err = transport->set_param(conn, ev->u.set_param.param, + data, ev->u.set_param.len); + } else { + return -ENOTCONN; + } } return err; @@ -2953,6 +2961,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport, mutex_lock(&conn->ep_mutex); conn->ep = NULL; mutex_unlock(&conn->ep_mutex); + conn->state = ISCSI_CONN_DOWN; } transport->ep_disconnect(ep); @@ -3713,6 +3722,8 @@ iscsi_if_recv_msg(struct sk_buff *skb, struct nlmsghdr *nlh, uint32_t *group) ev->r.retcode = transport->bind_conn(session, conn, ev->u.b_conn.transport_eph, ev->u.b_conn.is_leading); + if (!ev->r.retcode) + conn->state = ISCSI_CONN_BOUND; mutex_unlock(&conn_mutex); if (ev->r.retcode || !transport->ep_connect) @@ -3944,7 +3955,8 @@ iscsi_conn_attr(local_ipaddr, ISCSI_PARAM_LOCAL_IPADDR); static const char *const connection_state_names[] = { [ISCSI_CONN_UP] = "up", [ISCSI_CONN_DOWN] = "down", - [ISCSI_CONN_FAILED] = "failed" + [ISCSI_CONN_FAILED] = "failed", + [ISCSI_CONN_BOUND] = "bound" }; static ssize_t show_conn_state(struct device *dev, diff --git a/include/scsi/scsi_transport_iscsi.h b/include/scsi/scsi_transport_iscsi.h index 8a26a2ffa952..fc5a39839b4b 100644 --- a/include/scsi/scsi_transport_iscsi.h +++ b/include/scsi/scsi_transport_iscsi.h @@ -193,6 +193,7 @@ enum iscsi_connection_state { ISCSI_CONN_UP = 0, ISCSI_CONN_DOWN, ISCSI_CONN_FAILED, + ISCSI_CONN_BOUND, }; struct iscsi_cls_conn { From ef19e111337f6c3dca7019a8bad5fbc6fb18d635 Mon Sep 17 00:00:00 2001 From: Dmitry Safonov Date: Tue, 30 Mar 2021 00:25:06 +0100 Subject: [PATCH 0495/1091] xfrm/compat: Cleanup WARN()s that can be user-triggered Replace WARN_ONCE() that can be triggered from userspace with pr_warn_once(). Those still give user a hint what's the issue. I've left WARN()s that are not possible to trigger with current code-base and that would mean that the code has issues: - relying on current compat_msg_min[type] <= xfrm_msg_min[type] - expected 4-byte padding size difference between compat_msg_min[type] and xfrm_msg_min[type] - compat_policy[type].len <= xfrma_policy[type].len (for every type) Reported-by: syzbot+834ffd1afc7212eb8147@syzkaller.appspotmail.com Fixes: 5f3eea6b7e8f ("xfrm/compat: Attach xfrm dumps to 64=>32 bit translator") Cc: "David S. Miller" Cc: Eric Dumazet Cc: Herbert Xu Cc: Jakub Kicinski Cc: Steffen Klassert Cc: netdev@vger.kernel.org Cc: stable@vger.kernel.org Signed-off-by: Dmitry Safonov Signed-off-by: Steffen Klassert --- net/xfrm/xfrm_compat.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/net/xfrm/xfrm_compat.c b/net/xfrm/xfrm_compat.c index d8e8a11ca845..a20aec9d7393 100644 --- a/net/xfrm/xfrm_compat.c +++ b/net/xfrm/xfrm_compat.c @@ -216,7 +216,7 @@ static struct nlmsghdr *xfrm_nlmsg_put_compat(struct sk_buff *skb, case XFRM_MSG_GETSADINFO: case XFRM_MSG_GETSPDINFO: default: - WARN_ONCE(1, "unsupported nlmsg_type %d", nlh_src->nlmsg_type); + pr_warn_once("unsupported nlmsg_type %d\n", nlh_src->nlmsg_type); return ERR_PTR(-EOPNOTSUPP); } @@ -277,7 +277,7 @@ static int xfrm_xlate64_attr(struct sk_buff *dst, const struct nlattr *src) return xfrm_nla_cpy(dst, src, nla_len(src)); default: BUILD_BUG_ON(XFRMA_MAX != XFRMA_IF_ID); - WARN_ONCE(1, "unsupported nla_type %d", src->nla_type); + pr_warn_once("unsupported nla_type %d\n", src->nla_type); return -EOPNOTSUPP; } } @@ -315,8 +315,10 @@ static int xfrm_alloc_compat(struct sk_buff *skb, const struct nlmsghdr *nlh_src struct sk_buff *new = NULL; int err; - if (WARN_ON_ONCE(type >= ARRAY_SIZE(xfrm_msg_min))) + if (type >= ARRAY_SIZE(xfrm_msg_min)) { + pr_warn_once("unsupported nlmsg_type %d\n", nlh_src->nlmsg_type); return -EOPNOTSUPP; + } if (skb_shinfo(skb)->frag_list == NULL) { new = alloc_skb(skb->len + skb_tailroom(skb), GFP_ATOMIC); @@ -378,6 +380,10 @@ static int xfrm_attr_cpy32(void *dst, size_t *pos, const struct nlattr *src, struct nlmsghdr *nlmsg = dst; struct nlattr *nla; + /* xfrm_user_rcv_msg_compat() relies on fact that 32-bit messages + * have the same len or shorted than 64-bit ones. + * 32-bit translation that is bigger than 64-bit original is unexpected. + */ if (WARN_ON_ONCE(copy_len > payload)) copy_len = payload; From f57011e72f5fe0421ec7a812beb1b57bdf4bb47f Mon Sep 17 00:00:00 2001 From: Stefan Riedmueller Date: Mon, 29 Mar 2021 15:01:03 +0200 Subject: [PATCH 0496/1091] ARM: dts: imx6: pbab01: Set vmmc supply for both SD interfaces Setting the vmmc supplies is crucial since otherwise the supplying regulators get disabled and the SD interfaces are no longer powered which leads to system failures if the system is booted from that SD interface. Fixes: 1e44d3f880d5 ("ARM i.MX6Q: dts: Enable I2C1 with EEPROM and PMIC on Phytec phyFLEX-i.MX6 Ouad module") Signed-off-by: Stefan Riedmueller Reviewed-by: Fabio Estevam Signed-off-by: Shawn Guo --- arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi index 7a1e53195785..f28a96fcf23e 100644 --- a/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi +++ b/arch/arm/boot/dts/imx6qdl-phytec-pfla02.dtsi @@ -433,6 +433,7 @@ pinctrl-0 = <&pinctrl_usdhc2>; cd-gpios = <&gpio1 4 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio1 2 GPIO_ACTIVE_HIGH>; + vmmc-supply = <&vdd_sd1_reg>; status = "disabled"; }; @@ -442,5 +443,6 @@ &pinctrl_usdhc3_cdwp>; cd-gpios = <&gpio1 27 GPIO_ACTIVE_LOW>; wp-gpios = <&gpio1 29 GPIO_ACTIVE_HIGH>; + vmmc-supply = <&vdd_sd0_reg>; status = "disabled"; }; From bec4d7c93afc07dd0454ae41c559513f858cfb83 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 29 Mar 2021 09:07:18 +0300 Subject: [PATCH 0497/1091] thunderbolt: Fix a leak in tb_retimer_add() After the device_register() succeeds, then the correct way to clean up is to call device_unregister(). The unregister calls both device_del() and device_put(). Since this code was only device_del() it results in a memory leak. Fixes: dacb12877d92 ("thunderbolt: Add support for on-board retimers") Cc: stable@vger.kernel.org Signed-off-by: Dan Carpenter Reviewed-by: Jason Gunthorpe Signed-off-by: Mika Westerberg --- drivers/thunderbolt/retimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index 620bcf586ee2..7a5d61604c8b 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c @@ -347,7 +347,7 @@ static int tb_retimer_add(struct tb_port *port, u8 index, u32 auth_status) ret = tb_retimer_nvm_add(rt); if (ret) { dev_err(&rt->dev, "failed to add NVM devices: %d\n", ret); - device_del(&rt->dev); + device_unregister(&rt->dev); return ret; } From 08fe7ae1857080f5075df5ac7fef2ecd4e289117 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Mon, 29 Mar 2021 09:08:01 +0300 Subject: [PATCH 0498/1091] thunderbolt: Fix off by one in tb_port_find_retimer() This array uses 1-based indexing so it corrupts memory one element beyond of the array. Fix it by making the array one element larger. Fixes: dacb12877d92 ("thunderbolt: Add support for on-board retimers") Cc: stable@vger.kernel.org Signed-off-by: Dan Carpenter Signed-off-by: Mika Westerberg --- drivers/thunderbolt/retimer.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/thunderbolt/retimer.c b/drivers/thunderbolt/retimer.c index 7a5d61604c8b..c44fad2b9fbb 100644 --- a/drivers/thunderbolt/retimer.c +++ b/drivers/thunderbolt/retimer.c @@ -406,7 +406,7 @@ static struct tb_retimer *tb_port_find_retimer(struct tb_port *port, u8 index) */ int tb_retimer_scan(struct tb_port *port) { - u32 status[TB_MAX_RETIMER_INDEX] = {}; + u32 status[TB_MAX_RETIMER_INDEX + 1] = {}; int ret, i, last_idx = 0; if (!port->cap_usb4) From f556de6087f0d19825ffcdddc4816f83ddfd35e3 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Tue, 30 Mar 2021 09:47:10 +0100 Subject: [PATCH 0499/1091] ASoC: mediatek: mt6359: Fix spelling mistake "reate" -> "create" There is a spelling mistake in a dev_err error message. Fix it. Signed-off-by: Colin Ian King Link: https://lore.kernel.org/r/20210330084710.997731-1-colin.king@canonical.com Signed-off-by: Mark Brown --- sound/soc/codecs/mt6359-accdet.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/mt6359-accdet.c b/sound/soc/codecs/mt6359-accdet.c index 0bef6eaad5ad..4222aed013f1 100644 --- a/sound/soc/codecs/mt6359-accdet.c +++ b/sound/soc/codecs/mt6359-accdet.c @@ -1019,7 +1019,7 @@ static int mt6359_accdet_probe(struct platform_device *pdev) priv->jd_workqueue = create_singlethread_workqueue("mt6359_accdet_jd"); INIT_WORK(&priv->jd_work, mt6359_accdet_jd_work); if (!priv->jd_workqueue) { - dev_err(&pdev->dev, "Failed to reate jack detect workqueue\n"); + dev_err(&pdev->dev, "Failed to create jack detect workqueue\n"); ret = -1; goto err_eint_wq; } From c7721e94279887f9dd8f4be303f2054bb5477c9e Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Fri, 26 Mar 2021 19:21:29 +0800 Subject: [PATCH 0500/1091] ASoC: Intel: add max98390 echo reference support load new topology file with speaker capture pipeline. Signed-off-by: Mac Chiang Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/1616757689-22014-1-git-send-email-mac.chiang@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-cml-match.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-cml-match.c b/sound/soc/intel/common/soc-acpi-intel-cml-match.c index 2161b3b85b4a..7f6ef8229969 100644 --- a/sound/soc/intel/common/soc-acpi-intel-cml-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-cml-match.c @@ -79,7 +79,7 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_cml_machines[] = { .machine_quirk = snd_soc_acpi_codec_list, .quirk_data = &max98390_spk_codecs, .sof_fw_filename = "sof-cml.ri", - .sof_tplg_filename = "sof-cml-da7219-max98357a.tplg", + .sof_tplg_filename = "sof-cml-da7219-max98390.tplg", }, {}, }; From 96fadf7e8ff49fdb74754801228942b67c3eeebd Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Sat, 27 Mar 2021 12:28:57 +0300 Subject: [PATCH 0501/1091] ASoC: q6afe-clocks: fix reprobing of the driver Q6afe-clocks driver can get reprobed. For example if the APR services are restarted after the firmware crash. However currently Q6afe-clocks driver will oops because hw.init will get cleared during first _probe call. Rewrite the driver to fill the clock data at runtime rather than using big static array of clocks. Signed-off-by: Dmitry Baryshkov Reviewed-by: Srinivas Kandagatla Reviewed-by: Stephen Boyd Fixes: 520a1c396d19 ("ASoC: q6afe-clocks: add q6afe clock controller") Link: https://lore.kernel.org/r/20210327092857.3073879-1-dmitry.baryshkov@linaro.org Signed-off-by: Mark Brown --- sound/soc/qcom/qdsp6/q6afe-clocks.c | 209 ++++++++++++++-------------- sound/soc/qcom/qdsp6/q6afe.c | 2 +- sound/soc/qcom/qdsp6/q6afe.h | 2 +- 3 files changed, 108 insertions(+), 105 deletions(-) diff --git a/sound/soc/qcom/qdsp6/q6afe-clocks.c b/sound/soc/qcom/qdsp6/q6afe-clocks.c index f0362f061652..9431656283cd 100644 --- a/sound/soc/qcom/qdsp6/q6afe-clocks.c +++ b/sound/soc/qcom/qdsp6/q6afe-clocks.c @@ -11,33 +11,29 @@ #include #include "q6afe.h" -#define Q6AFE_CLK(id) &(struct q6afe_clk) { \ +#define Q6AFE_CLK(id) { \ .clk_id = id, \ .afe_clk_id = Q6AFE_##id, \ .name = #id, \ - .attributes = LPASS_CLK_ATTRIBUTE_COUPLE_NO, \ .rate = 19200000, \ - .hw.init = &(struct clk_init_data) { \ - .ops = &clk_q6afe_ops, \ - .name = #id, \ - }, \ } -#define Q6AFE_VOTE_CLK(id, blkid, n) &(struct q6afe_clk) { \ +#define Q6AFE_VOTE_CLK(id, blkid, n) { \ .clk_id = id, \ .afe_clk_id = blkid, \ - .name = #n, \ - .hw.init = &(struct clk_init_data) { \ - .ops = &clk_vote_q6afe_ops, \ - .name = #id, \ - }, \ + .name = n, \ } -struct q6afe_clk { - struct device *dev; +struct q6afe_clk_init { int clk_id; int afe_clk_id; char *name; + int rate; +}; + +struct q6afe_clk { + struct device *dev; + int afe_clk_id; int attributes; int rate; uint32_t handle; @@ -48,8 +44,7 @@ struct q6afe_clk { struct q6afe_cc { struct device *dev; - struct q6afe_clk **clks; - int num_clks; + struct q6afe_clk *clks[Q6AFE_MAX_CLK_ID]; }; static int clk_q6afe_prepare(struct clk_hw *hw) @@ -105,7 +100,7 @@ static int clk_vote_q6afe_block(struct clk_hw *hw) struct q6afe_clk *clk = to_q6afe_clk(hw); return q6afe_vote_lpass_core_hw(clk->dev, clk->afe_clk_id, - clk->name, &clk->handle); + clk_hw_get_name(&clk->hw), &clk->handle); } static void clk_unvote_q6afe_block(struct clk_hw *hw) @@ -120,84 +115,76 @@ static const struct clk_ops clk_vote_q6afe_ops = { .unprepare = clk_unvote_q6afe_block, }; -static struct q6afe_clk *q6afe_clks[Q6AFE_MAX_CLK_ID] = { - [LPASS_CLK_ID_PRI_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_IBIT), - [LPASS_CLK_ID_PRI_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_EBIT), - [LPASS_CLK_ID_SEC_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_IBIT), - [LPASS_CLK_ID_SEC_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_EBIT), - [LPASS_CLK_ID_TER_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_IBIT), - [LPASS_CLK_ID_TER_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_EBIT), - [LPASS_CLK_ID_QUAD_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_IBIT), - [LPASS_CLK_ID_QUAD_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_EBIT), - [LPASS_CLK_ID_SPEAKER_I2S_IBIT] = - Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_IBIT), - [LPASS_CLK_ID_SPEAKER_I2S_EBIT] = - Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_EBIT), - [LPASS_CLK_ID_SPEAKER_I2S_OSR] = - Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_OSR), - [LPASS_CLK_ID_QUI_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_IBIT), - [LPASS_CLK_ID_QUI_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_EBIT), - [LPASS_CLK_ID_SEN_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_IBIT), - [LPASS_CLK_ID_SEN_MI2S_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_EBIT), - [LPASS_CLK_ID_INT0_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT0_MI2S_IBIT), - [LPASS_CLK_ID_INT1_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT1_MI2S_IBIT), - [LPASS_CLK_ID_INT2_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT2_MI2S_IBIT), - [LPASS_CLK_ID_INT3_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT3_MI2S_IBIT), - [LPASS_CLK_ID_INT4_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT4_MI2S_IBIT), - [LPASS_CLK_ID_INT5_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT), - [LPASS_CLK_ID_INT6_MI2S_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT), - [LPASS_CLK_ID_QUI_MI2S_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_OSR), - [LPASS_CLK_ID_PRI_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_IBIT), - [LPASS_CLK_ID_PRI_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_EBIT), - [LPASS_CLK_ID_SEC_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_IBIT), - [LPASS_CLK_ID_SEC_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_EBIT), - [LPASS_CLK_ID_TER_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_IBIT), - [LPASS_CLK_ID_TER_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_EBIT), - [LPASS_CLK_ID_QUAD_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_IBIT), - [LPASS_CLK_ID_QUAD_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_EBIT), - [LPASS_CLK_ID_QUIN_PCM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_IBIT), - [LPASS_CLK_ID_QUIN_PCM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_EBIT), - [LPASS_CLK_ID_QUI_PCM_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUI_PCM_OSR), - [LPASS_CLK_ID_PRI_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_IBIT), - [LPASS_CLK_ID_PRI_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_EBIT), - [LPASS_CLK_ID_SEC_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_IBIT), - [LPASS_CLK_ID_SEC_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_EBIT), - [LPASS_CLK_ID_TER_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_IBIT), - [LPASS_CLK_ID_TER_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_EBIT), - [LPASS_CLK_ID_QUAD_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_IBIT), - [LPASS_CLK_ID_QUAD_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_EBIT), - [LPASS_CLK_ID_QUIN_TDM_IBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_IBIT), - [LPASS_CLK_ID_QUIN_TDM_EBIT] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_EBIT), - [LPASS_CLK_ID_QUIN_TDM_OSR] = Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_OSR), - [LPASS_CLK_ID_MCLK_1] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_1), - [LPASS_CLK_ID_MCLK_2] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_2), - [LPASS_CLK_ID_MCLK_3] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_3), - [LPASS_CLK_ID_MCLK_4] = Q6AFE_CLK(LPASS_CLK_ID_MCLK_4), - [LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE] = - Q6AFE_CLK(LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE), - [LPASS_CLK_ID_INT_MCLK_0] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_0), - [LPASS_CLK_ID_INT_MCLK_1] = Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_1), - [LPASS_CLK_ID_WSA_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_MCLK), - [LPASS_CLK_ID_WSA_CORE_NPL_MCLK] = - Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK), - [LPASS_CLK_ID_VA_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_MCLK), - [LPASS_CLK_ID_TX_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_MCLK), - [LPASS_CLK_ID_TX_CORE_NPL_MCLK] = - Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_NPL_MCLK), - [LPASS_CLK_ID_RX_CORE_MCLK] = Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_MCLK), - [LPASS_CLK_ID_RX_CORE_NPL_MCLK] = - Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_NPL_MCLK), - [LPASS_CLK_ID_VA_CORE_2X_MCLK] = - Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_2X_MCLK), - [LPASS_HW_AVTIMER_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_AVTIMER_VOTE, - Q6AFE_LPASS_CORE_AVTIMER_BLOCK, - "LPASS_AVTIMER_MACRO"), - [LPASS_HW_MACRO_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_MACRO_VOTE, - Q6AFE_LPASS_CORE_HW_MACRO_BLOCK, - "LPASS_HW_MACRO"), - [LPASS_HW_DCODEC_VOTE] = Q6AFE_VOTE_CLK(LPASS_HW_DCODEC_VOTE, - Q6AFE_LPASS_CORE_HW_DCODEC_BLOCK, - "LPASS_HW_DCODEC"), +static const struct q6afe_clk_init q6afe_clks[] = { + Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_PRI_MI2S_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEC_MI2S_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_TER_MI2S_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUAD_MI2S_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_SPEAKER_I2S_OSR), + Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEN_MI2S_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_INT0_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_INT1_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_INT2_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_INT3_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_INT4_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_INT5_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_INT6_MI2S_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUI_MI2S_OSR), + Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_PRI_PCM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEC_PCM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_TER_PCM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUAD_PCM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUIN_PCM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUI_PCM_OSR), + Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_PRI_TDM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_SEC_TDM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_TER_TDM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUAD_TDM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_IBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_EBIT), + Q6AFE_CLK(LPASS_CLK_ID_QUIN_TDM_OSR), + Q6AFE_CLK(LPASS_CLK_ID_MCLK_1), + Q6AFE_CLK(LPASS_CLK_ID_MCLK_2), + Q6AFE_CLK(LPASS_CLK_ID_MCLK_3), + Q6AFE_CLK(LPASS_CLK_ID_MCLK_4), + Q6AFE_CLK(LPASS_CLK_ID_INTERNAL_DIGITAL_CODEC_CORE), + Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_0), + Q6AFE_CLK(LPASS_CLK_ID_INT_MCLK_1), + Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_MCLK), + Q6AFE_CLK(LPASS_CLK_ID_WSA_CORE_NPL_MCLK), + Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_MCLK), + Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_MCLK), + Q6AFE_CLK(LPASS_CLK_ID_TX_CORE_NPL_MCLK), + Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_MCLK), + Q6AFE_CLK(LPASS_CLK_ID_RX_CORE_NPL_MCLK), + Q6AFE_CLK(LPASS_CLK_ID_VA_CORE_2X_MCLK), + Q6AFE_VOTE_CLK(LPASS_HW_AVTIMER_VOTE, + Q6AFE_LPASS_CORE_AVTIMER_BLOCK, + "LPASS_AVTIMER_MACRO"), + Q6AFE_VOTE_CLK(LPASS_HW_MACRO_VOTE, + Q6AFE_LPASS_CORE_HW_MACRO_BLOCK, + "LPASS_HW_MACRO"), + Q6AFE_VOTE_CLK(LPASS_HW_DCODEC_VOTE, + Q6AFE_LPASS_CORE_HW_DCODEC_BLOCK, + "LPASS_HW_DCODEC"), }; static struct clk_hw *q6afe_of_clk_hw_get(struct of_phandle_args *clkspec, @@ -207,7 +194,7 @@ static struct clk_hw *q6afe_of_clk_hw_get(struct of_phandle_args *clkspec, unsigned int idx = clkspec->args[0]; unsigned int attr = clkspec->args[1]; - if (idx >= cc->num_clks || attr > LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR) { + if (idx >= Q6AFE_MAX_CLK_ID || attr > LPASS_CLK_ATTRIBUTE_COUPLE_DIVISOR) { dev_err(cc->dev, "Invalid clk specifier (%d, %d)\n", idx, attr); return ERR_PTR(-EINVAL); } @@ -230,20 +217,36 @@ static int q6afe_clock_dev_probe(struct platform_device *pdev) if (!cc) return -ENOMEM; - cc->clks = &q6afe_clks[0]; - cc->num_clks = ARRAY_SIZE(q6afe_clks); + cc->dev = dev; for (i = 0; i < ARRAY_SIZE(q6afe_clks); i++) { - if (!q6afe_clks[i]) - continue; + unsigned int id = q6afe_clks[i].clk_id; + struct clk_init_data init = { + .name = q6afe_clks[i].name, + }; + struct q6afe_clk *clk; - q6afe_clks[i]->dev = dev; + clk = devm_kzalloc(dev, sizeof(*clk), GFP_KERNEL); + if (!clk) + return -ENOMEM; - ret = devm_clk_hw_register(dev, &q6afe_clks[i]->hw); + clk->dev = dev; + clk->afe_clk_id = q6afe_clks[i].afe_clk_id; + clk->rate = q6afe_clks[i].rate; + clk->hw.init = &init; + + if (clk->rate) + init.ops = &clk_q6afe_ops; + else + init.ops = &clk_vote_q6afe_ops; + + cc->clks[id] = clk; + + ret = devm_clk_hw_register(dev, &clk->hw); if (ret) return ret; } - ret = of_clk_add_hw_provider(dev->of_node, q6afe_of_clk_hw_get, cc); + ret = devm_of_clk_add_hw_provider(dev, q6afe_of_clk_hw_get, cc); if (ret) return ret; diff --git a/sound/soc/qcom/qdsp6/q6afe.c b/sound/soc/qcom/qdsp6/q6afe.c index 38f6042fe893..729d27da0447 100644 --- a/sound/soc/qcom/qdsp6/q6afe.c +++ b/sound/soc/qcom/qdsp6/q6afe.c @@ -1680,7 +1680,7 @@ int q6afe_unvote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, EXPORT_SYMBOL(q6afe_unvote_lpass_core_hw); int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, - char *client_name, uint32_t *client_handle) + const char *client_name, uint32_t *client_handle) { struct q6afe *afe = dev_get_drvdata(dev->parent); struct afe_cmd_remote_lpass_core_hw_vote_request *vote_cfg; diff --git a/sound/soc/qcom/qdsp6/q6afe.h b/sound/soc/qcom/qdsp6/q6afe.h index 41133f8797c9..f9a1c04e38c2 100644 --- a/sound/soc/qcom/qdsp6/q6afe.h +++ b/sound/soc/qcom/qdsp6/q6afe.h @@ -236,7 +236,7 @@ int q6afe_port_set_sysclk(struct q6afe_port *port, int clk_id, int q6afe_set_lpass_clock(struct device *dev, int clk_id, int attri, int clk_root, unsigned int freq); int q6afe_vote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, - char *client_name, uint32_t *client_handle); + const char *client_name, uint32_t *client_handle); int q6afe_unvote_lpass_core_hw(struct device *dev, uint32_t hw_block_id, uint32_t client_handle); #endif /* __Q6AFE_H__ */ From 9ae31e2ab293bf4d9c42e7079b156072f8a7f8ca Mon Sep 17 00:00:00 2001 From: Mauri Sandberg Date: Mon, 29 Mar 2021 15:31:36 +0300 Subject: [PATCH 0502/1091] MIPS: kernel: setup.c: fix compilation error With ath79_defconfig enabling CONFIG_MIPS_ELF_APPENDED_DTB gives a compilation error. This patch fixes it. Build log: ... CC kernel/locking/percpu-rwsem.o ../arch/mips/kernel/setup.c:46:39: error: conflicting types for '__appended_dtb' const char __section(".appended_dtb") __appended_dtb[0x100000]; ^~~~~~~~~~~~~~ In file included from ../arch/mips/kernel/setup.c:34: ../arch/mips/include/asm/bootinfo.h:118:13: note: previous declaration of '__appended_dtb' was here extern char __appended_dtb[]; ^~~~~~~~~~~~~~ CC fs/attr.o make[4]: *** [../scripts/Makefile.build:271: arch/mips/kernel/setup.o] Error 1 ... Root cause seems to be: Fixes: b83ba0b9df56 ("MIPS: of: Introduce helper function to get DTB") Signed-off-by: Mauri Sandberg Reviewed-by: Thomas Bogendoerfer Cc: trivial@kernel.org Signed-off-by: Thomas Bogendoerfer --- arch/mips/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 279be0153f8b..23a140327a0b 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -43,7 +43,7 @@ #include #ifdef CONFIG_MIPS_ELF_APPENDED_DTB -const char __section(".appended_dtb") __appended_dtb[0x100000]; +char __section(".appended_dtb") __appended_dtb[0x100000]; #endif /* CONFIG_MIPS_ELF_APPENDED_DTB */ struct cpuinfo_mips cpu_data[NR_CPUS] __read_mostly; From 59300b36f85f254260c81d9dd09195fa49eb0f98 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Tue, 30 Mar 2021 09:58:38 -0400 Subject: [PATCH 0503/1091] ftrace: Check if pages were allocated before calling free_pages() It is possible that on error pg->size can be zero when getting its order, which would return a -1 value. It is dangerous to pass in an order of -1 to free_pages(). Check if order is greater than or equal to zero before calling free_pages(). Link: https://lore.kernel.org/lkml/20210330093916.432697c7@gandalf.local.home/ Reported-by: Abaci Robot Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/ftrace.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/kernel/trace/ftrace.c b/kernel/trace/ftrace.c index 4d8e35575549..12223132eff4 100644 --- a/kernel/trace/ftrace.c +++ b/kernel/trace/ftrace.c @@ -3231,7 +3231,8 @@ ftrace_allocate_pages(unsigned long num_to_init) pg = start_pg; while (pg) { order = get_count_order(pg->size / ENTRIES_PER_PAGE); - free_pages((unsigned long)pg->records, order); + if (order >= 0) + free_pages((unsigned long)pg->records, order); start_pg = pg->next; kfree(pg); pg = start_pg; @@ -6418,7 +6419,8 @@ void ftrace_release_mod(struct module *mod) clear_mod_from_hashes(pg); order = get_count_order(pg->size / ENTRIES_PER_PAGE); - free_pages((unsigned long)pg->records, order); + if (order >= 0) + free_pages((unsigned long)pg->records, order); tmp_page = pg->next; kfree(pg); ftrace_number_of_pages -= 1 << order; @@ -6778,7 +6780,8 @@ void ftrace_free_mem(struct module *mod, void *start_ptr, void *end_ptr) if (!pg->index) { *last_pg = pg->next; order = get_count_order(pg->size / ENTRIES_PER_PAGE); - free_pages((unsigned long)pg->records, order); + if (order >= 0) + free_pages((unsigned long)pg->records, order); ftrace_number_of_pages -= 1 << order; ftrace_number_of_groups--; kfree(pg); From 8b01a0d0b5c1327296b37a13c37ca7ab31841577 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 26 Mar 2021 13:50:03 -0600 Subject: [PATCH 0504/1091] ASoC: dt-bindings: nvidia, tegra210-ahub: Add missing child nodes The nvidia,tegra210-ahub binding is missing schema for child nodes. This results in warnings if 'additionalProperties: false' is set (or when the tools implement 'unevaluatedProperties' support). Add the child nodes and reference their schema if one exists. Cc: Liam Girdwood Cc: Mark Brown Cc: Thierry Reding Cc: Jonathan Hunter Cc: Sameer Pujar Cc: alsa-devel@alsa-project.org Cc: linux-tegra@vger.kernel.org Signed-off-by: Rob Herring Acked-by: Thierry Reding Acked-by: Sameer Pujar Link: https://lore.kernel.org/r/20210326195003.3756394-1-robh@kernel.org Signed-off-by: Mark Brown --- .../bindings/sound/nvidia,tegra210-ahub.yaml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml index 31f3e51974bb..61d0c944e972 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml @@ -66,6 +66,22 @@ properties: number of port nodes depend on the number of clients that AHUB may have depending on the SoC revision. +patternProperties: + '^i2s@[0-9a-f]+$': + type: object + + '^dmic@[0-9a-f]+$': + type: object + $ref: nvidia,tegra210-dmic.yaml# + + '^admaif@[0-9a-f]+$': + type: object + $ref: nvidia,tegra210-admaif.yaml# + + '^dspk@[0-9a-f]+$': + type: object + $ref: nvidia,tegra186-dspk.yaml# + required: - compatible - reg From e720e7d0e983bf05de80b231bccc39f1487f0f16 Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 29 Mar 2021 21:42:08 -0700 Subject: [PATCH 0505/1091] mm: fix race by making init_zero_pfn() early_initcall MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There are code paths that rely on zero_pfn to be fully initialized before core_initcall. For example, wq_sysfs_init() is a core_initcall function that eventually results in a call to kernel_execve, which causes a page fault with a subsequent mmput. If zero_pfn is not initialized by then it may not get cleaned up properly and result in an error: BUG: Bad rss-counter state mm:(ptrval) type:MM_ANONPAGES val:1 Here is an analysis of the race as seen on a MIPS device. On this particular MT7621 device (Ubiquiti ER-X), zero_pfn is PFN 0 until initialized, at which point it becomes PFN 5120: 1. wq_sysfs_init calls into kobject_uevent_env at core_initcall: kobject_uevent_env+0x7e4/0x7ec kset_register+0x68/0x88 bus_register+0xdc/0x34c subsys_virtual_register+0x34/0x78 wq_sysfs_init+0x1c/0x4c do_one_initcall+0x50/0x1a8 kernel_init_freeable+0x230/0x2c8 kernel_init+0x10/0x100 ret_from_kernel_thread+0x14/0x1c 2. kobject_uevent_env() calls call_usermodehelper_exec() which executes kernel_execve asynchronously. 3. Memory allocations in kernel_execve cause a page fault, bumping the MM reference counter: add_mm_counter_fast+0xb4/0xc0 handle_mm_fault+0x6e4/0xea0 __get_user_pages.part.78+0x190/0x37c __get_user_pages_remote+0x128/0x360 get_arg_page+0x34/0xa0 copy_string_kernel+0x194/0x2a4 kernel_execve+0x11c/0x298 call_usermodehelper_exec_async+0x114/0x194 4. In case zero_pfn has not been initialized yet, zap_pte_range does not decrement the MM_ANONPAGES RSS counter and the BUG message is triggered shortly afterwards when __mmdrop checks the ref counters: __mmdrop+0x98/0x1d0 free_bprm+0x44/0x118 kernel_execve+0x160/0x1d8 call_usermodehelper_exec_async+0x114/0x194 ret_from_kernel_thread+0x14/0x1c To avoid races such as described above, initialize init_zero_pfn at early_initcall level. Depending on the architecture, ZERO_PAGE is either constant or gets initialized even earlier, at paging_init, so there is no issue with initializing zero_pfn earlier. Link: https://lkml.kernel.org/r/CALCv0x2YqOXEAy2Q=hafjhHCtTHVodChv1qpM=niAXOpqEbt7w@mail.gmail.com Signed-off-by: Ilya Lipnitskiy Cc: Hugh Dickins Cc: "Eric W. Biederman" Cc: stable@vger.kernel.org Tested-by: 周琰杰 (Zhou Yanjie) Signed-off-by: Linus Torvalds --- mm/memory.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/memory.c b/mm/memory.c index 5efa07fb6cdc..550405fc3b5e 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -166,7 +166,7 @@ static int __init init_zero_pfn(void) zero_pfn = page_to_pfn(ZERO_PAGE(0)); return 0; } -core_initcall(init_zero_pfn); +early_initcall(init_zero_pfn); void mm_trace_rss_stat(struct mm_struct *mm, int member, long count) { From 75f94ecbd0dfd2ac4e671f165f5ae864b7301422 Mon Sep 17 00:00:00 2001 From: Stefan Raspl Date: Thu, 25 Mar 2021 13:29:49 +0100 Subject: [PATCH 0506/1091] tools/kvm_stat: Add restart delay If this service is enabled and the system rebooted, Systemd's initial attempt to start this unit file may fail in case the kvm module is not loaded. Since we did not specify a delay for the retries, Systemd restarts with a minimum delay a number of times before giving up and disabling the service. Which means a subsequent kvm module load will have kvm running without monitoring. Adding a delay to fix this. Signed-off-by: Stefan Raspl Message-Id: <20210325122949.1433271-1-raspl@linux.ibm.com> Signed-off-by: Paolo Bonzini --- tools/kvm/kvm_stat/kvm_stat.service | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/kvm/kvm_stat/kvm_stat.service b/tools/kvm/kvm_stat/kvm_stat.service index 71aabaffe779..8f13b843d5b4 100644 --- a/tools/kvm/kvm_stat/kvm_stat.service +++ b/tools/kvm/kvm_stat/kvm_stat.service @@ -9,6 +9,7 @@ Type=simple ExecStart=/usr/bin/kvm_stat -dtcz -s 10 -L /var/log/kvm_stat.csv ExecReload=/bin/kill -HUP $MAINPID Restart=always +RestartSec=60s SyslogIdentifier=kvm_stat SyslogLevel=debug From d632826f26f2361e6ef18881611928036fac30e6 Mon Sep 17 00:00:00 2001 From: Haiwei Li Date: Sat, 13 Mar 2021 13:10:32 +0800 Subject: [PATCH 0507/1091] KVM: clean up the unused argument kvm_msr_ignored_check function never uses vcpu argument. Clean up the function and invokers. Signed-off-by: Haiwei Li Message-Id: <20210313051032.4171-1-lihaiwei.kernel@gmail.com> Reviewed-by: Keqian Zhu Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index fe806e894212..f7d12fca397b 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -271,8 +271,7 @@ static struct kmem_cache *x86_emulator_cache; * When called, it means the previous get/set msr reached an invalid msr. * Return true if we want to ignore/silent this failed msr access. */ -static bool kvm_msr_ignored_check(struct kvm_vcpu *vcpu, u32 msr, - u64 data, bool write) +static bool kvm_msr_ignored_check(u32 msr, u64 data, bool write) { const char *op = write ? "wrmsr" : "rdmsr"; @@ -1445,7 +1444,7 @@ static int do_get_msr_feature(struct kvm_vcpu *vcpu, unsigned index, u64 *data) if (r == KVM_MSR_RET_INVALID) { /* Unconditionally clear the output for simplicity */ *data = 0; - if (kvm_msr_ignored_check(vcpu, index, 0, false)) + if (kvm_msr_ignored_check(index, 0, false)) r = 0; } @@ -1620,7 +1619,7 @@ static int kvm_set_msr_ignored_check(struct kvm_vcpu *vcpu, int ret = __kvm_set_msr(vcpu, index, data, host_initiated); if (ret == KVM_MSR_RET_INVALID) - if (kvm_msr_ignored_check(vcpu, index, data, true)) + if (kvm_msr_ignored_check(index, data, true)) ret = 0; return ret; @@ -1658,7 +1657,7 @@ static int kvm_get_msr_ignored_check(struct kvm_vcpu *vcpu, if (ret == KVM_MSR_RET_INVALID) { /* Unconditionally clear *data for simplicity */ *data = 0; - if (kvm_msr_ignored_check(vcpu, index, 0, false)) + if (kvm_msr_ignored_check(index, 0, false)) ret = 0; } From ecaf088f53fcc893cd00c846f53042a536b9630d Mon Sep 17 00:00:00 2001 From: Dongli Zhang Date: Fri, 26 Mar 2021 00:03:34 -0700 Subject: [PATCH 0508/1091] KVM: x86: remove unused declaration of kvm_write_tsc() kvm_write_tsc() was renamed and made static since commit 0c899c25d754 ("KVM: x86: do not attempt TSC synchronization on guest writes"). Remove its unused declaration. Signed-off-by: Dongli Zhang Message-Id: <20210326070334.12310-1-dongli.zhang@oracle.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/x86/kvm/x86.h b/arch/x86/kvm/x86.h index 39eb04887141..9035e34aa156 100644 --- a/arch/x86/kvm/x86.h +++ b/arch/x86/kvm/x86.h @@ -250,7 +250,6 @@ static inline bool kvm_vcpu_latch_init(struct kvm_vcpu *vcpu) void kvm_write_wall_clock(struct kvm *kvm, gpa_t wall_clock, int sec_hi_ofs); void kvm_inject_realmode_interrupt(struct kvm_vcpu *vcpu, int irq, int inc_eip); -void kvm_write_tsc(struct kvm_vcpu *vcpu, struct msr_data *msr); u64 get_kvmclock_ns(struct kvm *kvm); int kvm_read_guest_virt(struct kvm_vcpu *vcpu, From 1973cadd4cca08eaeca944f60598f04ab0d80682 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 23 Mar 2021 09:45:15 +0100 Subject: [PATCH 0509/1091] KVM: x86/vPMU: Forbid writing to MSR_F15H_PERF MSRs when guest doesn't have X86_FEATURE_PERFCTR_CORE MSR_F15H_PERF_CTL0-5, MSR_F15H_PERF_CTR0-5 MSRs are only available when X86_FEATURE_PERFCTR_CORE CPUID bit was exposed to the guest. KVM, however, allows these MSRs unconditionally because kvm_pmu_is_valid_msr() -> amd_msr_idx_to_pmc() check always passes and because kvm_pmu_set_msr() -> amd_pmu_set_msr() doesn't fail. In case of a counter (CTRn), no big harm is done as we only increase internal PMC's value but in case of an eventsel (CTLn), we go deep into perf internals with a non-existing counter. Note, kvm_get_msr_common() just returns '0' when these MSRs don't exist and this also seems to contradict architectural behavior which is #GP (I did check one old Opteron host) but changing this status quo is a bit scarier. Signed-off-by: Vitaly Kuznetsov Message-Id: <20210323084515.1346540-1-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm/pmu.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/arch/x86/kvm/svm/pmu.c b/arch/x86/kvm/svm/pmu.c index 035da07500e8..fdf587f19c5f 100644 --- a/arch/x86/kvm/svm/pmu.c +++ b/arch/x86/kvm/svm/pmu.c @@ -98,6 +98,8 @@ static enum index msr_to_index(u32 msr) static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, enum pmu_type type) { + struct kvm_vcpu *vcpu = pmu_to_vcpu(pmu); + switch (msr) { case MSR_F15H_PERF_CTL0: case MSR_F15H_PERF_CTL1: @@ -105,6 +107,9 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, case MSR_F15H_PERF_CTL3: case MSR_F15H_PERF_CTL4: case MSR_F15H_PERF_CTL5: + if (!guest_cpuid_has(vcpu, X86_FEATURE_PERFCTR_CORE)) + return NULL; + fallthrough; case MSR_K7_EVNTSEL0 ... MSR_K7_EVNTSEL3: if (type != PMU_TYPE_EVNTSEL) return NULL; @@ -115,6 +120,9 @@ static inline struct kvm_pmc *get_gp_pmc_amd(struct kvm_pmu *pmu, u32 msr, case MSR_F15H_PERF_CTR3: case MSR_F15H_PERF_CTR4: case MSR_F15H_PERF_CTR5: + if (!guest_cpuid_has(vcpu, X86_FEATURE_PERFCTR_CORE)) + return NULL; + fallthrough; case MSR_K7_PERFCTR0 ... MSR_K7_PERFCTR3: if (type != PMU_TYPE_COUNTER) return NULL; From f982fb62a304235397ec092936432199ca50ac4d Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 23 Mar 2021 11:43:31 +0100 Subject: [PATCH 0510/1091] selftests: kvm: make hardware_disable_test less verbose hardware_disable_test produces 512 snippets like ... main: [511] waiting semaphore run_test: [511] start vcpus run_test: [511] all threads launched main: [511] waiting 368us main: [511] killing child and this doesn't have much value, let's print this info with pr_debug(). Signed-off-by: Vitaly Kuznetsov Message-Id: <20210323104331.1354800-1-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/hardware_disable_test.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tools/testing/selftests/kvm/hardware_disable_test.c b/tools/testing/selftests/kvm/hardware_disable_test.c index 2f2eeb8a1d86..5aadf84c91c0 100644 --- a/tools/testing/selftests/kvm/hardware_disable_test.c +++ b/tools/testing/selftests/kvm/hardware_disable_test.c @@ -108,7 +108,7 @@ static void run_test(uint32_t run) kvm_vm_elf_load(vm, program_invocation_name, 0, 0); vm_create_irqchip(vm); - fprintf(stderr, "%s: [%d] start vcpus\n", __func__, run); + pr_debug("%s: [%d] start vcpus\n", __func__, run); for (i = 0; i < VCPU_NUM; ++i) { vm_vcpu_add_default(vm, i, guest_code); payloads[i].vm = vm; @@ -124,7 +124,7 @@ static void run_test(uint32_t run) check_set_affinity(throw_away, &cpu_set); } } - fprintf(stderr, "%s: [%d] all threads launched\n", __func__, run); + pr_debug("%s: [%d] all threads launched\n", __func__, run); sem_post(sem); for (i = 0; i < VCPU_NUM; ++i) check_join(threads[i], &b); @@ -147,16 +147,16 @@ int main(int argc, char **argv) if (pid == 0) run_test(i); /* This function always exits */ - fprintf(stderr, "%s: [%d] waiting semaphore\n", __func__, i); + pr_debug("%s: [%d] waiting semaphore\n", __func__, i); sem_wait(sem); r = (rand() % DELAY_US_MAX) + 1; - fprintf(stderr, "%s: [%d] waiting %dus\n", __func__, i, r); + pr_debug("%s: [%d] waiting %dus\n", __func__, i, r); usleep(r); r = waitpid(pid, &s, WNOHANG); TEST_ASSERT(r != pid, "%s: [%d] child exited unexpectedly status: [%d]", __func__, i, s); - fprintf(stderr, "%s: [%d] killing child\n", __func__, i); + pr_debug("%s: [%d] killing child\n", __func__, i); kill(pid, SIGKILL); } From 6fb3084ab5d9331cfadf07c59cf4a0bd4059bf4a Mon Sep 17 00:00:00 2001 From: Siddharth Chandrasekaran Date: Wed, 24 Mar 2021 13:43:47 +0100 Subject: [PATCH 0511/1091] KVM: make: Fix out-of-source module builds Building kvm module out-of-source with, make -C $SRC O=$BIN M=arch/x86/kvm fails to find "irq.h" as the include dir passed to cflags-y does not prefix the source dir. Fix this by prefixing $(srctree) to the include dir path. Signed-off-by: Siddharth Chandrasekaran Message-Id: <20210324124347.18336-1-sidcha@amazon.de> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/Makefile b/arch/x86/kvm/Makefile index 1b4766fe1de2..eafc4d601f25 100644 --- a/arch/x86/kvm/Makefile +++ b/arch/x86/kvm/Makefile @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0 -ccflags-y += -Iarch/x86/kvm +ccflags-y += -I $(srctree)/arch/x86/kvm ccflags-$(CONFIG_KVM_WERROR) += -Werror ifeq ($(CONFIG_FRAME_POINTER),y) From a835429cda91621fca915d80672a157b47738afb Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 25 Mar 2021 13:01:17 -0700 Subject: [PATCH 0512/1091] KVM: x86/mmu: Ensure TLBs are flushed when yielding during GFN range zap When flushing a range of GFNs across multiple roots, ensure any pending flush from a previous root is honored before yielding while walking the tables of the current root. Note, kvm_tdp_mmu_zap_gfn_range() now intentionally overwrites its local "flush" with the result to avoid redundant flushes. zap_gfn_range() preserves and return the incoming "flush", unless of course the flush was performed prior to yielding and no new flush was triggered. Fixes: 1af4a96025b3 ("KVM: x86/mmu: Yield in TDU MMU iter even if no SPTES changed") Cc: stable@vger.kernel.org Reviewed-by: Ben Gardon Signed-off-by: Sean Christopherson Message-Id: <20210325200119.1359384-2-seanjc@google.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/tdp_mmu.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index d78915019b08..f80648ac1d15 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -86,7 +86,7 @@ static inline struct kvm_mmu_page *tdp_mmu_next_root(struct kvm *kvm, list_for_each_entry(_root, &_kvm->arch.tdp_mmu_roots, link) static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, - gfn_t start, gfn_t end, bool can_yield); + gfn_t start, gfn_t end, bool can_yield, bool flush); void kvm_tdp_mmu_free_root(struct kvm *kvm, struct kvm_mmu_page *root) { @@ -99,7 +99,7 @@ void kvm_tdp_mmu_free_root(struct kvm *kvm, struct kvm_mmu_page *root) list_del(&root->link); - zap_gfn_range(kvm, root, 0, max_gfn, false); + zap_gfn_range(kvm, root, 0, max_gfn, false, false); free_page((unsigned long)root->spt); kmem_cache_free(mmu_page_header_cache, root); @@ -678,20 +678,21 @@ static inline bool tdp_mmu_iter_cond_resched(struct kvm *kvm, * scheduler needs the CPU or there is contention on the MMU lock. If this * function cannot yield, it will not release the MMU lock or reschedule and * the caller must ensure it does not supply too large a GFN range, or the - * operation can cause a soft lockup. + * operation can cause a soft lockup. Note, in some use cases a flush may be + * required by prior actions. Ensure the pending flush is performed prior to + * yielding. */ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, - gfn_t start, gfn_t end, bool can_yield) + gfn_t start, gfn_t end, bool can_yield, bool flush) { struct tdp_iter iter; - bool flush_needed = false; rcu_read_lock(); tdp_root_for_each_pte(iter, root, start, end) { if (can_yield && - tdp_mmu_iter_cond_resched(kvm, &iter, flush_needed)) { - flush_needed = false; + tdp_mmu_iter_cond_resched(kvm, &iter, flush)) { + flush = false; continue; } @@ -709,11 +710,11 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, continue; tdp_mmu_set_spte(kvm, &iter, 0); - flush_needed = true; + flush = true; } rcu_read_unlock(); - return flush_needed; + return flush; } /* @@ -728,7 +729,7 @@ bool kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, gfn_t start, gfn_t end) bool flush = false; for_each_tdp_mmu_root_yield_safe(kvm, root) - flush |= zap_gfn_range(kvm, root, start, end, true); + flush = zap_gfn_range(kvm, root, start, end, true, flush); return flush; } @@ -940,7 +941,7 @@ static int zap_gfn_range_hva_wrapper(struct kvm *kvm, struct kvm_mmu_page *root, gfn_t start, gfn_t end, unsigned long unused) { - return zap_gfn_range(kvm, root, start, end, false); + return zap_gfn_range(kvm, root, start, end, false, false); } int kvm_tdp_mmu_zap_hva_range(struct kvm *kvm, unsigned long start, From 048f49809c526348775425420fb5b8e84fd9a133 Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 25 Mar 2021 13:01:18 -0700 Subject: [PATCH 0513/1091] KVM: x86/mmu: Ensure TLBs are flushed for TDP MMU during NX zapping Honor the "flush needed" return from kvm_tdp_mmu_zap_gfn_range(), which does the flush itself if and only if it yields (which it will never do in this particular scenario), and otherwise expects the caller to do the flush. If pages are zapped from the TDP MMU but not the legacy MMU, then no flush will occur. Fixes: 29cf0f5007a2 ("kvm: x86/mmu: NX largepage recovery for TDP MMU") Cc: stable@vger.kernel.org Cc: Ben Gardon Signed-off-by: Sean Christopherson Message-Id: <20210325200119.1359384-3-seanjc@google.com> Reviewed-by: Ben Gardon Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/mmu.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index d75524bc8423..2705f9fa22b9 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -5884,6 +5884,8 @@ static void kvm_recover_nx_lpages(struct kvm *kvm) struct kvm_mmu_page *sp; unsigned int ratio; LIST_HEAD(invalid_list); + bool flush = false; + gfn_t gfn_end; ulong to_zap; rcu_idx = srcu_read_lock(&kvm->srcu); @@ -5905,19 +5907,20 @@ static void kvm_recover_nx_lpages(struct kvm *kvm) lpage_disallowed_link); WARN_ON_ONCE(!sp->lpage_disallowed); if (is_tdp_mmu_page(sp)) { - kvm_tdp_mmu_zap_gfn_range(kvm, sp->gfn, - sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level)); + gfn_end = sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level); + flush = kvm_tdp_mmu_zap_gfn_range(kvm, sp->gfn, gfn_end); } else { kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list); WARN_ON_ONCE(sp->lpage_disallowed); } if (need_resched() || rwlock_needbreak(&kvm->mmu_lock)) { - kvm_mmu_commit_zap_page(kvm, &invalid_list); + kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush); cond_resched_rwlock_write(&kvm->mmu_lock); + flush = false; } } - kvm_mmu_commit_zap_page(kvm, &invalid_list); + kvm_mmu_remote_flush_or_zap(kvm, &invalid_list, flush); write_unlock(&kvm->mmu_lock); srcu_read_unlock(&kvm->srcu, rcu_idx); From 33a3164161fc86b9cc238f7f2aa2ccb1d5559b1c Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Thu, 25 Mar 2021 13:01:19 -0700 Subject: [PATCH 0514/1091] KVM: x86/mmu: Don't allow TDP MMU to yield when recovering NX pages Prevent the TDP MMU from yielding when zapping a gfn range during NX page recovery. If a flush is pending from a previous invocation of the zapping helper, either in the TDP MMU or the legacy MMU, but the TDP MMU has not accumulated a flush for the current invocation, then yielding will release mmu_lock with stale TLB entries. That being said, this isn't technically a bug fix in the current code, as the TDP MMU will never yield in this case. tdp_mmu_iter_cond_resched() will yield if and only if it has made forward progress, as defined by the current gfn vs. the last yielded (or starting) gfn. Because zapping a single shadow page is guaranteed to (a) find that page and (b) step sideways at the level of the shadow page, the TDP iter will break its loop before getting a chance to yield. But that is all very, very subtle, and will break at the slightest sneeze, e.g. zapping while holding mmu_lock for read would break as the TDP MMU wouldn't be guaranteed to see the present shadow page, and thus could step sideways at a lower level. Cc: Ben Gardon Signed-off-by: Sean Christopherson Message-Id: <20210325200119.1359384-4-seanjc@google.com> [Add lockdep assertion. - Paolo] Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/mmu.c | 4 +--- arch/x86/kvm/mmu/tdp_mmu.c | 5 +++-- arch/x86/kvm/mmu/tdp_mmu.h | 24 +++++++++++++++++++++++- 3 files changed, 27 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 2705f9fa22b9..486aa94ecf1d 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -5885,7 +5885,6 @@ static void kvm_recover_nx_lpages(struct kvm *kvm) unsigned int ratio; LIST_HEAD(invalid_list); bool flush = false; - gfn_t gfn_end; ulong to_zap; rcu_idx = srcu_read_lock(&kvm->srcu); @@ -5907,8 +5906,7 @@ static void kvm_recover_nx_lpages(struct kvm *kvm) lpage_disallowed_link); WARN_ON_ONCE(!sp->lpage_disallowed); if (is_tdp_mmu_page(sp)) { - gfn_end = sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level); - flush = kvm_tdp_mmu_zap_gfn_range(kvm, sp->gfn, gfn_end); + flush = kvm_tdp_mmu_zap_sp(kvm, sp); } else { kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list); WARN_ON_ONCE(sp->lpage_disallowed); diff --git a/arch/x86/kvm/mmu/tdp_mmu.c b/arch/x86/kvm/mmu/tdp_mmu.c index f80648ac1d15..81352cd428fa 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.c +++ b/arch/x86/kvm/mmu/tdp_mmu.c @@ -723,13 +723,14 @@ static bool zap_gfn_range(struct kvm *kvm, struct kvm_mmu_page *root, * SPTEs have been cleared and a TLB flush is needed before releasing the * MMU lock. */ -bool kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, gfn_t start, gfn_t end) +bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, gfn_t start, gfn_t end, + bool can_yield) { struct kvm_mmu_page *root; bool flush = false; for_each_tdp_mmu_root_yield_safe(kvm, root) - flush = zap_gfn_range(kvm, root, start, end, true, flush); + flush = zap_gfn_range(kvm, root, start, end, can_yield, flush); return flush; } diff --git a/arch/x86/kvm/mmu/tdp_mmu.h b/arch/x86/kvm/mmu/tdp_mmu.h index 3b761c111bff..31096ece9b14 100644 --- a/arch/x86/kvm/mmu/tdp_mmu.h +++ b/arch/x86/kvm/mmu/tdp_mmu.h @@ -8,7 +8,29 @@ hpa_t kvm_tdp_mmu_get_vcpu_root_hpa(struct kvm_vcpu *vcpu); void kvm_tdp_mmu_free_root(struct kvm *kvm, struct kvm_mmu_page *root); -bool kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, gfn_t start, gfn_t end); +bool __kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, gfn_t start, gfn_t end, + bool can_yield); +static inline bool kvm_tdp_mmu_zap_gfn_range(struct kvm *kvm, gfn_t start, + gfn_t end) +{ + return __kvm_tdp_mmu_zap_gfn_range(kvm, start, end, true); +} +static inline bool kvm_tdp_mmu_zap_sp(struct kvm *kvm, struct kvm_mmu_page *sp) +{ + gfn_t end = sp->gfn + KVM_PAGES_PER_HPAGE(sp->role.level); + + /* + * Don't allow yielding, as the caller may have a flush pending. Note, + * if mmu_lock is held for write, zapping will never yield in this case, + * but explicitly disallow it for safety. The TDP MMU does not yield + * until it has made forward progress (steps sideways), and when zapping + * a single shadow page that it's guaranteed to see (thus the mmu_lock + * requirement), its "step sideways" will always step beyond the bounds + * of the shadow page's gfn range and stop iterating before yielding. + */ + lockdep_assert_held_write(&kvm->mmu_lock); + return __kvm_tdp_mmu_zap_gfn_range(kvm, sp->gfn, end, false); +} void kvm_tdp_mmu_zap_all(struct kvm *kvm); int kvm_tdp_mmu_map(struct kvm_vcpu *vcpu, gpa_t gpa, u32 error_code, From f8fb97c915954fc6de6513cdf277103b5c6df7b3 Mon Sep 17 00:00:00 2001 From: Dmitry Osipenko Date: Tue, 2 Mar 2021 16:15:06 +0300 Subject: [PATCH 0515/1091] drm/tegra: dc: Don't set PLL clock to 0Hz RGB output doesn't allow to change parent clock rate of the display and PCLK rate is set to 0Hz in this case. The tegra_dc_commit_state() shall not set the display clock to 0Hz since this change propagates to the parent clock. The DISP clock is defined as a NODIV clock by the tegra-clk driver and all NODIV clocks use the CLK_SET_RATE_PARENT flag. This bug stayed unnoticed because by default PLLP is used as the parent clock for the display controller and PLLP silently skips the erroneous 0Hz rate changes because it always has active child clocks that don't permit rate changes. The PLLP isn't acceptable for some devices that we want to upstream (like Samsung Galaxy Tab and ASUS TF700T) due to a display panel clock rate requirements that can't be fulfilled by using PLLP and then the bug pops up in this case since parent clock is set to 0Hz, killing the display output. Don't touch DC clock if pclk=0 in order to fix the problem. Signed-off-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dc.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 0ae3a025efe9..24362533e14c 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -1688,6 +1688,11 @@ static void tegra_dc_commit_state(struct tegra_dc *dc, dev_err(dc->dev, "failed to set clock rate to %lu Hz\n", state->pclk); + + err = clk_set_rate(dc->clk, state->pclk); + if (err < 0) + dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n", + dc->clk, state->pclk, err); } DRM_DEBUG_KMS("rate: %lu, div: %u\n", clk_get_rate(dc->clk), @@ -1698,11 +1703,6 @@ static void tegra_dc_commit_state(struct tegra_dc *dc, value = SHIFT_CLK_DIVIDER(state->div) | PIXEL_CLK_DIVIDER_PCD1; tegra_dc_writel(dc, value, DC_DISP_DISP_CLOCK_CONTROL); } - - err = clk_set_rate(dc->clk, state->pclk); - if (err < 0) - dev_err(dc->dev, "failed to set clock %pC to %lu Hz: %d\n", - dc->clk, state->pclk, err); } static void tegra_dc_stop(struct tegra_dc *dc) From a24f98176d1efae2c37d3438c57a624d530d9c33 Mon Sep 17 00:00:00 2001 From: Mikko Perttunen Date: Mon, 29 Mar 2021 16:38:27 +0300 Subject: [PATCH 0516/1091] gpu: host1x: Use different lock classes for each client To avoid false lockdep warnings, give each client lock a different lock class, passed from the initialization site by macro. Signed-off-by: Mikko Perttunen Signed-off-by: Thierry Reding --- drivers/gpu/host1x/bus.c | 10 ++++++---- include/linux/host1x.h | 9 ++++++++- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/drivers/gpu/host1x/bus.c b/drivers/gpu/host1x/bus.c index 347fb962b6c9..68a766ff0e9d 100644 --- a/drivers/gpu/host1x/bus.c +++ b/drivers/gpu/host1x/bus.c @@ -705,8 +705,9 @@ void host1x_driver_unregister(struct host1x_driver *driver) EXPORT_SYMBOL(host1x_driver_unregister); /** - * host1x_client_register() - register a host1x client + * __host1x_client_register() - register a host1x client * @client: host1x client + * @key: lock class key for the client-specific mutex * * Registers a host1x client with each host1x controller instance. Note that * each client will only match their parent host1x controller and will only be @@ -715,13 +716,14 @@ EXPORT_SYMBOL(host1x_driver_unregister); * device and call host1x_device_init(), which will in turn call each client's * &host1x_client_ops.init implementation. */ -int host1x_client_register(struct host1x_client *client) +int __host1x_client_register(struct host1x_client *client, + struct lock_class_key *key) { struct host1x *host1x; int err; INIT_LIST_HEAD(&client->list); - mutex_init(&client->lock); + __mutex_init(&client->lock, "host1x client lock", key); client->usecount = 0; mutex_lock(&devices_lock); @@ -742,7 +744,7 @@ int host1x_client_register(struct host1x_client *client) return 0; } -EXPORT_SYMBOL(host1x_client_register); +EXPORT_SYMBOL(__host1x_client_register); /** * host1x_client_unregister() - unregister a host1x client diff --git a/include/linux/host1x.h b/include/linux/host1x.h index ce59a6a6a008..9eb77c87a83b 100644 --- a/include/linux/host1x.h +++ b/include/linux/host1x.h @@ -320,7 +320,14 @@ static inline struct host1x_device *to_host1x_device(struct device *dev) int host1x_device_init(struct host1x_device *device); int host1x_device_exit(struct host1x_device *device); -int host1x_client_register(struct host1x_client *client); +int __host1x_client_register(struct host1x_client *client, + struct lock_class_key *key); +#define host1x_client_register(class) \ + ({ \ + static struct lock_class_key __key; \ + __host1x_client_register(class, &__key); \ + }) + int host1x_client_unregister(struct host1x_client *client); int host1x_client_suspend(struct host1x_client *client); From a31500fe7055451ed9043c8fff938dfa6f70ee37 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 19 Mar 2021 08:06:37 +0100 Subject: [PATCH 0517/1091] drm/tegra: dc: Restore coupling of display controllers Coupling of display controllers used to rely on runtime PM to take the companion controller out of reset. Commit fd67e9c6ed5a ("drm/tegra: Do not implement runtime PM") accidentally broke this when runtime PM was removed. Restore this functionality by reusing the hierarchical host1x client suspend/resume infrastructure that's similar to runtime PM and which perfectly fits this use-case. Fixes: fd67e9c6ed5a ("drm/tegra: Do not implement runtime PM") Reported-by: Dmitry Osipenko Reported-by: Paul Fertser Tested-by: Dmitry Osipenko Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/dc.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/tegra/dc.c b/drivers/gpu/drm/tegra/dc.c index 24362533e14c..134986dc2783 100644 --- a/drivers/gpu/drm/tegra/dc.c +++ b/drivers/gpu/drm/tegra/dc.c @@ -2501,22 +2501,18 @@ static int tegra_dc_couple(struct tegra_dc *dc) * POWER_CONTROL registers during CRTC enabling. */ if (dc->soc->coupled_pm && dc->pipe == 1) { - u32 flags = DL_FLAG_PM_RUNTIME | DL_FLAG_AUTOREMOVE_CONSUMER; - struct device_link *link; - struct device *partner; + struct device *companion; + struct tegra_dc *parent; - partner = driver_find_device(dc->dev->driver, NULL, NULL, - tegra_dc_match_by_pipe); - if (!partner) + companion = driver_find_device(dc->dev->driver, NULL, (const void *)0, + tegra_dc_match_by_pipe); + if (!companion) return -EPROBE_DEFER; - link = device_link_add(dc->dev, partner, flags); - if (!link) { - dev_err(dc->dev, "failed to link controllers\n"); - return -EINVAL; - } + parent = dev_get_drvdata(companion); + dc->client.parent = &parent->client; - dev_dbg(dc->dev, "coupled to %s\n", dev_name(partner)); + dev_dbg(dc->dev, "coupled to %s\n", dev_name(companion)); } return 0; From 12efebab09e383bf366bec323bd296b7d90e1c43 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Sat, 10 Oct 2020 11:17:44 -0400 Subject: [PATCH 0518/1091] XArray: Fix split documentation I wrote the documentation backwards; the new order of the entry is stored in the xas and the caller passes the old entry. Reported-by: Zi Yan Signed-off-by: Matthew Wilcox (Oracle) --- lib/xarray.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/lib/xarray.c b/lib/xarray.c index 5fa51614802a..fb3a0ccebb7e 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -987,7 +987,7 @@ static void node_set_marks(struct xa_node *node, unsigned int offset, * xas_split_alloc() - Allocate memory for splitting an entry. * @xas: XArray operation state. * @entry: New entry which will be stored in the array. - * @order: New entry order. + * @order: Current entry order. * @gfp: Memory allocation flags. * * This function should be called before calling xas_split(). @@ -1041,9 +1041,10 @@ EXPORT_SYMBOL_GPL(xas_split_alloc); * xas_split() - Split a multi-index entry into smaller entries. * @xas: XArray operation state. * @entry: New entry to store in the array. - * @order: New entry order. + * @order: Current entry order. * - * The value in the entry is copied to all the replacement entries. + * The size of the new entries is set in @xas. The value in @entry is + * copied to all the replacement entries. * * Context: Any context. The caller should hold the xa_lock. */ From 3012110d71f41410932924e1d188f9eb57f1f824 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Thu, 19 Nov 2020 08:32:31 -0500 Subject: [PATCH 0519/1091] XArray: Fix splitting to non-zero orders Splitting an order-4 entry into order-2 entries would leave the array containing pointers to 000040008000c000 instead of 000044448888cccc. This is a one-character fix, but enhance the test suite to check this case. Reported-by: Zi Yan Signed-off-by: Matthew Wilcox (Oracle) --- lib/test_xarray.c | 26 ++++++++++++++------------ lib/xarray.c | 4 ++-- 2 files changed, 16 insertions(+), 14 deletions(-) diff --git a/lib/test_xarray.c b/lib/test_xarray.c index 8294f43f4981..8b1c318189ce 100644 --- a/lib/test_xarray.c +++ b/lib/test_xarray.c @@ -1530,24 +1530,24 @@ static noinline void check_store_range(struct xarray *xa) #ifdef CONFIG_XARRAY_MULTI static void check_split_1(struct xarray *xa, unsigned long index, - unsigned int order) + unsigned int order, unsigned int new_order) { - XA_STATE(xas, xa, index); - void *entry; - unsigned int i = 0; + XA_STATE_ORDER(xas, xa, index, new_order); + unsigned int i; xa_store_order(xa, index, order, xa, GFP_KERNEL); xas_split_alloc(&xas, xa, order, GFP_KERNEL); xas_lock(&xas); xas_split(&xas, xa, order); + for (i = 0; i < (1 << order); i += (1 << new_order)) + __xa_store(xa, index + i, xa_mk_index(index + i), 0); xas_unlock(&xas); - xa_for_each(xa, index, entry) { - XA_BUG_ON(xa, entry != xa); - i++; + for (i = 0; i < (1 << order); i++) { + unsigned int val = index + (i & ~((1 << new_order) - 1)); + XA_BUG_ON(xa, xa_load(xa, index + i) != xa_mk_index(val)); } - XA_BUG_ON(xa, i != 1 << order); xa_set_mark(xa, index, XA_MARK_0); XA_BUG_ON(xa, !xa_get_mark(xa, index, XA_MARK_0)); @@ -1557,14 +1557,16 @@ static void check_split_1(struct xarray *xa, unsigned long index, static noinline void check_split(struct xarray *xa) { - unsigned int order; + unsigned int order, new_order; XA_BUG_ON(xa, !xa_empty(xa)); for (order = 1; order < 2 * XA_CHUNK_SHIFT; order++) { - check_split_1(xa, 0, order); - check_split_1(xa, 1UL << order, order); - check_split_1(xa, 3UL << order, order); + for (new_order = 0; new_order < order; new_order++) { + check_split_1(xa, 0, order, new_order); + check_split_1(xa, 1UL << order, order, new_order); + check_split_1(xa, 3UL << order, order, new_order); + } } } #else diff --git a/lib/xarray.c b/lib/xarray.c index fb3a0ccebb7e..f5d8f54907b4 100644 --- a/lib/xarray.c +++ b/lib/xarray.c @@ -1011,7 +1011,7 @@ void xas_split_alloc(struct xa_state *xas, void *entry, unsigned int order, do { unsigned int i; - void *sibling; + void *sibling = NULL; struct xa_node *node; node = kmem_cache_alloc(radix_tree_node_cachep, gfp); @@ -1021,7 +1021,7 @@ void xas_split_alloc(struct xa_state *xas, void *entry, unsigned int order, for (i = 0; i < XA_CHUNK_SIZE; i++) { if ((i & mask) == 0) { RCU_INIT_POINTER(node->slots[i], entry); - sibling = xa_mk_sibling(0); + sibling = xa_mk_sibling(i); } else { RCU_INIT_POINTER(node->slots[i], sibling); } From df59d0a461bc5935232bf56a279e4d7a71c566a5 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Tue, 30 Mar 2021 13:40:27 -0400 Subject: [PATCH 0520/1091] XArray: Add xa_limit_16b A 16-bit limit is a more common limit than I had realised. Make it generally available. Signed-off-by: Matthew Wilcox (Oracle) --- include/linux/xarray.h | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/include/linux/xarray.h b/include/linux/xarray.h index 92c0160b3352..a91e3d90df8a 100644 --- a/include/linux/xarray.h +++ b/include/linux/xarray.h @@ -229,9 +229,10 @@ static inline int xa_err(void *entry) * * This structure is used either directly or via the XA_LIMIT() macro * to communicate the range of IDs that are valid for allocation. - * Two common ranges are predefined for you: + * Three common ranges are predefined for you: * * xa_limit_32b - [0 - UINT_MAX] * * xa_limit_31b - [0 - INT_MAX] + * * xa_limit_16b - [0 - USHRT_MAX] */ struct xa_limit { u32 max; @@ -242,6 +243,7 @@ struct xa_limit { #define xa_limit_32b XA_LIMIT(0, UINT_MAX) #define xa_limit_31b XA_LIMIT(0, INT_MAX) +#define xa_limit_16b XA_LIMIT(0, USHRT_MAX) typedef unsigned __bitwise xa_mark_t; #define XA_MARK_0 ((__force xa_mark_t)0U) From 7487de534dcbe143e6f41da751dd3ffcf93b00ee Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Tue, 30 Mar 2021 13:44:35 -0400 Subject: [PATCH 0521/1091] radix tree test suite: Fix compilation Commit 4bba4c4bb09a added tools/include/linux/compiler_types.h which includes linux/compiler-gcc.h. Unfortunately, we had our own (empty) compiler_types.h which overrode the one added by that commit, and so we lost the definition of __must_be_array(). Removing our empty compiler_types.h fixes the problem and reduces our divergence from the rest of the tools. Signed-off-by: Matthew Wilcox (Oracle) --- tools/testing/radix-tree/linux/compiler_types.h | 0 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 tools/testing/radix-tree/linux/compiler_types.h diff --git a/tools/testing/radix-tree/linux/compiler_types.h b/tools/testing/radix-tree/linux/compiler_types.h deleted file mode 100644 index e69de29bb2d1..000000000000 From ac097aecfef0bb289ca53d2fe0b73fc7e1612a05 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 19 Mar 2021 14:17:22 +0100 Subject: [PATCH 0522/1091] drm/tegra: sor: Grab runtime PM reference across reset The SOR resets are exclusively shared with the SOR power domain. This means that exclusive access can only be granted temporarily and in order for that to work, a rigorous sequence must be observed. To ensure that a single consumer gets exclusive access to a reset, each consumer must implement a rigorous protocol using the reset_control_acquire() and reset_control_release() functions. However, these functions alone don't provide any guarantees at the system level. Drivers need to ensure that the only a single consumer has access to the reset at the same time. In order for the SOR to be able to exclusively access its reset, it must therefore ensure that the SOR power domain is not powered off by holding on to a runtime PM reference to that power domain across the reset assert/deassert operation. This used to work fine by accident, but was revealed when recently more devices started to rely on the SOR power domain. Fixes: 11c632e1cfd3 ("drm/tegra: sor: Implement acquire/release for reset") Reported-by: Jonathan Hunter Signed-off-by: Thierry Reding --- drivers/gpu/drm/tegra/sor.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/gpu/drm/tegra/sor.c b/drivers/gpu/drm/tegra/sor.c index f02a035dda45..7b88261f57bb 100644 --- a/drivers/gpu/drm/tegra/sor.c +++ b/drivers/gpu/drm/tegra/sor.c @@ -3115,6 +3115,12 @@ static int tegra_sor_init(struct host1x_client *client) * kernel is possible. */ if (sor->rst) { + err = pm_runtime_resume_and_get(sor->dev); + if (err < 0) { + dev_err(sor->dev, "failed to get runtime PM: %d\n", err); + return err; + } + err = reset_control_acquire(sor->rst); if (err < 0) { dev_err(sor->dev, "failed to acquire SOR reset: %d\n", @@ -3148,6 +3154,7 @@ static int tegra_sor_init(struct host1x_client *client) } reset_control_release(sor->rst); + pm_runtime_put(sor->dev); } err = clk_prepare_enable(sor->clk_safe); From 3e759425cc3cf9a43392309819d34c65a3644c59 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Tue, 30 Mar 2021 20:49:32 +0200 Subject: [PATCH 0523/1091] ACPI: scan: Fix _STA getting called on devices with unmet dependencies Commit 71da201f38df ("ACPI: scan: Defer enumeration of devices with _DEP lists") dropped the following 2 lines from acpi_init_device_object(): /* Assume there are unmet deps until acpi_device_dep_initialize() runs */ device->dep_unmet = 1; Leaving the initial value of dep_unmet at the 0 from the kzalloc(). This causes the acpi_bus_get_status() call in acpi_add_single_object() to actually call _STA, even though there maybe unmet deps, leading to errors like these: [ 0.123579] ACPI Error: No handler for Region [ECRM] (00000000ba9edc4c) [GenericSerialBus] (20170831/evregion-166) [ 0.123601] ACPI Error: Region GenericSerialBus (ID=9) has no handler (20170831/exfldio-299) [ 0.123618] ACPI Error: Method parse/execution failed \_SB.I2C1.BAT1._STA, AE_NOT_EXIST (20170831/psparse-550) Fix this by re-adding the dep_unmet = 1 initialization to acpi_init_device_object() and modifying acpi_bus_check_add() to make sure that dep_unmet always gets setup there, overriding the initial 1 value. This re-fixes the issue initially fixed by commit 63347db0affa ("ACPI / scan: Use acpi_bus_get_status() to initialize ACPI_TYPE_DEVICE devs"), which introduced the removed "device->dep_unmet = 1;" statement. This issue was noticed; and the fix tested on a Dell Venue 10 Pro 5055. Fixes: 71da201f38df ("ACPI: scan: Defer enumeration of devices with _DEP lists") Suggested-by: Rafael J. Wysocki Signed-off-by: Hans de Goede Cc: 5.11+ # 5.11+ Signed-off-by: Rafael J. Wysocki --- drivers/acpi/scan.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c index 84bb7c1929f1..6efe7edd7b1e 100644 --- a/drivers/acpi/scan.c +++ b/drivers/acpi/scan.c @@ -1670,6 +1670,8 @@ void acpi_init_device_object(struct acpi_device *device, acpi_handle handle, device_initialize(&device->dev); dev_set_uevent_suppress(&device->dev, true); acpi_init_coherency(device); + /* Assume there are unmet deps to start with. */ + device->dep_unmet = 1; } void acpi_device_add_finalize(struct acpi_device *device) @@ -1933,6 +1935,8 @@ static void acpi_scan_dep_init(struct acpi_device *adev) { struct acpi_dep_data *dep; + adev->dep_unmet = 0; + mutex_lock(&acpi_dep_list_lock); list_for_each_entry(dep, &acpi_dep_list, node) { @@ -1980,7 +1984,13 @@ static acpi_status acpi_bus_check_add(acpi_handle handle, bool check_dep, return AE_CTRL_DEPTH; acpi_scan_init_hotplug(device); - if (!check_dep) + /* + * If check_dep is true at this point, the device has no dependencies, + * or the creation of the device object would have been postponed above. + */ + if (check_dep) + device->dep_unmet = 0; + else acpi_scan_dep_init(device); out: From 03cb4d05b4ea9a3491674ca40952adb708d549fa Mon Sep 17 00:00:00 2001 From: Milton Miller Date: Mon, 29 Mar 2021 10:20:39 -0500 Subject: [PATCH 0524/1091] net/ncsi: Avoid channel_monitor hrtimer deadlock Calling ncsi_stop_channel_monitor from channel_monitor is a guaranteed deadlock on SMP because stop calls del_timer_sync on the timer that invoked channel_monitor as its timer function. Recognise the inherent race of marking the monitor disabled before deleting the timer by just returning if enable was cleared. After a timeout (the default case -- reset to START when response received) just mark the monitor.enabled false. If the channel has an entry on the channel_queue list, or if the state is not ACTIVE or INACTIVE, then warn and mark the timer stopped and don't restart, as the locking is broken somehow. Fixes: 0795fb2021f0 ("net/ncsi: Stop monitor if channel times out or is inactive") Signed-off-by: Milton Miller Signed-off-by: Eddie James Signed-off-by: David S. Miller --- net/ncsi/ncsi-manage.c | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/net/ncsi/ncsi-manage.c b/net/ncsi/ncsi-manage.c index a9cb355324d1..ffff8da707b8 100644 --- a/net/ncsi/ncsi-manage.c +++ b/net/ncsi/ncsi-manage.c @@ -105,13 +105,20 @@ static void ncsi_channel_monitor(struct timer_list *t) monitor_state = nc->monitor.state; spin_unlock_irqrestore(&nc->lock, flags); - if (!enabled || chained) { - ncsi_stop_channel_monitor(nc); - return; - } + if (!enabled) + return; /* expected race disabling timer */ + if (WARN_ON_ONCE(chained)) + goto bad_state; + if (state != NCSI_CHANNEL_INACTIVE && state != NCSI_CHANNEL_ACTIVE) { - ncsi_stop_channel_monitor(nc); +bad_state: + netdev_warn(ndp->ndev.dev, + "Bad NCSI monitor state channel %d 0x%x %s queue\n", + nc->id, state, chained ? "on" : "off"); + spin_lock_irqsave(&nc->lock, flags); + nc->monitor.enabled = false; + spin_unlock_irqrestore(&nc->lock, flags); return; } @@ -136,10 +143,9 @@ static void ncsi_channel_monitor(struct timer_list *t) ncsi_report_link(ndp, true); ndp->flags |= NCSI_DEV_RESHUFFLE; - ncsi_stop_channel_monitor(nc); - ncm = &nc->modes[NCSI_MODE_LINK]; spin_lock_irqsave(&nc->lock, flags); + nc->monitor.enabled = false; nc->state = NCSI_CHANNEL_INVISIBLE; ncm->data[2] &= ~0x1; spin_unlock_irqrestore(&nc->lock, flags); From 6855e8213e06efcaf7c02a15e12b1ae64b9a7149 Mon Sep 17 00:00:00 2001 From: Kumar Kartikeya Dwivedi Date: Tue, 30 Mar 2021 04:23:23 +0530 Subject: [PATCH 0525/1091] net: sched: bump refcount for new action in ACT replace mode Currently, action creation using ACT API in replace mode is buggy. When invoking for non-existent action index 42, tc action replace action bpf obj foo.o sec index 42 kernel creates the action, fills up the netlink response, and then just deletes the action after notifying userspace. tc action show action bpf doesn't list the action. This happens due to the following sequence when ovr = 1 (replace mode) is enabled: tcf_idr_check_alloc is used to atomically check and either obtain reference for existing action at index, or reserve the index slot using a dummy entry (ERR_PTR(-EBUSY)). This is necessary as pointers to these actions will be held after dropping the idrinfo lock, so bumping the reference count is necessary as we need to insert the actions, and notify userspace by dumping their attributes. Finally, we drop the reference we took using the tcf_action_put_many call in tcf_action_add. However, for the case where a new action is created due to free index, its refcount remains one. This when paired with the put_many call leads to the kernel setting up the action, notifying userspace of its creation, and then tearing it down. For existing actions, the refcount is still held so they remain unaffected. Fortunately due to rtnl_lock serialization requirement, such an action with refcount == 1 will not be concurrently deleted by anything else, at best CLS API can move its refcount up and down by binding to it after it has been published from tcf_idr_insert_many. Since refcount is atleast one until put_many call, CLS API cannot delete it. Also __tcf_action_put release path already ensures deterministic outcome (either new action will be created or existing action will be reused in case CLS API tries to bind to action concurrently) due to idr lock serialization. We fix this by making refcount of newly created actions as 2 in ACT API replace mode. A relaxed store will suffice as visibility is ensured only after the tcf_idr_insert_many call. Note that in case of creation or overwriting using CLS API only (i.e. bind = 1), overwriting existing action object is not allowed, and any such request is silently ignored (without error). The refcount bump that occurs in tcf_idr_check_alloc call there for existing action will pair with tcf_exts_destroy call made from the owner module for the same action. In case of action creation, there is no existing action, so no tcf_exts_destroy callback happens. This means no code changes for CLS API. Fixes: cae422f379f3 ("net: sched: use reference counting action init") Signed-off-by: Kumar Kartikeya Dwivedi Signed-off-by: David S. Miller --- net/sched/act_api.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index b919826939e0..43cceb924976 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -1042,6 +1042,9 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, if (err != ACT_P_CREATED) module_put(a_o->owner); + if (!bind && ovr && err == ACT_P_CREATED) + refcount_set(&a->tcfa_refcnt, 2); + return a; err_out: From 82734c5b1b24c020d701cf90ccb075e43a5ccb07 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Mon, 29 Mar 2021 06:52:44 -0600 Subject: [PATCH 0526/1091] io_uring: drop sqd lock before handling signals for SQPOLL Don't call into get_signal() with the sqd mutex held, it'll fail if we're freezing the task and we'll get complaints on locks still being held: ==================================== WARNING: iou-sqp-8386/8387 still has locks held! 5.12.0-rc4-syzkaller #0 Not tainted ------------------------------------ 1 lock held by iou-sqp-8386/8387: #0: ffff88801e1d2470 (&sqd->lock){+.+.}-{3:3}, at: io_sq_thread+0x24c/0x13a0 fs/io_uring.c:6731 stack backtrace: CPU: 1 PID: 8387 Comm: iou-sqp-8386 Not tainted 5.12.0-rc4-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x141/0x1d7 lib/dump_stack.c:120 try_to_freeze include/linux/freezer.h:66 [inline] get_signal+0x171a/0x2150 kernel/signal.c:2576 io_sq_thread+0x8d2/0x13a0 fs/io_uring.c:6748 Fold the get_signal() case in with the parking checks, as we need to drop the lock in both cases, and since we need to be checking for parking when juggling the lock anyway. Reported-by: syzbot+796d767eb376810256f5@syzkaller.appspotmail.com Fixes: dbe1bdbb39db ("io_uring: handle signals for IO threads like a normal thread") Signed-off-by: Jens Axboe --- fs/io_uring.c | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 088a9d3c420a..6d7a1b69712b 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -6733,22 +6733,25 @@ static int io_sq_thread(void *data) int ret; bool cap_entries, sqt_spin, needs_sched; - if (test_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state)) { + if (test_bit(IO_SQ_THREAD_SHOULD_PARK, &sqd->state) || + signal_pending(current)) { + bool did_sig = false; + mutex_unlock(&sqd->lock); + if (signal_pending(current)) { + struct ksignal ksig; + + did_sig = get_signal(&ksig); + } cond_resched(); mutex_lock(&sqd->lock); + if (did_sig) + break; io_run_task_work(); io_run_task_work_head(&sqd->park_task_work); timeout = jiffies + sqd->sq_thread_idle; continue; } - if (signal_pending(current)) { - struct ksignal ksig; - - if (!get_signal(&ksig)) - continue; - break; - } sqt_spin = false; cap_entries = !list_is_singular(&sqd->ctx_list); list_for_each_entry(ctx, &sqd->ctx_list, sqd_list) { From 8a03dd925786bdc3834d56ccc980bb70668efa35 Mon Sep 17 00:00:00 2001 From: Loic Poulain Date: Tue, 30 Mar 2021 16:11:08 +0200 Subject: [PATCH 0527/1091] net: qrtr: Fix memory leak on qrtr_tx_wait failure qrtr_tx_wait does not check for radix_tree_insert failure, causing the 'flow' object to be unreferenced after qrtr_tx_wait return. Fix that by releasing flow on radix_tree_insert failure. Fixes: 5fdeb0d372ab ("net: qrtr: Implement outgoing flow control") Reported-by: syzbot+739016799a89c530b32a@syzkaller.appspotmail.com Signed-off-by: Loic Poulain Reviewed-by: Bjorn Andersson Reviewed-by: Manivannan Sadhasivam Signed-off-by: David S. Miller --- net/qrtr/qrtr.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index dfc820ee553a..1e4fb568fa84 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -271,7 +271,10 @@ static int qrtr_tx_wait(struct qrtr_node *node, int dest_node, int dest_port, flow = kzalloc(sizeof(*flow), GFP_KERNEL); if (flow) { init_waitqueue_head(&flow->resume_tx); - radix_tree_insert(&node->qrtr_tx_flow, key, flow); + if (radix_tree_insert(&node->qrtr_tx_flow, key, flow)) { + kfree(flow); + flow = NULL; + } } } mutex_unlock(&node->qrtr_tx_lock); From ae81feb7338c89cee4e6aa0424bdab2ce2b52da2 Mon Sep 17 00:00:00 2001 From: Yunjian Wang Date: Tue, 30 Mar 2021 22:27:48 +0800 Subject: [PATCH 0528/1091] sch_htb: fix null pointer dereference on a null new_q sch_htb: fix null pointer dereference on a null new_q Currently if new_q is null, the null new_q pointer will be dereference when 'q->offload' is true. Fix this by adding a braces around htb_parent_to_leaf_offload() to avoid it. Addresses-Coverity: ("Dereference after null check") Fixes: d03b195b5aa0 ("sch_htb: Hierarchical QoS hardware offload") Signed-off-by: Yunjian Wang Signed-off-by: David S. Miller --- net/sched/sch_htb.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/net/sched/sch_htb.c b/net/sched/sch_htb.c index 62e12cb41a3e..081c11d5717c 100644 --- a/net/sched/sch_htb.c +++ b/net/sched/sch_htb.c @@ -1675,9 +1675,10 @@ static int htb_delete(struct Qdisc *sch, unsigned long arg, cl->parent->common.classid, NULL); if (q->offload) { - if (new_q) + if (new_q) { htb_set_lockdep_class_child(new_q); - htb_parent_to_leaf_offload(sch, dev_queue, new_q); + htb_parent_to_leaf_offload(sch, dev_queue, new_q); + } } } From 9adc89af724f12a03b47099cd943ed54e877cd59 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Tue, 30 Mar 2021 18:43:54 +0200 Subject: [PATCH 0529/1091] net: let skb_orphan_partial wake-up waiters. Currently the mentioned helper can end-up freeing the socket wmem without waking-up any processes waiting for more write memory. If the partially orphaned skb is attached to an UDP (or raw) socket, the lack of wake-up can hang the user-space. Even for TCP sockets not calling the sk destructor could have bad effects on TSQ. Address the issue using skb_orphan to release the sk wmem before setting the new sock_efree destructor. Additionally bundle the whole ownership update in a new helper, so that later other potential users could avoid duplicate code. v1 -> v2: - use skb_orphan() instead of sort of open coding it (Eric) - provide an helper for the ownership change (Eric) Fixes: f6ba8d33cfbb ("netem: fix skb_orphan_partial()") Suggested-by: Eric Dumazet Signed-off-by: Paolo Abeni Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sock.h | 9 +++++++++ net/core/sock.c | 12 +++--------- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/include/net/sock.h b/include/net/sock.h index 0b6266fd6bf6..3e3a5da2ce5a 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -2221,6 +2221,15 @@ static inline void skb_set_owner_r(struct sk_buff *skb, struct sock *sk) sk_mem_charge(sk, skb->truesize); } +static inline void skb_set_owner_sk_safe(struct sk_buff *skb, struct sock *sk) +{ + if (sk && refcount_inc_not_zero(&sk->sk_refcnt)) { + skb_orphan(skb); + skb->destructor = sock_efree; + skb->sk = sk; + } +} + void sk_reset_timer(struct sock *sk, struct timer_list *timer, unsigned long expires); diff --git a/net/core/sock.c b/net/core/sock.c index cc31b601ae10..5ec90f99e102 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -2132,16 +2132,10 @@ void skb_orphan_partial(struct sk_buff *skb) if (skb_is_tcp_pure_ack(skb)) return; - if (can_skb_orphan_partial(skb)) { - struct sock *sk = skb->sk; - - if (refcount_inc_not_zero(&sk->sk_refcnt)) { - WARN_ON(refcount_sub_and_test(skb->truesize, &sk->sk_wmem_alloc)); - skb->destructor = sock_efree; - } - } else { + if (can_skb_orphan_partial(skb)) + skb_set_owner_sk_safe(skb, skb->sk); + else skb_orphan(skb); - } } EXPORT_SYMBOL(skb_orphan_partial); From 5e46d1b78a03d52306f21f77a4e4a144b6d31486 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Sun, 21 Mar 2021 23:37:49 +0900 Subject: [PATCH 0530/1091] reiserfs: update reiserfs_xattrs_initialized() condition syzbot is reporting NULL pointer dereference at reiserfs_security_init() [1], for commit ab17c4f02156c4f7 ("reiserfs: fixup xattr_root caching") is assuming that REISERFS_SB(s)->xattr_root != NULL in reiserfs_xattr_jcreate_nblocks() despite that commit made REISERFS_SB(sb)->priv_root != NULL && REISERFS_SB(s)->xattr_root == NULL case possible. I guess that commit 6cb4aff0a77cc0e6 ("reiserfs: fix oops while creating privroot with selinux enabled") wanted to check xattr_root != NULL before reiserfs_xattr_jcreate_nblocks(), for the changelog is talking about the xattr root. The issue is that while creating the privroot during mount reiserfs_security_init calls reiserfs_xattr_jcreate_nblocks which dereferences the xattr root. The xattr root doesn't exist, so we get an oops. Therefore, update reiserfs_xattrs_initialized() to check both the privroot and the xattr root. Link: https://syzkaller.appspot.com/bug?id=8abaedbdeb32c861dc5340544284167dd0e46cde # [1] Reported-and-tested-by: syzbot Signed-off-by: Tetsuo Handa Fixes: 6cb4aff0a77c ("reiserfs: fix oops while creating privroot with selinux enabled") Acked-by: Jeff Mahoney Acked-by: Jan Kara Signed-off-by: Linus Torvalds --- fs/reiserfs/xattr.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/reiserfs/xattr.h b/fs/reiserfs/xattr.h index 9b3b06da568c..e47fde1182de 100644 --- a/fs/reiserfs/xattr.h +++ b/fs/reiserfs/xattr.h @@ -44,7 +44,7 @@ void reiserfs_security_free(struct reiserfs_security_handle *sec); static inline int reiserfs_xattrs_initialized(struct super_block *sb) { - return REISERFS_SB(sb)->priv_root != NULL; + return REISERFS_SB(sb)->priv_root && REISERFS_SB(sb)->xattr_root; } #define xattr_size(size) ((size) + sizeof(struct reiserfs_xattr_header)) From 0e07e25b481aa021e4b48085ecb8a049e9614510 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Tue, 30 Mar 2021 16:24:11 +0200 Subject: [PATCH 0531/1091] netfilter: flowtable: fix NAT IPv6 offload mangling Fix out-of-bound access in the address array. Fixes: 5c27d8d76ce8 ("netfilter: nf_flow_table_offload: add IPv6 support") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_flow_table_offload.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/netfilter/nf_flow_table_offload.c b/net/netfilter/nf_flow_table_offload.c index 2a6993fa40d7..1c5460e7bce8 100644 --- a/net/netfilter/nf_flow_table_offload.c +++ b/net/netfilter/nf_flow_table_offload.c @@ -305,12 +305,12 @@ static void flow_offload_ipv6_mangle(struct nf_flow_rule *flow_rule, const __be32 *addr, const __be32 *mask) { struct flow_action_entry *entry; - int i; + int i, j; - for (i = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32)) { + for (i = 0, j = 0; i < sizeof(struct in6_addr) / sizeof(u32); i += sizeof(u32), j++) { entry = flow_action_entry_next(flow_rule); flow_offload_mangle(entry, FLOW_ACT_MANGLE_HDR_TYPE_IP6, - offset + i, &addr[i], mask); + offset + i, &addr[j], mask); } } From fbea31808ca124dd73ff6bb1e67c9af4607c3e32 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Wed, 31 Mar 2021 01:04:45 +0200 Subject: [PATCH 0532/1091] netfilter: conntrack: do not print icmpv6 as unknown via /proc /proc/net/nf_conntrack shows icmpv6 as unknown. Fixes: 09ec82f5af99 ("netfilter: conntrack: remove protocol name from l4proto struct") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_conntrack_standalone.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/netfilter/nf_conntrack_standalone.c b/net/netfilter/nf_conntrack_standalone.c index 0ee702d374b0..c6c0cb465664 100644 --- a/net/netfilter/nf_conntrack_standalone.c +++ b/net/netfilter/nf_conntrack_standalone.c @@ -266,6 +266,7 @@ static const char* l4proto_name(u16 proto) case IPPROTO_GRE: return "gre"; case IPPROTO_SCTP: return "sctp"; case IPPROTO_UDPLITE: return "udplite"; + case IPPROTO_ICMPV6: return "icmpv6"; } return "unknown"; From 2ea538dbee1c79f6f6c24a6f2f82986e4b7ccb78 Mon Sep 17 00:00:00 2001 From: Yinjun Zhang Date: Tue, 30 Mar 2021 10:30:23 +0200 Subject: [PATCH 0533/1091] nfp: flower: ignore duplicate merge hints from FW A merge hint message needs some time to process before the merged flow actually reaches the firmware, during which we may get duplicate merge hints if there're more than one packet that hit the pre-merged flow. And processing duplicate merge hints will cost extra host_ctx's which are a limited resource. Avoid the duplicate merge by using hash table to store the sub_flows to be merged. Fixes: 8af56f40e53b ("nfp: flower: offload merge flows") Signed-off-by: Yinjun Zhang Signed-off-by: Louis Peens Signed-off-by: Simon Horman Signed-off-by: David S. Miller --- .../net/ethernet/netronome/nfp/flower/main.h | 8 ++++ .../ethernet/netronome/nfp/flower/metadata.c | 16 ++++++- .../ethernet/netronome/nfp/flower/offload.c | 48 ++++++++++++++++++- 3 files changed, 69 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/netronome/nfp/flower/main.h b/drivers/net/ethernet/netronome/nfp/flower/main.h index caf12eec9945..56833a41f3d2 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/main.h +++ b/drivers/net/ethernet/netronome/nfp/flower/main.h @@ -190,6 +190,7 @@ struct nfp_fl_internal_ports { * @qos_rate_limiters: Current active qos rate limiters * @qos_stats_lock: Lock on qos stats updates * @pre_tun_rule_cnt: Number of pre-tunnel rules offloaded + * @merge_table: Hash table to store merged flows */ struct nfp_flower_priv { struct nfp_app *app; @@ -223,6 +224,7 @@ struct nfp_flower_priv { unsigned int qos_rate_limiters; spinlock_t qos_stats_lock; /* Protect the qos stats */ int pre_tun_rule_cnt; + struct rhashtable merge_table; }; /** @@ -350,6 +352,12 @@ struct nfp_fl_payload_link { }; extern const struct rhashtable_params nfp_flower_table_params; +extern const struct rhashtable_params merge_table_params; + +struct nfp_merge_info { + u64 parent_ctx; + struct rhash_head ht_node; +}; struct nfp_fl_stats_frame { __be32 stats_con_id; diff --git a/drivers/net/ethernet/netronome/nfp/flower/metadata.c b/drivers/net/ethernet/netronome/nfp/flower/metadata.c index aa06fcb38f8b..327bb56b3ef5 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/metadata.c +++ b/drivers/net/ethernet/netronome/nfp/flower/metadata.c @@ -490,6 +490,12 @@ const struct rhashtable_params nfp_flower_table_params = { .automatic_shrinking = true, }; +const struct rhashtable_params merge_table_params = { + .key_offset = offsetof(struct nfp_merge_info, parent_ctx), + .head_offset = offsetof(struct nfp_merge_info, ht_node), + .key_len = sizeof(u64), +}; + int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, unsigned int host_num_mems) { @@ -506,6 +512,10 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, if (err) goto err_free_flow_table; + err = rhashtable_init(&priv->merge_table, &merge_table_params); + if (err) + goto err_free_stats_ctx_table; + get_random_bytes(&priv->mask_id_seed, sizeof(priv->mask_id_seed)); /* Init ring buffer and unallocated mask_ids. */ @@ -513,7 +523,7 @@ int nfp_flower_metadata_init(struct nfp_app *app, u64 host_ctx_count, kmalloc_array(NFP_FLOWER_MASK_ENTRY_RS, NFP_FLOWER_MASK_ELEMENT_RS, GFP_KERNEL); if (!priv->mask_ids.mask_id_free_list.buf) - goto err_free_stats_ctx_table; + goto err_free_merge_table; priv->mask_ids.init_unallocated = NFP_FLOWER_MASK_ENTRY_RS - 1; @@ -550,6 +560,8 @@ err_free_last_used: kfree(priv->mask_ids.last_used); err_free_mask_id: kfree(priv->mask_ids.mask_id_free_list.buf); +err_free_merge_table: + rhashtable_destroy(&priv->merge_table); err_free_stats_ctx_table: rhashtable_destroy(&priv->stats_ctx_table); err_free_flow_table: @@ -568,6 +580,8 @@ void nfp_flower_metadata_cleanup(struct nfp_app *app) nfp_check_rhashtable_empty, NULL); rhashtable_free_and_destroy(&priv->stats_ctx_table, nfp_check_rhashtable_empty, NULL); + rhashtable_free_and_destroy(&priv->merge_table, + nfp_check_rhashtable_empty, NULL); kvfree(priv->stats); kfree(priv->mask_ids.mask_id_free_list.buf); kfree(priv->mask_ids.last_used); diff --git a/drivers/net/ethernet/netronome/nfp/flower/offload.c b/drivers/net/ethernet/netronome/nfp/flower/offload.c index d72225d64a75..e95969c462e4 100644 --- a/drivers/net/ethernet/netronome/nfp/flower/offload.c +++ b/drivers/net/ethernet/netronome/nfp/flower/offload.c @@ -1009,6 +1009,8 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, struct netlink_ext_ack *extack = NULL; struct nfp_fl_payload *merge_flow; struct nfp_fl_key_ls merge_key_ls; + struct nfp_merge_info *merge_info; + u64 parent_ctx = 0; int err; ASSERT_RTNL(); @@ -1019,6 +1021,15 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, nfp_flower_is_merge_flow(sub_flow2)) return -EINVAL; + /* check if the two flows are already merged */ + parent_ctx = (u64)(be32_to_cpu(sub_flow1->meta.host_ctx_id)) << 32; + parent_ctx |= (u64)(be32_to_cpu(sub_flow2->meta.host_ctx_id)); + if (rhashtable_lookup_fast(&priv->merge_table, + &parent_ctx, merge_table_params)) { + nfp_flower_cmsg_warn(app, "The two flows are already merged.\n"); + return 0; + } + err = nfp_flower_can_merge(sub_flow1, sub_flow2); if (err) return err; @@ -1060,16 +1071,33 @@ int nfp_flower_merge_offloaded_flows(struct nfp_app *app, if (err) goto err_release_metadata; + merge_info = kmalloc(sizeof(*merge_info), GFP_KERNEL); + if (!merge_info) { + err = -ENOMEM; + goto err_remove_rhash; + } + merge_info->parent_ctx = parent_ctx; + err = rhashtable_insert_fast(&priv->merge_table, &merge_info->ht_node, + merge_table_params); + if (err) + goto err_destroy_merge_info; + err = nfp_flower_xmit_flow(app, merge_flow, NFP_FLOWER_CMSG_TYPE_FLOW_MOD); if (err) - goto err_remove_rhash; + goto err_remove_merge_info; merge_flow->in_hw = true; sub_flow1->in_hw = false; return 0; +err_remove_merge_info: + WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table, + &merge_info->ht_node, + merge_table_params)); +err_destroy_merge_info: + kfree(merge_info); err_remove_rhash: WARN_ON_ONCE(rhashtable_remove_fast(&priv->flow_table, &merge_flow->fl_node, @@ -1359,7 +1387,9 @@ nfp_flower_remove_merge_flow(struct nfp_app *app, { struct nfp_flower_priv *priv = app->priv; struct nfp_fl_payload_link *link, *temp; + struct nfp_merge_info *merge_info; struct nfp_fl_payload *origin; + u64 parent_ctx = 0; bool mod = false; int err; @@ -1396,8 +1426,22 @@ nfp_flower_remove_merge_flow(struct nfp_app *app, err_free_links: /* Clean any links connected with the merged flow. */ list_for_each_entry_safe(link, temp, &merge_flow->linked_flows, - merge_flow.list) + merge_flow.list) { + u32 ctx_id = be32_to_cpu(link->sub_flow.flow->meta.host_ctx_id); + + parent_ctx = (parent_ctx << 32) | (u64)(ctx_id); nfp_flower_unlink_flow(link); + } + + merge_info = rhashtable_lookup_fast(&priv->merge_table, + &parent_ctx, + merge_table_params); + if (merge_info) { + WARN_ON_ONCE(rhashtable_remove_fast(&priv->merge_table, + &merge_info->ht_node, + merge_table_params)); + kfree(merge_info); + } kfree(merge_flow->action_data); kfree(merge_flow->mask_data); From c056d480b40a68f2520ccc156c7fae672d69d57d Mon Sep 17 00:00:00 2001 From: Florian Fainelli Date: Tue, 30 Mar 2021 15:00:24 -0700 Subject: [PATCH 0534/1091] net: phy: broadcom: Only advertise EEE for supported modes We should not be advertising EEE for modes that we do not support, correct that oversight by looking at the PHY device supported linkmodes. Fixes: 99cec8a4dda2 ("net: phy: broadcom: Allow enabling or disabling of EEE") Signed-off-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/phy/bcm-phy-lib.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/drivers/net/phy/bcm-phy-lib.c b/drivers/net/phy/bcm-phy-lib.c index 53282a6d5928..287cccf8f7f4 100644 --- a/drivers/net/phy/bcm-phy-lib.c +++ b/drivers/net/phy/bcm-phy-lib.c @@ -369,7 +369,7 @@ EXPORT_SYMBOL_GPL(bcm_phy_enable_apd); int bcm_phy_set_eee(struct phy_device *phydev, bool enable) { - int val; + int val, mask = 0; /* Enable EEE at PHY level */ val = phy_read_mmd(phydev, MDIO_MMD_AN, BRCM_CL45VEN_EEE_CONTROL); @@ -388,10 +388,17 @@ int bcm_phy_set_eee(struct phy_device *phydev, bool enable) if (val < 0) return val; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_1000baseT_Full_BIT, + phydev->supported)) + mask |= MDIO_EEE_1000T; + if (linkmode_test_bit(ETHTOOL_LINK_MODE_100baseT_Full_BIT, + phydev->supported)) + mask |= MDIO_EEE_100TX; + if (enable) - val |= (MDIO_EEE_100TX | MDIO_EEE_1000T); + val |= mask; else - val &= ~(MDIO_EEE_100TX | MDIO_EEE_1000T); + val &= ~mask; phy_write_mmd(phydev, MDIO_MMD_AN, BCM_CL45VEN_EEE_ADV, (u32)val); From 61431a5907fc36d0738e9a547c7e1556349a03e9 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 30 Mar 2021 16:43:43 -0700 Subject: [PATCH 0535/1091] net: ensure mac header is set in virtio_net_hdr_to_skb() Commit 924a9bc362a5 ("net: check if protocol extracted by virtio_net_hdr_set_proto is correct") added a call to dev_parse_header_protocol() but mac_header is not yet set. This means that eth_hdr() reads complete garbage, and syzbot complained about it [1] This patch resets mac_header earlier, to get more coverage about this change. Audit of virtio_net_hdr_to_skb() callers shows that this change should be safe. [1] BUG: KASAN: use-after-free in eth_header_parse_protocol+0xdc/0xe0 net/ethernet/eth.c:282 Read of size 2 at addr ffff888017a6200b by task syz-executor313/8409 CPU: 1 PID: 8409 Comm: syz-executor313 Not tainted 5.12.0-rc2-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 Call Trace: __dump_stack lib/dump_stack.c:79 [inline] dump_stack+0x141/0x1d7 lib/dump_stack.c:120 print_address_description.constprop.0.cold+0x5b/0x2f8 mm/kasan/report.c:232 __kasan_report mm/kasan/report.c:399 [inline] kasan_report.cold+0x7c/0xd8 mm/kasan/report.c:416 eth_header_parse_protocol+0xdc/0xe0 net/ethernet/eth.c:282 dev_parse_header_protocol include/linux/netdevice.h:3177 [inline] virtio_net_hdr_to_skb.constprop.0+0x99d/0xcd0 include/linux/virtio_net.h:83 packet_snd net/packet/af_packet.c:2994 [inline] packet_sendmsg+0x2325/0x52b0 net/packet/af_packet.c:3031 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 sock_no_sendpage+0xf3/0x130 net/core/sock.c:2860 kernel_sendpage.part.0+0x1ab/0x350 net/socket.c:3631 kernel_sendpage net/socket.c:3628 [inline] sock_sendpage+0xe5/0x140 net/socket.c:947 pipe_to_sendpage+0x2ad/0x380 fs/splice.c:364 splice_from_pipe_feed fs/splice.c:418 [inline] __splice_from_pipe+0x43e/0x8a0 fs/splice.c:562 splice_from_pipe fs/splice.c:597 [inline] generic_splice_sendpage+0xd4/0x140 fs/splice.c:746 do_splice_from fs/splice.c:767 [inline] do_splice+0xb7e/0x1940 fs/splice.c:1079 __do_splice+0x134/0x250 fs/splice.c:1144 __do_sys_splice fs/splice.c:1350 [inline] __se_sys_splice fs/splice.c:1332 [inline] __x64_sys_splice+0x198/0x250 fs/splice.c:1332 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 Fixes: 924a9bc362a5 ("net: check if protocol extracted by virtio_net_hdr_set_proto is correct") Signed-off-by: Eric Dumazet Cc: Balazs Nemeth Cc: Willem de Bruijn Reported-by: syzbot Signed-off-by: David S. Miller --- include/linux/virtio_net.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 6b5fcfa1e555..98775d7fa696 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -62,6 +62,8 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, return -EINVAL; } + skb_reset_mac_header(skb); + if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); From fc85dc42a38405099f97aa2af709fe9504a82508 Mon Sep 17 00:00:00 2001 From: Tony Lindgren Date: Wed, 31 Mar 2021 09:27:41 +0300 Subject: [PATCH 0536/1091] ARM: OMAP2+: Fix uninitialized sr_inst Fix uninitialized sr_inst. Fixes: fbfa463be8dc ("ARM: OMAP2+: Fix smartreflex init regression after dropping legacy data") Reported-by: kernel test robot Signed-off-by: Tony Lindgren --- arch/arm/mach-omap2/sr_device.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/arm/mach-omap2/sr_device.c b/arch/arm/mach-omap2/sr_device.c index 17b66f0d0dee..605925684b0a 100644 --- a/arch/arm/mach-omap2/sr_device.c +++ b/arch/arm/mach-omap2/sr_device.c @@ -188,7 +188,7 @@ static const char * const dra7_sr_instances[] = { int __init omap_devinit_smartreflex(void) { - const char * const *sr_inst; + const char * const *sr_inst = NULL; int i, nr_sr = 0; if (soc_is_omap44xx()) { From 942bfbecc0281c75db84f744b9b77b0f2396f484 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=91=A8=E7=90=B0=E6=9D=B0=20=28Zhou=20Yanjie=29?= Date: Fri, 19 Mar 2021 18:12:13 +0800 Subject: [PATCH 0537/1091] I2C: JZ4780: Fix bug for Ingenic X1000. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Only send "X1000_I2C_DC_STOP" when last byte, or it will cause error when I2C write operation which should look like this: device_addr + w, reg_addr, data; But without this patch, it looks like this: device_addr + w, reg_addr, device_addr + w, data; Fixes: 21575a7a8d4c ("I2C: JZ4780: Add support for the X1000.") Reported-by: 杨文龙 (Yang Wenlong) Tested-by: 杨文龙 (Yang Wenlong) Signed-off-by: 周琰杰 (Zhou Yanjie) Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-jz4780.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-jz4780.c b/drivers/i2c/busses/i2c-jz4780.c index 8509c5f11356..55177eb21d7b 100644 --- a/drivers/i2c/busses/i2c-jz4780.c +++ b/drivers/i2c/busses/i2c-jz4780.c @@ -525,8 +525,8 @@ static irqreturn_t jz4780_i2c_irq(int irqno, void *dev_id) i2c_sta = jz4780_i2c_readw(i2c, JZ4780_I2C_STA); data = *i2c->wbuf; data &= ~JZ4780_I2C_DC_READ; - if ((!i2c->stop_hold) && (i2c->cdata->version >= - ID_X1000)) + if ((i2c->wt_len == 1) && (!i2c->stop_hold) && + (i2c->cdata->version >= ID_X1000)) data |= X1000_I2C_DC_STOP; jz4780_i2c_writew(i2c, JZ4780_I2C_DC, data); i2c->wbuf++; From 67ff1d98652ac141f46b3871ebc34350ddffa2ef Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Wed, 24 Mar 2021 19:36:10 +0530 Subject: [PATCH 0538/1091] i2c: stm32f4: Mundane typo fix s/postion/position/ Signed-off-by: Bhaskar Chowdhury Acked-by: Randy Dunlap Reviewed-by: Alain Volmat Reviewed-by: Pierre-Yves MORDRET Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-stm32f4.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-stm32f4.c b/drivers/i2c/busses/i2c-stm32f4.c index 937c2c8fd349..4933fc8ce3fd 100644 --- a/drivers/i2c/busses/i2c-stm32f4.c +++ b/drivers/i2c/busses/i2c-stm32f4.c @@ -534,7 +534,7 @@ static void stm32f4_i2c_handle_rx_addr(struct stm32f4_i2c_dev *i2c_dev) default: /* * N-byte reception: - * Enable ACK, reset POS (ACK postion) and clear ADDR flag. + * Enable ACK, reset POS (ACK position) and clear ADDR flag. * In that way, ACK will be sent as soon as the current byte * will be received in the shift register */ From 1ae6b3780848c6b1efc6b994963082cfd04ac114 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 29 Mar 2021 21:24:09 +0200 Subject: [PATCH 0539/1091] i2c: imx: drop me as maintainer of binding docs I dunno why I got added here, but I haven't been using this driver for years. Remove me to make space for interested parties. Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-imx.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx.yaml index f23966b0d6c6..f33c6b29966b 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-imx.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-imx.yaml @@ -6,9 +6,6 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX -maintainers: - - Wolfram Sang - allOf: - $ref: /schemas/i2c/i2c-controller.yaml# From 98a479991dc5b986d9d48a1b73f568e58e3d82b6 Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Mon, 29 Mar 2021 21:25:41 +0200 Subject: [PATCH 0540/1091] i2c: gpio: update email address in binding docs Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-gpio.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/i2c/i2c-gpio.yaml b/Documentation/devicetree/bindings/i2c/i2c-gpio.yaml index ff99344788ab..fd040284561f 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-gpio.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-gpio.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Bindings for GPIO bitbanged I2C maintainers: - - Wolfram Sang + - Wolfram Sang allOf: - $ref: /schemas/i2c/i2c-controller.yaml# From 629a411f7e71afeee34edd4c1418c4e7f7d5575a Mon Sep 17 00:00:00 2001 From: Hao Fang Date: Tue, 30 Mar 2021 14:37:14 +0800 Subject: [PATCH 0541/1091] i2c: hix5hd2: use the correct HiSilicon copyright s/Hisilicon/HiSilicon/g. It should use capital S, according to https://www.hisilicon.com/en/terms-of-use. Signed-off-by: Hao Fang Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-hix5hd2.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-hix5hd2.c b/drivers/i2c/busses/i2c-hix5hd2.c index c45f226c2b85..aa00ba8bcb70 100644 --- a/drivers/i2c/busses/i2c-hix5hd2.c +++ b/drivers/i2c/busses/i2c-hix5hd2.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* * Copyright (c) 2014 Linaro Ltd. - * Copyright (c) 2014 Hisilicon Limited. + * Copyright (c) 2014 HiSilicon Limited. * * Now only support 7 bit address. */ From 89503d736e3631bda906c627d1092dc8e76ddfd9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Mar 2021 12:25:57 +0900 Subject: [PATCH 0542/1091] ASoC: simple-card-utils.c: remove old comment commit adb76b5b9c474 ("ASoC: soc-core: remove legacy style dai_link") removed snd_soc_init_multicodec(). The comment on asoc_simple_init_priv() is no longer needed. This patch removes it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87czvm1tq2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 06c2512b6f2d..6897455219d1 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -617,11 +617,6 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, } /* - * Use snd_soc_dai_link_component instead of legacy style - * It is codec only. but cpu/platform will be supported in the future. - * see - * soc-core.c :: snd_soc_init_multicodec() - * * "platform" might be removed * see * simple-card-utils.c :: asoc_simple_canonicalize_platform() From 050c7950fd706fec229af9f30e8ce254cea9b675 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Mar 2021 12:26:06 +0900 Subject: [PATCH 0543/1091] ASoC: simple-card-utils: alloc dai_link information for CPU/Codec/Platform simple-card / audio-graph are assuming single CPU/Codec/Platform on dai_link. Because of it, it is difficult to support Multi-CPU/Codec. This patch allocs CPU/Codec/Platform dai_link imformation instead of using existing props information. It can update to multi-CPU/Codec, but is still assuming single-CPU/Codec for now. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87blb61tpv.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 7 ++++--- sound/soc/generic/simple-card-utils.c | 15 +++++++++++---- 2 files changed, 15 insertions(+), 7 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index ba4a3e1897b9..86e46cbf9e14 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -43,9 +43,9 @@ struct asoc_simple_priv { struct simple_dai_props { struct asoc_simple_dai *cpu_dai; struct asoc_simple_dai *codec_dai; - struct snd_soc_dai_link_component cpus; /* single cpu */ - struct snd_soc_dai_link_component codecs; /* single codec */ - struct snd_soc_dai_link_component platforms; + struct snd_soc_dai_link_component *cpus; + struct snd_soc_dai_link_component *codecs; + struct snd_soc_dai_link_component *platforms; struct asoc_simple_data adata; struct snd_soc_codec_conf *codec_conf; unsigned int mclk_fs; @@ -54,6 +54,7 @@ struct asoc_simple_priv { struct asoc_simple_jack mic_jack; struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dais; + struct snd_soc_dai_link_component *dlcs; struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; const struct snd_soc_ops *ops; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 6897455219d1..f05954529dfc 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -601,13 +601,15 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct snd_soc_dai_link *dai_link; struct simple_dai_props *dai_props; struct asoc_simple_dai *dais; + struct snd_soc_dai_link_component *dlcs; struct snd_soc_codec_conf *cconf = NULL; int i; dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL); dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL); dais = devm_kcalloc(dev, li->dais, sizeof(*dais), GFP_KERNEL); - if (!dai_props || !dai_link || !dais) + dlcs = devm_kcalloc(dev, li->link * 3, sizeof(*dai_props), GFP_KERNEL); + if (!dai_props || !dai_link || !dais || !dlcs) return -ENOMEM; if (li->conf) { @@ -622,17 +624,22 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, * simple-card-utils.c :: asoc_simple_canonicalize_platform() */ for (i = 0; i < li->link; i++) { - dai_link[i].cpus = &dai_props[i].cpus; + dai_props[i].cpus = dlcs + (3 * i) + 0; + dai_props[i].codecs = dlcs + (3 * i) + 1; + dai_props[i].platforms = dlcs + (3 * i) + 2; + + dai_link[i].cpus = dai_props[i].cpus; dai_link[i].num_cpus = 1; - dai_link[i].codecs = &dai_props[i].codecs; + dai_link[i].codecs = dai_props[i].codecs; dai_link[i].num_codecs = 1; - dai_link[i].platforms = &dai_props[i].platforms; + dai_link[i].platforms = dai_props[i].platforms; dai_link[i].num_platforms = 1; } priv->dai_props = dai_props; priv->dai_link = dai_link; priv->dais = dais; + priv->dlcs = dlcs; priv->codec_conf = cconf; card->dai_link = priv->dai_link; From 674b9438e2d4c44f45af2a38521767c06c46eacb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Mar 2021 12:26:11 +0900 Subject: [PATCH 0544/1091] ASoC: audio-graph: count DAI / link numbers as in order audio-graph checks DT links 2 times. 1st is for counting DAIs / links to allocating memory, 2nd is for detecting DAIs. To detecting DAIs as CPU-dummy -> dummy-Codec order when DPCM case, it uses loops 2 times at 2nd DT link check. But it doesn't do it at 1st DT link check. for (li.cpu = 1; li.cpu >= 0; li.cpu--) { /* * Detect all CPU first, and Detect all Codec 2n * * In Normal sound case, all DAIs are detected * as "CPU-Codec". * * In DPCM sound case, * all CPUs are detected as "CPU-dummy", and * all Codecs are detected as "dummy-Codec". * To avoid random sub-device numbering, * detect "dummy-Codec" in last; */ ret = graph_for_each_link(...); ... } To prepare supporting multi-CPU/Codec, and code cleanup, this patch use same loop for 1st DT link check, too. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a6qq1tpp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 29 ++++++++++++++++++++++------ 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 8c5cdcdc8713..3a967c520b01 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -617,6 +617,10 @@ static int graph_count_noml(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); + /* Do it only CPU turn */ + if (!li->cpu) + return 0; + li->link += 1; /* 1xCPU-Codec */ li->dais += 2; /* 1xCPU + 1xCodec */ @@ -633,10 +637,22 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); - li->link++; /* 1xCPU-dummy */ - li->dais++; /* 1xCPU */ + /* + * Codec endpoint can be NULL for pluggable audio HW. + * Platform DT can populate the Codec endpoint depending on the + * plugged HW. + */ + if (!li->cpu && !codec_ep) + return 0; - if (!dup_codec && codec_ep) { + /* Do it all CPU endpoint, and 1st Codec endpoint */ + if (!li->cpu && dup_codec) + return 0; + + if (li->cpu) { + li->link++; /* 1xCPU-dummy */ + li->dais++; /* 1xCPU */ + } else if (!dup_codec && codec_ep) { li->link++; /* 1xdummy-Codec */ li->conf++; /* 1xdummy-Codec */ li->dais++; /* 1xCodec */ @@ -698,9 +714,10 @@ static void graph_get_dais_count(struct asoc_simple_priv *priv, * => 4 DAIs = 2xCPU + 2xCodec * => 1 ccnf = 1xdummy-Codec */ - graph_for_each_link(priv, li, - graph_count_noml, - graph_count_dpcm); + for (li->cpu = 1; li->cpu >= 0; li->cpu--) + graph_for_each_link(priv, li, + graph_count_noml, + graph_count_dpcm); dev_dbg(dev, "link %d, dais %d, ccnf %d\n", li->link, li->dais, li->conf); } From e9cbcf23a28b41a310a13d0b1b67501948b255fb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Mar 2021 12:26:20 +0900 Subject: [PATCH 0545/1091] ASoC: audio-graph: cleanup graph_for_each_link() audio-graph checks DT links 2 times. 1st is for counting DAIs / links to allocating memory, 2nd is for detecting DAIs. To detecting DAIs as CPU-dummy -> dummy-Codec order when DPCM case, it uses loops 2 times. Because of this kind of complex background, it needs to use local varuable for it, and each call-back functions need to care about it. Now, 1st and 2nd DT link check are using same order, thus we can share same code. This patch do it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/878s6a1tpf.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 129 +++++++++++++-------------- 1 file changed, 61 insertions(+), 68 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 3a967c520b01..ee1d924d68e5 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -212,8 +212,7 @@ static void graph_parse_mclk_fs(struct device_node *top, static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *cpu_ep, struct device_node *codec_ep, - struct link_info *li, - int dup_codec) + struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); struct snd_soc_card *card = simple_priv_to_card(priv); @@ -229,18 +228,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct snd_soc_dai_link_component *codecs = dai_link->codecs; int ret; - /* - * Codec endpoint can be NULL for pluggable audio HW. - * Platform DT can populate the Codec endpoint depending on the - * plugged HW. - */ - if (!li->cpu && !codec_ep) - return 0; - - /* Do it all CPU endpoint, and 1st Codec endpoint */ - if (!li->cpu && dup_codec) - return 0; - port = of_get_parent(ep); ports = of_get_parent(port); node = of_graph_get_port_parent(ep); @@ -382,10 +369,6 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, struct asoc_simple_dai *codec_dai; int ret, single_cpu; - /* Do it only CPU turn */ - if (!li->cpu) - return 0; - dev_dbg(dev, "link_of (%pOF)\n", cpu_ep); li->link++; @@ -466,7 +449,7 @@ static inline bool parse_as_dpcm_link(struct asoc_simple_priv *priv, return false; } -static int graph_for_each_link(struct asoc_simple_priv *priv, +static int __graph_for_each_link(struct asoc_simple_priv *priv, struct link_info *li, int (*func_noml)(struct asoc_simple_priv *priv, struct device_node *cpu_ep, @@ -475,7 +458,7 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, int (*func_dpcm)(struct asoc_simple_priv *priv, struct device_node *cpu_ep, struct device_node *codec_ep, - struct link_info *li, int dup_codec)) + struct link_info *li)) { struct of_phandle_iterator it; struct device *dev = simple_priv_to_dev(priv); @@ -486,7 +469,7 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, struct device_node *codec_port; struct device_node *codec_port_old = NULL; struct asoc_simple_data adata; - int rc, ret; + int rc, ret = 0; /* loop for all listed CPU port */ of_for_each_phandle(&it, rc, node, "dais", NULL, 0) { @@ -509,12 +492,21 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, graph_parse_convert(dev, cpu_ep, &adata); /* check if link requires DPCM parsing */ - if (parse_as_dpcm_link(priv, codec_port, &adata)) - ret = func_dpcm(priv, cpu_ep, codec_ep, li, - (codec_port_old == codec_port)); + if (parse_as_dpcm_link(priv, codec_port, &adata)) { + /* + * Codec endpoint can be NULL for pluggable audio HW. + * Platform DT can populate the Codec endpoint depending on the + * plugged HW. + */ + /* Do it all CPU endpoint, and 1st Codec endpoint */ + if (li->cpu || + ((codec_port_old != codec_port) && codec_ep)) + ret = func_dpcm(priv, cpu_ep, codec_ep, li); /* else normal sound */ - else - ret = func_noml(priv, cpu_ep, codec_ep, li); + } else { + if (li->cpu) + ret = func_noml(priv, cpu_ep, codec_ep, li); + } of_node_put(codec_ep); of_node_put(codec_port); @@ -529,6 +521,39 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, return 0; } +static int graph_for_each_link(struct asoc_simple_priv *priv, + struct link_info *li, + int (*func_noml)(struct asoc_simple_priv *priv, + struct device_node *cpu_ep, + struct device_node *codec_ep, + struct link_info *li), + int (*func_dpcm)(struct asoc_simple_priv *priv, + struct device_node *cpu_ep, + struct device_node *codec_ep, + struct link_info *li)) +{ + int ret; + /* + * Detect all CPU first, and Detect all Codec 2nd. + * + * In Normal sound case, all DAIs are detected + * as "CPU-Codec". + * + * In DPCM sound case, + * all CPUs are detected as "CPU-dummy", and + * all Codecs are detected as "dummy-Codec". + * To avoid random sub-device numbering, + * detect "dummy-Codec" in last; + */ + for (li->cpu = 1; li->cpu >= 0; li->cpu--) { + ret = __graph_for_each_link(priv, li, func_noml, func_dpcm); + if (ret < 0) + break; + } + + return ret; +} + static void graph_get_dais_count(struct asoc_simple_priv *priv, struct link_info *li); @@ -566,25 +591,11 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) return ret; memset(&li, 0, sizeof(li)); - for (li.cpu = 1; li.cpu >= 0; li.cpu--) { - /* - * Detect all CPU first, and Detect all Codec 2nd. - * - * In Normal sound case, all DAIs are detected - * as "CPU-Codec". - * - * In DPCM sound case, - * all CPUs are detected as "CPU-dummy", and - * all Codecs are detected as "dummy-Codec". - * To avoid random sub-device numbering, - * detect "dummy-Codec" in last; - */ - ret = graph_for_each_link(priv, &li, - graph_dai_link_of, - graph_dai_link_of_dpcm); - if (ret < 0) - goto err; - } + ret = graph_for_each_link(priv, &li, + graph_dai_link_of, + graph_dai_link_of_dpcm); + if (ret < 0) + goto err; ret = asoc_simple_parse_card_name(card, NULL); if (ret < 0) @@ -617,10 +628,6 @@ static int graph_count_noml(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); - /* Do it only CPU turn */ - if (!li->cpu) - return 0; - li->link += 1; /* 1xCPU-Codec */ li->dais += 2; /* 1xCPU + 1xCodec */ @@ -632,27 +639,14 @@ static int graph_count_noml(struct asoc_simple_priv *priv, static int graph_count_dpcm(struct asoc_simple_priv *priv, struct device_node *cpu_ep, struct device_node *codec_ep, - struct link_info *li, - int dup_codec) + struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); - /* - * Codec endpoint can be NULL for pluggable audio HW. - * Platform DT can populate the Codec endpoint depending on the - * plugged HW. - */ - if (!li->cpu && !codec_ep) - return 0; - - /* Do it all CPU endpoint, and 1st Codec endpoint */ - if (!li->cpu && dup_codec) - return 0; - if (li->cpu) { li->link++; /* 1xCPU-dummy */ li->dais++; /* 1xCPU */ - } else if (!dup_codec && codec_ep) { + } else { li->link++; /* 1xdummy-Codec */ li->conf++; /* 1xdummy-Codec */ li->dais++; /* 1xCodec */ @@ -714,10 +708,9 @@ static void graph_get_dais_count(struct asoc_simple_priv *priv, * => 4 DAIs = 2xCPU + 2xCodec * => 1 ccnf = 1xdummy-Codec */ - for (li->cpu = 1; li->cpu >= 0; li->cpu--) - graph_for_each_link(priv, li, - graph_count_noml, - graph_count_dpcm); + graph_for_each_link(priv, li, + graph_count_noml, + graph_count_dpcm); dev_dbg(dev, "link %d, dais %d, ccnf %d\n", li->link, li->dais, li->conf); } From a6e8798061bf0f33caea6fd47b0cb367309e34d0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Mar 2021 12:26:33 +0900 Subject: [PATCH 0546/1091] ASoC: simple-card: count DAI / link numbers as in order simple-card checks DT links 2 times. 1st is for counting DAIs / links to allocating memory, 2nd is for detecting DAIs. To detecting DAIs as CPU-dummy -> dummy-Codec order when DPCM case, it uses loops 2 times at 2nd DT link check. But it doesn't do it at 1st DT link check. for (li.cpu = 1; li.cpu >= 0; li.cpu--) { /* * Detect all CPU first, and Detect all Codec 2n * * In Normal sound case, all DAIs are detected * as "CPU-Codec". * * In DPCM sound case, * all CPUs are detected as "CPU-dummy", and * all Codecs are detected as "dummy-Codec". * To avoid random sub-device numbering, * detect "dummy-Codec" in last; */ ret = simple_for_each_link(...); ... } To prepare supporting multi-CPU/Codec, and code cleanup, this patch use same loop for 1st DT link check, too. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/877dlu1tp2.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 40 +++++++++++++++++++++++++-------- 1 file changed, 31 insertions(+), 9 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 75365c7bb393..f53f76ee0a8b 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -483,9 +483,17 @@ static int simple_count_noml(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - li->dais++; /* CPU or Codec */ - if (np != codec) - li->link++; /* CPU-Codec */ + /* + * |CPU |Codec : turn + * CPU |Pass |return + * Codec |return|return + * np + */ + if (!li->cpu || np == codec) + return 0; + + li->link += 1; + li->dais += 2; return 0; } @@ -495,10 +503,23 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - li->dais++; /* CPU or Codec */ - li->link++; /* CPU-dummy or dummy-Codec */ - if (np == codec) + /* + * |CPU |Codec : turn + * CPU |Pass |return + * Codec |return|Pass + * np + */ + if (li->cpu == (np == codec)) + return 0; + + if (li->cpu) { + li->link++; /* CPU-dummy */ + li->dais++; + } else { + li->link++; /* dummy-Codec */ + li->dais++; li->conf++; + } return 0; } @@ -562,9 +583,10 @@ static void simple_get_dais_count(struct asoc_simple_priv *priv, return; } - simple_for_each_link(priv, li, - simple_count_noml, - simple_count_dpcm); + for (li->cpu = 1; li->cpu >= 0; li->cpu--) + simple_for_each_link(priv, li, + simple_count_noml, + simple_count_dpcm); dev_dbg(dev, "link %d, dais %d, ccnf %d\n", li->link, li->dais, li->conf); From 39af7f7a03d007e5590f0b852b3f2fed9e703d0f Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 26 Mar 2021 12:26:40 +0900 Subject: [PATCH 0547/1091] ASoC: simple-card: cleanup graph_for_each_link() simple-card checks DT links 2 times. 1st is for counting DAIs / links to allocating memory, 2nd is for detecting DAIs. To detecting DAIs as CPU-dummy -> dummy-Codec order when DPCM case, it uses loops 2 times. Because of this kind of complex background, it needs to use local varuable for it, and each call-back functions need to care about it. Now, 1st and 2nd DT link check are using same order, thus we can share same code. This patch do it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875z1e1tov.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 125 ++++++++++++++++---------------- 1 file changed, 61 insertions(+), 64 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index f53f76ee0a8b..41aa40765a8d 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -129,15 +129,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, char *prefix = ""; int ret; - /* - * |CPU |Codec : turn - * CPU |Pass |return - * Codec |return|Pass - * np - */ - if (li->cpu == (np == codec)) - return 0; - dev_dbg(dev, "link_of DPCM (%pOF)\n", np); li->link++; @@ -260,15 +251,6 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, char *prefix = ""; int ret, single_cpu; - /* - * |CPU |Codec : turn - * CPU |Pass |return - * Codec |return|return - * np - */ - if (!li->cpu || np == codec) - return 0; - cpu = np; node = of_get_parent(np); li->link++; @@ -342,7 +324,7 @@ dai_link_of_err: return ret; } -static int simple_for_each_link(struct asoc_simple_priv *priv, +static int __simple_for_each_link(struct asoc_simple_priv *priv, struct link_info *li, int (*func_noml)(struct asoc_simple_priv *priv, struct device_node *np, @@ -402,11 +384,26 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, */ if (dpcm_selectable && (num > 2 || - adata.convert_rate || adata.convert_channels)) - ret = func_dpcm(priv, np, codec, li, is_top); + adata.convert_rate || adata.convert_channels)) { + /* + * np + * |1(CPU)|0(Codec) li->cpu + * CPU |Pass |return + * Codec |return|Pass + */ + if (li->cpu != (np == codec)) + ret = func_dpcm(priv, np, codec, li, is_top); /* else normal sound */ - else - ret = func_noml(priv, np, codec, li, is_top); + } else { + /* + * np + * |1(CPU)|0(Codec) li->cpu + * CPU |Pass |return + * Codec |return|return + */ + if (li->cpu && (np != codec)) + ret = func_noml(priv, np, codec, li, is_top); + } if (ret < 0) { of_node_put(codec); @@ -424,6 +421,39 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, return ret; } +static int simple_for_each_link(struct asoc_simple_priv *priv, + struct link_info *li, + int (*func_noml)(struct asoc_simple_priv *priv, + struct device_node *np, + struct device_node *codec, + struct link_info *li, bool is_top), + int (*func_dpcm)(struct asoc_simple_priv *priv, + struct device_node *np, + struct device_node *codec, + struct link_info *li, bool is_top)) +{ + int ret; + /* + * Detect all CPU first, and Detect all Codec 2nd. + * + * In Normal sound case, all DAIs are detected + * as "CPU-Codec". + * + * In DPCM sound case, + * all CPUs are detected as "CPU-dummy", and + * all Codecs are detected as "dummy-Codec". + * To avoid random sub-device numbering, + * detect "dummy-Codec" in last; + */ + for (li->cpu = 1; li->cpu >= 0; li->cpu--) { + ret = __simple_for_each_link(priv, li, func_noml, func_dpcm); + if (ret < 0) + break; + } + + return ret; +} + static int simple_parse_of(struct asoc_simple_priv *priv) { struct device *dev = simple_priv_to_dev(priv); @@ -449,25 +479,11 @@ static int simple_parse_of(struct asoc_simple_priv *priv) /* Single/Muti DAI link(s) & New style of DT node */ memset(&li, 0, sizeof(li)); - for (li.cpu = 1; li.cpu >= 0; li.cpu--) { - /* - * Detect all CPU first, and Detect all Codec 2nd. - * - * In Normal sound case, all DAIs are detected - * as "CPU-Codec". - * - * In DPCM sound case, - * all CPUs are detected as "CPU-dummy", and - * all Codecs are detected as "dummy-Codec". - * To avoid random sub-device numbering, - * detect "dummy-Codec" in last; - */ - ret = simple_for_each_link(priv, &li, - simple_dai_link_of, - simple_dai_link_of_dpcm); - if (ret < 0) - return ret; - } + ret = simple_for_each_link(priv, &li, + simple_dai_link_of, + simple_dai_link_of_dpcm); + if (ret < 0) + return ret; ret = asoc_simple_parse_card_name(card, PREFIX); if (ret < 0) @@ -483,15 +499,6 @@ static int simple_count_noml(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - /* - * |CPU |Codec : turn - * CPU |Pass |return - * Codec |return|return - * np - */ - if (!li->cpu || np == codec) - return 0; - li->link += 1; li->dais += 2; @@ -503,15 +510,6 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - /* - * |CPU |Codec : turn - * CPU |Pass |return - * Codec |return|Pass - * np - */ - if (li->cpu == (np == codec)) - return 0; - if (li->cpu) { li->link++; /* CPU-dummy */ li->dais++; @@ -583,10 +581,9 @@ static void simple_get_dais_count(struct asoc_simple_priv *priv, return; } - for (li->cpu = 1; li->cpu >= 0; li->cpu--) - simple_for_each_link(priv, li, - simple_count_noml, - simple_count_dpcm); + simple_for_each_link(priv, li, + simple_count_noml, + simple_count_dpcm); dev_dbg(dev, "link %d, dais %d, ccnf %d\n", li->link, li->dais, li->conf); From 875c40eadf6ac6644c0f71842a4f30dd9968d281 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 25 Mar 2021 23:10:54 +0100 Subject: [PATCH 0548/1091] ASoC: Intel: bytcr_rt5640: Add quirk for the Chuwi Hi8 tablet The Chuwi Hi8 tablet is using an analog mic on IN1 and has its jack-detect connected to JD2_IN4N, instead of using the default IN3 for its internal mic and JD1_IN4P for jack-detect. It also only has 1 speaker. Add a quirk applying the correct settings for this configuration. Signed-off-by: Hans de Goede Link: https://lore.kernel.org/r/20210325221054.22714-1-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bytcr_rt5640.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/sound/soc/intel/boards/bytcr_rt5640.c b/sound/soc/intel/boards/bytcr_rt5640.c index 59d6d47c8d82..df2f5d55e8ff 100644 --- a/sound/soc/intel/boards/bytcr_rt5640.c +++ b/sound/soc/intel/boards/bytcr_rt5640.c @@ -518,6 +518,23 @@ static const struct dmi_system_id byt_rt5640_quirk_table[] = { BYT_RT5640_SSP0_AIF1 | BYT_RT5640_MCLK_EN), }, + { + /* Chuwi Hi8 (CWI509) */ + .matches = { + DMI_MATCH(DMI_BOARD_VENDOR, "Hampoo"), + DMI_MATCH(DMI_BOARD_NAME, "BYT-PA03C"), + DMI_MATCH(DMI_SYS_VENDOR, "ilife"), + DMI_MATCH(DMI_PRODUCT_NAME, "S806"), + }, + .driver_data = (void *)(BYT_RT5640_IN1_MAP | + BYT_RT5640_JD_SRC_JD2_IN4N | + BYT_RT5640_OVCD_TH_2000UA | + BYT_RT5640_OVCD_SF_0P75 | + BYT_RT5640_MONO_SPEAKER | + BYT_RT5640_DIFF_MIC | + BYT_RT5640_SSP0_AIF1 | + BYT_RT5640_MCLK_EN), + }, { .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Circuitco"), From d8c5c82e4e5b641404c65bfc6cdf57b5d0a6c836 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Wed, 31 Mar 2021 15:44:45 +0800 Subject: [PATCH 0549/1091] ASoC: ak5558: Add support for ak5552 AK5552 is a 32-bit 2ch ADC and has the same register map as AK5558. Signed-off-by: Viorel Suman Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1617176686-25528-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 97 ++++++++++++++++++++++++++++++++++++--- 1 file changed, 90 insertions(+), 7 deletions(-) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 85bdd0534180..3ac62a281807 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -23,6 +24,11 @@ #include "ak5558.h" +enum ak555x_type { + AK5558, + AK5552, +}; + #define AK5558_NUM_SUPPLIES 2 static const char *ak5558_supply_names[AK5558_NUM_SUPPLIES] = { "DVDD", @@ -59,6 +65,15 @@ static const struct soc_enum ak5558_mono_enum[] = { ARRAY_SIZE(mono_texts), mono_texts), }; +static const char * const mono_5552_texts[] = { + "2 Slot", "1 Slot (Fixed)", "2 Slot", "1 Slot (Optimal)", +}; + +static const struct soc_enum ak5552_mono_enum[] = { + SOC_ENUM_SINGLE(AK5558_01_POWER_MANAGEMENT2, 1, + ARRAY_SIZE(mono_5552_texts), mono_5552_texts), +}; + static const char * const digfil_texts[] = { "Sharp Roll-Off", "Show Roll-Off", "Short Delay Sharp Roll-Off", "Short Delay Show Roll-Off", @@ -70,8 +85,13 @@ static const struct soc_enum ak5558_adcset_enum[] = { }; static const struct snd_kcontrol_new ak5558_snd_controls[] = { - SOC_ENUM("AK5558 Monaural Mode", ak5558_mono_enum[0]), - SOC_ENUM("AK5558 Digital Filter", ak5558_adcset_enum[0]), + SOC_ENUM("Monaural Mode", ak5558_mono_enum[0]), + SOC_ENUM("Digital Filter", ak5558_adcset_enum[0]), +}; + +static const struct snd_kcontrol_new ak5552_snd_controls[] = { + SOC_ENUM("Monaural Mode", ak5552_mono_enum[0]), + SOC_ENUM("Digital Filter", ak5558_adcset_enum[0]), }; static const struct snd_soc_dapm_widget ak5558_dapm_widgets[] = { @@ -97,6 +117,17 @@ static const struct snd_soc_dapm_widget ak5558_dapm_widgets[] = { SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0), }; +static const struct snd_soc_dapm_widget ak5552_dapm_widgets[] = { + /* Analog Input */ + SND_SOC_DAPM_INPUT("AIN1"), + SND_SOC_DAPM_INPUT("AIN2"), + + SND_SOC_DAPM_ADC("ADC Ch1", NULL, AK5558_00_POWER_MANAGEMENT1, 0, 0), + SND_SOC_DAPM_ADC("ADC Ch2", NULL, AK5558_00_POWER_MANAGEMENT1, 1, 0), + + SND_SOC_DAPM_AIF_OUT("SDTO", "Capture", 0, SND_SOC_NOPM, 0, 0), +}; + static const struct snd_soc_dapm_route ak5558_intercon[] = { {"ADC Ch1", NULL, "AIN1"}, {"SDTO", NULL, "ADC Ch1"}, @@ -123,6 +154,14 @@ static const struct snd_soc_dapm_route ak5558_intercon[] = { {"SDTO", NULL, "ADC Ch8"}, }; +static const struct snd_soc_dapm_route ak5552_intercon[] = { + {"ADC Ch1", NULL, "AIN1"}, + {"SDTO", NULL, "ADC Ch1"}, + + {"ADC Ch2", NULL, "AIN2"}, + {"SDTO", NULL, "ADC Ch2"}, +}; + static int ak5558_set_mcki(struct snd_soc_component *component) { return snd_soc_component_update_bits(component, AK5558_02_CONTROL1, AK5558_CKS, @@ -267,6 +306,18 @@ static struct snd_soc_dai_driver ak5558_dai = { .ops = &ak5558_dai_ops, }; +static struct snd_soc_dai_driver ak5552_dai = { + .name = "ak5558-aif", + .capture = { + .stream_name = "Capture", + .channels_min = 1, + .channels_max = 2, + .rates = SNDRV_PCM_RATE_KNOT, + .formats = AK5558_FORMATS, + }, + .ops = &ak5558_dai_ops, +}; + static void ak5558_power_off(struct ak5558_priv *ak5558) { if (!ak5558->reset_gpiod) @@ -354,6 +405,21 @@ static const struct snd_soc_component_driver soc_codec_dev_ak5558 = { .non_legacy_dai_naming = 1, }; +static const struct snd_soc_component_driver soc_codec_dev_ak5552 = { + .probe = ak5558_probe, + .remove = ak5558_remove, + .controls = ak5552_snd_controls, + .num_controls = ARRAY_SIZE(ak5552_snd_controls), + .dapm_widgets = ak5552_dapm_widgets, + .num_dapm_widgets = ARRAY_SIZE(ak5552_dapm_widgets), + .dapm_routes = ak5552_intercon, + .num_dapm_routes = ARRAY_SIZE(ak5552_intercon), + .idle_bias_on = 1, + .use_pmdown_time = 1, + .endianness = 1, + .non_legacy_dai_naming = 1, +}; + static const struct regmap_config ak5558_regmap = { .reg_bits = 8, .val_bits = 8, @@ -368,6 +434,7 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) { struct ak5558_priv *ak5558; int ret = 0; + int dev_id; int i; ak5558 = devm_kzalloc(&i2c->dev, sizeof(*ak5558), GFP_KERNEL); @@ -396,11 +463,26 @@ static int ak5558_i2c_probe(struct i2c_client *i2c) return ret; } - ret = devm_snd_soc_register_component(&i2c->dev, - &soc_codec_dev_ak5558, - &ak5558_dai, 1); - if (ret) + dev_id = (uintptr_t)of_device_get_match_data(&i2c->dev); + switch (dev_id) { + case AK5552: + ret = devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_ak5552, + &ak5552_dai, 1); + break; + case AK5558: + ret = devm_snd_soc_register_component(&i2c->dev, + &soc_codec_dev_ak5558, + &ak5558_dai, 1); + break; + default: + dev_err(&i2c->dev, "unexpected device type\n"); + return -EINVAL; + } + if (ret < 0) { + dev_err(&i2c->dev, "failed to register component: %d\n", ret); return ret; + } pm_runtime_enable(&i2c->dev); regcache_cache_only(ak5558->regmap, true); @@ -416,7 +498,8 @@ static int ak5558_i2c_remove(struct i2c_client *i2c) } static const struct of_device_id ak5558_i2c_dt_ids[] __maybe_unused = { - { .compatible = "asahi-kasei,ak5558"}, + { .compatible = "asahi-kasei,ak5558", .data = (void *) AK5558 }, + { .compatible = "asahi-kasei,ak5552", .data = (void *) AK5552 }, { } }; MODULE_DEVICE_TABLE(of, ak5558_i2c_dt_ids); From 8d246806d510c1bf7da9aab0473dc0f9c9f99308 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 31 Mar 2021 15:44:46 +0800 Subject: [PATCH 0550/1091] ASoC: dt-bindings: ak5558: Add compatible string for ak5552 Add compatible string "asahi-kasei,ak5552" for ak5552 Signed-off-by: Shengjiu Wang Acked-by: Rob Herring Link: https://lore.kernel.org/r/1617176686-25528-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/ak5558.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/ak5558.txt b/Documentation/devicetree/bindings/sound/ak5558.txt index 36934098170c..e28708db6686 100644 --- a/Documentation/devicetree/bindings/sound/ak5558.txt +++ b/Documentation/devicetree/bindings/sound/ak5558.txt @@ -4,7 +4,7 @@ This device supports I2C mode only. Required properties: -- compatible : "asahi-kasei,ak5558" +- compatible : "asahi-kasei,ak5558" or "asahi-kasei,ak5552". - reg : The I2C address of the device. Optional properties: From 50cbf945566b7cdb186c80c389bdfe22850d8d29 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Mon, 22 Mar 2021 12:19:09 +0530 Subject: [PATCH 0551/1091] ASoC: Intel: Fix a typo s/struture/structure/ Signed-off-by: Bhaskar Chowdhury Link: https://lore.kernel.org/r/20210322064909.4189290-1-unixbhaskar@gmail.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-dsp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/atom/sst-mfld-dsp.h b/sound/soc/intel/atom/sst-mfld-dsp.h index 5795f98e04d4..102b0e7eafb0 100644 --- a/sound/soc/intel/atom/sst-mfld-dsp.h +++ b/sound/soc/intel/atom/sst-mfld-dsp.h @@ -358,7 +358,7 @@ struct snd_wma_params { u8 reserved; /* reserved */ } __packed; -/* Codec params struture */ +/* Codec params structure */ union snd_sst_codec_params { struct snd_pcm_params pcm_params; struct snd_mp3_params mp3_params; From 868d5c6340d878f44acf73c92923995b896b6454 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Tue, 30 Mar 2021 20:06:57 +0200 Subject: [PATCH 0552/1091] ASoC: tegra: Set driver name explicitly The SoC sound core will generate a driver name by normalizing the card name. However, most of the time that name does not tell anything about the driver and is therefore useless for this purpose. Make the driver name more useful by setting it explicitly during card initialization. Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20210330180657.1867971-1-thierry.reding@gmail.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra_audio_graph_card.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c index ddedf18adde1..47b319504c8c 100644 --- a/sound/soc/tegra/tegra_audio_graph_card.c +++ b/sound/soc/tegra/tegra_audio_graph_card.c @@ -198,6 +198,7 @@ static int tegra_audio_graph_probe(struct platform_device *pdev) return -ENOMEM; card = simple_priv_to_card(&priv->simple); + card->driver_name = "tegra-ape"; card->probe = tegra_audio_graph_card_probe; From e896ec390870287dcc92f3b46d80da88f3b4b1f8 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Wed, 31 Mar 2021 15:10:46 +0800 Subject: [PATCH 0553/1091] ASoC: rt1019: add address-cells and size-cells information Add address-cells and size-cells information to fix warnings for rt1019.yaml. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/20210331071046.12526-1-jack.yu@realtek.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/rt1019.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Documentation/devicetree/bindings/sound/rt1019.yaml b/Documentation/devicetree/bindings/sound/rt1019.yaml index c24c29eafa54..3d5a91a942f4 100644 --- a/Documentation/devicetree/bindings/sound/rt1019.yaml +++ b/Documentation/devicetree/bindings/sound/rt1019.yaml @@ -26,6 +26,8 @@ additionalProperties: false examples: - | i2c { + #address-cells = <1>; + #size-cells = <0>; rt1019: codec@28 { compatible = "realtek,rt1019"; reg = <0x28>; From 458c23c509f66c5950da7e5496ea952ad15128f7 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 17:16:18 -0500 Subject: [PATCH 0554/1091] ASoC: lm49453: fix useless assignment before return Cppcheck warning: sound/soc/codecs/lm49453.c:1210:11: style: Variable 'pll_clk' is assigned a value that is never used. [unreadVariable] pll_clk = BIT(4); ^ FIXME: What is the correct fix? /* fll clk slection */ pll_clk = BIT(4); return 0; is the assignment redundant or the 'return 0' a mistake? Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326221619.949961-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/lm49453.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/lm49453.c b/sound/soc/codecs/lm49453.c index eb3dd0bd80d9..fb0fb23537e7 100644 --- a/sound/soc/codecs/lm49453.c +++ b/sound/soc/codecs/lm49453.c @@ -1206,8 +1206,6 @@ static int lm49453_set_dai_sysclk(struct snd_soc_dai *dai, int clk_id, break; case 48000: case 32576: - /* fll clk slection */ - pll_clk = BIT(4); return 0; default: return -EINVAL; From 945b0b58c5d7c6640f9aad2096e4675bc7f5371c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 17:16:19 -0500 Subject: [PATCH 0555/1091] ASoC: da732x: simplify code cppcheck reports a false positive: sound/soc/codecs/da732x.c:1161:25: warning: Either the condition 'indiv<0' is redundant or there is division by zero at line 1161. [zerodivcond] fref = (da732x->sysclk / indiv); ^ sound/soc/codecs/da732x.c:1158:12: note: Assuming that condition 'indiv<0' is not redundant if (indiv < 0) ^ sound/soc/codecs/da732x.c:1161:25: note: Division by zero fref = (da732x->sysclk / indiv); ^ The code is awfully convoluted/confusing and can be simplified with a single variable and the BIT macro. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326221619.949961-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/da732x.c | 17 ++++++----------- sound/soc/codecs/da732x.h | 12 ++++-------- 2 files changed, 10 insertions(+), 19 deletions(-) diff --git a/sound/soc/codecs/da732x.c b/sound/soc/codecs/da732x.c index d43ee7159ae0..42d6a3fc3af5 100644 --- a/sound/soc/codecs/da732x.c +++ b/sound/soc/codecs/da732x.c @@ -168,30 +168,25 @@ static const struct reg_default da732x_reg_cache[] = { static inline int da732x_get_input_div(struct snd_soc_component *component, int sysclk) { int val; - int ret; if (sysclk < DA732X_MCLK_10MHZ) { - val = DA732X_MCLK_RET_0_10MHZ; - ret = DA732X_MCLK_VAL_0_10MHZ; + val = DA732X_MCLK_VAL_0_10MHZ; } else if ((sysclk >= DA732X_MCLK_10MHZ) && (sysclk < DA732X_MCLK_20MHZ)) { - val = DA732X_MCLK_RET_10_20MHZ; - ret = DA732X_MCLK_VAL_10_20MHZ; + val = DA732X_MCLK_VAL_10_20MHZ; } else if ((sysclk >= DA732X_MCLK_20MHZ) && (sysclk < DA732X_MCLK_40MHZ)) { - val = DA732X_MCLK_RET_20_40MHZ; - ret = DA732X_MCLK_VAL_20_40MHZ; + val = DA732X_MCLK_VAL_20_40MHZ; } else if ((sysclk >= DA732X_MCLK_40MHZ) && (sysclk <= DA732X_MCLK_54MHZ)) { - val = DA732X_MCLK_RET_40_54MHZ; - ret = DA732X_MCLK_VAL_40_54MHZ; + val = DA732X_MCLK_VAL_40_54MHZ; } else { return -EINVAL; } snd_soc_component_write(component, DA732X_REG_PLL_CTRL, val); - return ret; + return val; } static void da732x_set_charge_pump(struct snd_soc_component *component, int state) @@ -1158,7 +1153,7 @@ static int da732x_set_dai_pll(struct snd_soc_component *component, int pll_id, if (indiv < 0) return indiv; - fref = (da732x->sysclk / indiv); + fref = da732x->sysclk / BIT(indiv); div_hi = freq_out / fref; frac_div = (u64)(freq_out % fref) * 8192ULL; do_div(frac_div, fref); diff --git a/sound/soc/codecs/da732x.h b/sound/soc/codecs/da732x.h index c5af17ee1516..c2f784c3f359 100644 --- a/sound/soc/codecs/da732x.h +++ b/sound/soc/codecs/da732x.h @@ -48,14 +48,10 @@ #define DA732X_MCLK_20MHZ 20000000 #define DA732X_MCLK_40MHZ 40000000 #define DA732X_MCLK_54MHZ 54000000 -#define DA732X_MCLK_RET_0_10MHZ 0 -#define DA732X_MCLK_VAL_0_10MHZ 1 -#define DA732X_MCLK_RET_10_20MHZ 1 -#define DA732X_MCLK_VAL_10_20MHZ 2 -#define DA732X_MCLK_RET_20_40MHZ 2 -#define DA732X_MCLK_VAL_20_40MHZ 4 -#define DA732X_MCLK_RET_40_54MHZ 3 -#define DA732X_MCLK_VAL_40_54MHZ 8 +#define DA732X_MCLK_VAL_0_10MHZ 0 +#define DA732X_MCLK_VAL_10_20MHZ 1 +#define DA732X_MCLK_VAL_20_40MHZ 2 +#define DA732X_MCLK_VAL_40_54MHZ 3 #define DA732X_DAI_ID1 0 #define DA732X_DAI_ID2 1 #define DA732X_SRCCLK_PLL 0 From 9c1e0439ada9973ec99cc1e0887eb84fd26444b8 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 31 Mar 2021 09:27:46 -0500 Subject: [PATCH 0556/1091] ASoC: dt-bindings: Move port/ports properties out of audio-graph-port.yaml Users of the audio-graph-port schema need to define how many ports and what each port is, so they need to define 'ports' and/or 'port' anyways. Let's drop 'ports' and 'port' from the schema and adjust users to reference audio-graph-port.yaml from a port property. Cc: Liam Girdwood Cc: Mark Brown Cc: Thierry Reding Cc: Jonathan Hunter Cc: Kuninori Morimoto Cc: Lubomir Rintel Cc: Sameer Pujar Cc: alsa-devel@alsa-project.org Cc: linux-tegra@vger.kernel.org Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20210331142748.2163272-2-robh@kernel.org Signed-off-by: Mark Brown --- .../bindings/sound/audio-graph-port.yaml | 101 ++++++++---------- .../bindings/sound/marvell,mmp-sspa.yaml | 6 +- .../bindings/sound/nvidia,tegra186-dspk.yaml | 11 +- .../sound/nvidia,tegra210-admaif.yaml | 11 +- .../bindings/sound/nvidia,tegra210-ahub.yaml | 11 +- .../bindings/sound/nvidia,tegra210-dmic.yaml | 11 +- .../bindings/sound/nvidia,tegra210-i2s.yaml | 11 +- .../bindings/sound/renesas,rsnd.yaml | 5 +- 8 files changed, 82 insertions(+), 85 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml index 766e9109b2f7..9f68142c9ae3 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml @@ -12,70 +12,59 @@ maintainers: select: false properties: - port: - description: single OF-Graph subnode + reg: + maxItems: 1 + prefix: + description: "device name prefix" + $ref: /schemas/types.yaml#/definitions/string + convert-rate: + description: CPU to Codec rate convert. + $ref: /schemas/types.yaml#/definitions/uint32 + convert-channels: + description: CPU to Codec rate channels. + $ref: /schemas/types.yaml#/definitions/uint32 +patternProperties: + "^endpoint(@[0-9a-f]+)?": type: object properties: - reg: + remote-endpoint: maxItems: 1 - prefix: - description: "device name prefix" - $ref: /schemas/types.yaml#/definitions/string + mclk-fs: + description: | + Multiplication factor between stream rate and codec mclk. + When defined, mclk-fs property defined in dai-link sub nodes are + ignored. + $ref: /schemas/types.yaml#/definitions/uint32 + frame-inversion: + description: dai-link uses frame clock inversion + $ref: /schemas/types.yaml#/definitions/flag + bitclock-inversion: + description: dai-link uses bit clock inversion + $ref: /schemas/types.yaml#/definitions/flag + frame-master: + description: Indicates dai-link frame master. + $ref: /schemas/types.yaml#/definitions/phandle + bitclock-master: + description: Indicates dai-link bit clock master + $ref: /schemas/types.yaml#/definitions/phandle + dai-format: + description: audio format. + items: + enum: + - i2s + - right_j + - left_j + - dsp_a + - dsp_b + - ac97 + - pdm + - msb + - lsb convert-rate: description: CPU to Codec rate convert. $ref: /schemas/types.yaml#/definitions/uint32 convert-channels: description: CPU to Codec rate channels. $ref: /schemas/types.yaml#/definitions/uint32 - patternProperties: - "^endpoint(@[0-9a-f]+)?": - type: object - properties: - remote-endpoint: - maxItems: 1 - mclk-fs: - description: | - Multiplication factor between stream rate and codec mclk. - When defined, mclk-fs property defined in dai-link sub nodes are - ignored. - $ref: /schemas/types.yaml#/definitions/uint32 - frame-inversion: - description: dai-link uses frame clock inversion - $ref: /schemas/types.yaml#/definitions/flag - bitclock-inversion: - description: dai-link uses bit clock inversion - $ref: /schemas/types.yaml#/definitions/flag - frame-master: - description: Indicates dai-link frame master. - $ref: /schemas/types.yaml#/definitions/phandle - bitclock-master: - description: Indicates dai-link bit clock master - $ref: /schemas/types.yaml#/definitions/phandle - dai-format: - description: audio format. - items: - enum: - - i2s - - right_j - - left_j - - dsp_a - - dsp_b - - ac97 - - pdm - - msb - - lsb - convert-rate: - description: CPU to Codec rate convert. - $ref: /schemas/types.yaml#/definitions/uint32 - convert-channels: - description: CPU to Codec rate channels. - $ref: /schemas/types.yaml#/definitions/uint32 - - ports: - description: multi OF-Graph subnode - type: object - patternProperties: - "^port(@[0-9a-f]+)?": - $ref: "#/properties/port" additionalProperties: true diff --git a/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml b/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml index 234f64a32184..81f266d66ec5 100644 --- a/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml +++ b/Documentation/devicetree/bindings/sound/marvell,mmp-sspa.yaml @@ -9,9 +9,6 @@ title: Marvel SSPA Digital Audio Interface Bindings maintainers: - Lubomir Rintel -allOf: - - $ref: audio-graph-port.yaml# - properties: $nodename: pattern: "^audio-controller(@.*)?$" @@ -54,7 +51,8 @@ properties: - const: rx port: - type: object + $ref: audio-graph-port.yaml# + unevaluatedProperties: false properties: endpoint: diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml index b8645d9c38ac..5f6b37c251a8 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra186-dspk.yaml @@ -17,9 +17,6 @@ maintainers: - Jon Hunter - Sameer Pujar -allOf: - - $ref: audio-graph-port.yaml# - properties: $nodename: pattern: "^dspk@[0-9a-f]*$" @@ -59,14 +56,18 @@ properties: available instances on a Tegra SoC. ports: - type: object + $ref: /schemas/graph.yaml#/properties/ports properties: port@0: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false description: | DSPK ACIF (Audio Client Interface) port connected to the corresponding AHUB (Audio Hub) ACIF port. port@1: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false description: | DSPK DAP (Digital Audio Port) interface which can be connected to external audio codec for playback. @@ -80,7 +81,7 @@ required: - assigned-clock-parents - sound-name-prefix -unevaluatedProperties: false +additionalProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml index 7cee7722df41..19eaacc3f12a 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-admaif.yaml @@ -17,9 +17,6 @@ maintainers: - Jon Hunter - Sameer Pujar -allOf: - - $ref: audio-graph-port.yaml# - properties: $nodename: pattern: "^admaif@[0-9a-f]*$" @@ -41,6 +38,7 @@ properties: dma-names: true ports: + $ref: /schemas/graph.yaml#/properties/ports description: | Contains list of ACIF (Audio CIF) port nodes for ADMAIF channels. The number of port nodes depends on the number of ADMAIF channels @@ -48,6 +46,11 @@ properties: in AHUB (Audio Hub). Each port is capable of data transfers in both directions. + patternProperties: + '^port@[0-9]': + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + if: properties: compatible: @@ -92,7 +95,7 @@ required: - dmas - dma-names -unevaluatedProperties: false +additionalProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml index 61d0c944e972..1118a9488345 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-ahub.yaml @@ -17,9 +17,6 @@ maintainers: - Jon Hunter - Sameer Pujar -allOf: - - $ref: audio-graph-port.yaml# - properties: $nodename: pattern: "^ahub@[0-9a-f]*$" @@ -60,12 +57,18 @@ properties: ranges: true ports: + $ref: /schemas/graph.yaml#/properties/ports description: | Contains list of ACIF (Audio CIF) port nodes for AHUB (Audio Hub). These are connected to ACIF interfaces of AHUB clients. Thus the number of port nodes depend on the number of clients that AHUB may have depending on the SoC revision. + patternProperties: + '^port@[0-9]': + $ref: audio-graph-port.yaml# + unevaluatedProperties: false + patternProperties: '^i2s@[0-9a-f]+$': type: object @@ -93,7 +96,7 @@ required: - "#size-cells" - ranges -unevaluatedProperties: false +additionalProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml index 89f4f471be24..fd275a575055 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-dmic.yaml @@ -16,9 +16,6 @@ maintainers: - Jon Hunter - Sameer Pujar -allOf: - - $ref: audio-graph-port.yaml# - properties: $nodename: pattern: "^dmic@[0-9a-f]*$" @@ -60,14 +57,18 @@ properties: on the maximum available instances on a Tegra SoC. ports: - type: object + $ref: /schemas/graph.yaml#/properties/ports properties: port@0: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false description: | DMIC ACIF (Audio Client Interface) port connected to the corresponding AHUB (Audio Hub) ACIF port. port@1: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false description: | DMIC DAP (Digital Audio Port) interface which can be connected to external audio codec for capture. @@ -80,7 +81,7 @@ required: - assigned-clocks - assigned-clock-parents -unevaluatedProperties: false +additionalProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml index 556460332ffb..38e52e7dbb40 100644 --- a/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/nvidia,tegra210-i2s.yaml @@ -16,9 +16,6 @@ maintainers: - Jon Hunter - Sameer Pujar -allOf: - - $ref: audio-graph-port.yaml# - properties: $nodename: pattern: "^i2s@[0-9a-f]*$" @@ -78,14 +75,18 @@ properties: on the maximum available instances on a Tegra SoC. ports: - type: object + $ref: /schemas/graph.yaml#/properties/ports properties: port@0: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false description: | I2S ACIF (Audio Client Interface) port connected to the corresponding AHUB (Audio Hub) ACIF port. port@1: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false description: | I2S DAP (Digital Audio Port) interface which can be connected to external audio codec for playback or capture. @@ -98,7 +99,7 @@ required: - assigned-clocks - assigned-clock-parents -unevaluatedProperties: false +additionalProperties: false examples: - | diff --git a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml index 2e1046513603..1e0e14e88913 100644 --- a/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml +++ b/Documentation/devicetree/bindings/sound/renesas,rsnd.yaml @@ -111,7 +111,9 @@ properties: - pattern: '^dvc\.[0-1]$' - pattern: '^clk_(a|b|c|i)$' - port: true + port: + $ref: audio-graph-port.yaml# + unevaluatedProperties: false # use patternProperties to avoid naming "xxx,yyy" issue patternProperties: @@ -257,7 +259,6 @@ required: allOf: - $ref: audio-graph.yaml# - - $ref: audio-graph-port.yaml# - if: properties: compatible: From ec1c8302178a946986bb7b52ac7bb9ccdcdf7d92 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 31 Mar 2021 09:27:47 -0500 Subject: [PATCH 0557/1091] ASoC: dt-bindings: Use OF graph schema Now that we have an OF graph schema, let's use it for the audio-graph-port schema. Cc: Liam Girdwood Cc: Mark Brown Cc: Kuninori Morimoto Cc: alsa-devel@alsa-project.org Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20210331142748.2163272-3-robh@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/audio-graph-port.yaml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml index 9f68142c9ae3..43e7f86e3b23 100644 --- a/Documentation/devicetree/bindings/sound/audio-graph-port.yaml +++ b/Documentation/devicetree/bindings/sound/audio-graph-port.yaml @@ -11,9 +11,10 @@ maintainers: select: false +allOf: + - $ref: /schemas/graph.yaml#/$defs/port-base + properties: - reg: - maxItems: 1 prefix: description: "device name prefix" $ref: /schemas/types.yaml#/definitions/string @@ -25,10 +26,8 @@ properties: $ref: /schemas/types.yaml#/definitions/uint32 patternProperties: "^endpoint(@[0-9a-f]+)?": - type: object + $ref: /schemas/graph.yaml#/$defs/endpoint-base properties: - remote-endpoint: - maxItems: 1 mclk-fs: description: | Multiplication factor between stream rate and codec mclk. From f1321c9766b2c9e79de268225e291dead0a8f969 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Wed, 31 Mar 2021 09:27:48 -0500 Subject: [PATCH 0558/1091] ASoC: dt-bindings: socionext: Use audio-graph-port schema Convert the Socionext audio schemas to use audio-graph-port.yaml schema for 'port' nodes. The number and numbering of port nodes should be documented, but is not. Leave a FIXME here so others don't copy. Cc: Masahiro Yamada Cc: Liam Girdwood Cc: Mark Brown Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20210331142748.2163272-4-robh@kernel.org Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/socionext,uniphier-aio.yaml | 8 +++----- .../bindings/sound/socionext,uniphier-evea.yaml | 8 +++----- 2 files changed, 6 insertions(+), 10 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml index 4987eb91f2ab..55ae198220f4 100644 --- a/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml +++ b/Documentation/devicetree/bindings/sound/socionext,uniphier-aio.yaml @@ -46,11 +46,9 @@ properties: patternProperties: "^port@[0-9]$": - type: object - properties: - endpoint: true - required: - - endpoint + description: FIXME, Need to define what each port is. + $ref: audio-graph-port.yaml# + unevaluatedProperties: false additionalProperties: false diff --git a/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml b/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml index 228168f685cf..48ddfcbbcbae 100644 --- a/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml +++ b/Documentation/devicetree/bindings/sound/socionext,uniphier-evea.yaml @@ -40,11 +40,9 @@ properties: patternProperties: "^port@[0-9]$": - type: object - properties: - endpoint: true - required: - - endpoint + description: FIXME, Need to define what each port is. + $ref: audio-graph-port.yaml# + unevaluatedProperties: false additionalProperties: false From f1b3ee789f4b7a41ad93ff42d4efbae607622ae7 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 30 Mar 2021 14:26:28 +0900 Subject: [PATCH 0559/1091] ASoC: soc-core: add comment for rtd freeing We don't need to mind freeing for rtd, because it was created from devm_kzalloc(dev, xxx) which is rtd->dev. This means, if rtd->dev was freed, rtd will be also freed automatically. soc_new_pcm_runtime(...) { ... rtd = devm_kzalloc(dev, ...); rtd->dev = dev; ... } This explanation was missing at soc_free_pcm_runtime() comment. This patch indicates it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sg4dxldn.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 522bae73640a..88694746dc11 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -413,6 +413,14 @@ static void soc_free_pcm_runtime(struct snd_soc_pcm_runtime *rtd) * it is alloced *before* rtd. * see * soc_new_pcm_runtime() + * + * We don't need to mind freeing for rtd, + * because it was created from dev (= rtd->dev) + * see + * soc_new_pcm_runtime() + * + * rtd = devm_kzalloc(dev, ...); + * rtd->dev = dev */ device_unregister(rtd->dev); } From 5fa7553dcd83c576c589fd3e617dc599e4fe15dc Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Tue, 30 Mar 2021 14:26:38 +0900 Subject: [PATCH 0560/1091] ASoC: soc-core: use device_unregister() if rtd allocation failed Because soc_free_pcm_runtime(rtd) checks rtd pointer and freeing rtd->xxx, it doesn't work correctly in case of rtd allocation failed. We need to use device_unregister(dev) in such case. This patch fixup it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r1jxxldd.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 88694746dc11..236e075b9e57 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -470,8 +470,10 @@ static struct snd_soc_pcm_runtime *soc_new_pcm_runtime( dai_link->num_codecs + dai_link->num_platforms), GFP_KERNEL); - if (!rtd) - goto free_rtd; + if (!rtd) { + device_unregister(dev); + return NULL; + } rtd->dev = dev; INIT_LIST_HEAD(&rtd->list); From 2711a2d993036f26837e459ffb7b0d45c36b92a2 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:11 -0500 Subject: [PATCH 0561/1091] ASoC: amd: renoir: acp3x-pdm-dma: remove unnecessary assignments cppcheck warning: sound/soc/amd/renoir/acp3x-pdm-dma.c:132:17: style: Variable 'pdm_dma_enable' is assigned a value that is never used. [unreadVariable] pdm_dma_enable = 0x00; ^ sound/soc/amd/renoir/acp3x-pdm-dma.c:156:18: style: Variable 'pdm_dma_enable' is assigned a value that is never used. [unreadVariable] pdm_dma_enable = 0x00; ^ indeed those values are never used because the timeout is reset. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 7b14d9a81b97..1acd20439399 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -129,7 +129,6 @@ static int start_pdm_dma(void __iomem *acp_base) enable_pdm_clock(acp_base); rn_writel(pdm_enable, acp_base + ACP_WOV_PDM_ENABLE); rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); - pdm_dma_enable = 0x00; timeout = 0; while (++timeout < ACP_COUNTER) { pdm_dma_enable = rn_readl(acp_base + ACP_WOV_PDM_DMA_ENABLE); @@ -153,7 +152,6 @@ static int stop_pdm_dma(void __iomem *acp_base) if (pdm_dma_enable & 0x01) { pdm_dma_enable = 0x02; rn_writel(pdm_dma_enable, acp_base + ACP_WOV_PDM_DMA_ENABLE); - pdm_dma_enable = 0x00; timeout = 0; while (++timeout < ACP_COUNTER) { pdm_dma_enable = rn_readl(acp_base + From 86f3c05534bed54342ef6912b9da1d75f6b8d902 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:12 -0500 Subject: [PATCH 0562/1091] ASoC: atmel: fix shadowed variable Fix cppcheck warning: sound/soc/atmel/atmel-classd.c:51:14: style: Local variable 'pwm_type' shadows outer variable [shadowVariable] const char *pwm_type; ^ sound/soc/atmel/atmel-classd.c:226:27: note: Shadowed declaration static const char * const pwm_type[] = { ^ sound/soc/atmel/atmel-classd.c:51:14: note: Shadow variable const char *pwm_type; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210326215927.936377-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-classd.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/atmel/atmel-classd.c b/sound/soc/atmel/atmel-classd.c index b1a28a9382fb..6023369e0f1a 100644 --- a/sound/soc/atmel/atmel-classd.c +++ b/sound/soc/atmel/atmel-classd.c @@ -48,7 +48,7 @@ static struct atmel_classd_pdata *atmel_classd_dt_init(struct device *dev) { struct device_node *np = dev->of_node; struct atmel_classd_pdata *pdata; - const char *pwm_type; + const char *pwm_type_s; int ret; if (!np) { @@ -60,8 +60,8 @@ static struct atmel_classd_pdata *atmel_classd_dt_init(struct device *dev) if (!pdata) return ERR_PTR(-ENOMEM); - ret = of_property_read_string(np, "atmel,pwm-type", &pwm_type); - if ((ret == 0) && (strcmp(pwm_type, "diff") == 0)) + ret = of_property_read_string(np, "atmel,pwm-type", &pwm_type_s); + if ((ret == 0) && (strcmp(pwm_type_s, "diff") == 0)) pdata->pwm_type = CLASSD_MR_PWMTYP_DIFF; else pdata->pwm_type = CLASSD_MR_PWMTYP_SINGLE; From 6692dc07fa113939fc2c15d58dc3b27e28fc767c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:13 -0500 Subject: [PATCH 0563/1091] ASoC: atmel: atmel-i2s: remove useless initialization Cppcheck complains: sound/soc/atmel/atmel-i2s.c:628:6: style: Redundant initialization for 'err'. The initialized value is overwritten before it is read. [redundantInitialization] err = devm_request_irq(&pdev->dev, irq, atmel_i2s_interrupt, 0, ^ sound/soc/atmel/atmel-i2s.c:598:10: note: err is initialized int err = -ENXIO; ^ sound/soc/atmel/atmel-i2s.c:628:6: note: err is overwritten err = devm_request_irq(&pdev->dev, irq, atmel_i2s_interrupt, 0, ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Codrin Ciubotariu Link: https://lore.kernel.org/r/20210326215927.936377-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/atmel/atmel-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/atmel/atmel-i2s.c b/sound/soc/atmel/atmel-i2s.c index 7c6187e41f2b..584656cc7d3c 100644 --- a/sound/soc/atmel/atmel-i2s.c +++ b/sound/soc/atmel/atmel-i2s.c @@ -595,7 +595,7 @@ static int atmel_i2s_probe(struct platform_device *pdev) struct regmap *regmap; void __iomem *base; int irq; - int err = -ENXIO; + int err; unsigned int pcm_flags = 0; unsigned int version; From ce36242046f272c7656f7b4c91ff7b4387f514b0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:14 -0500 Subject: [PATCH 0564/1091] ASoC: bcm: cygnus_ssp: remove useless initialization Cppcheck warning: sound/soc/bcm/cygnus-ssp.c:1364:6: style: Redundant initialization for 'err'. The initialized value is overwritten before it is read. [redundantInitialization] err = devm_snd_soc_register_component(dev, &cygnus_ssp_component, ^ sound/soc/bcm/cygnus-ssp.c:1313:10: note: err is initialized int err = -EINVAL; ^ sound/soc/bcm/cygnus-ssp.c:1364:6: note: err is overwritten err = devm_snd_soc_register_component(dev, &cygnus_ssp_component, ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/bcm/cygnus-ssp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/bcm/cygnus-ssp.c b/sound/soc/bcm/cygnus-ssp.c index 6e634b448293..fea296b41a43 100644 --- a/sound/soc/bcm/cygnus-ssp.c +++ b/sound/soc/bcm/cygnus-ssp.c @@ -1310,7 +1310,7 @@ static int cygnus_ssp_probe(struct platform_device *pdev) struct device_node *child_node; struct resource *res; struct cygnus_audio *cygaud; - int err = -EINVAL; + int err; int node_count; int active_port_count; From 84d0493f67b856e5909c18e15b7ce78391565057 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:15 -0500 Subject: [PATCH 0565/1091] ASoC: meson: axg-tdmin: remove useless assignment cppcheck complains about potential null pointer dereference but it's rather an unnecessary assignment to NULL before walking through a list. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdmin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/axg-tdmin.c b/sound/soc/meson/axg-tdmin.c index b4faf9d5c1aa..49b613a1faf2 100644 --- a/sound/soc/meson/axg-tdmin.c +++ b/sound/soc/meson/axg-tdmin.c @@ -57,7 +57,7 @@ static const struct snd_kcontrol_new axg_tdmin_in_mux = static struct snd_soc_dai * axg_tdmin_get_be(struct snd_soc_dapm_widget *w) { - struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dapm_path *p; struct snd_soc_dai *be; snd_soc_dapm_widget_for_each_source_path(w, p) { From 18efddee4f0a8820a4ba0215655bbafd479025bf Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:16 -0500 Subject: [PATCH 0566/1091] ASoC: meson: axg-tdmout: remove useless assignment cppcheck complains about potential null pointer dereference but it's rather an unnecessary assignment to NULL before walking through a list. Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-7-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-tdmout.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/meson/axg-tdmout.c b/sound/soc/meson/axg-tdmout.c index 3ceabddae629..22d519fc07b2 100644 --- a/sound/soc/meson/axg-tdmout.c +++ b/sound/soc/meson/axg-tdmout.c @@ -55,7 +55,7 @@ static const struct regmap_config axg_tdmout_regmap_cfg = { static struct snd_soc_dai * axg_tdmout_get_be(struct snd_soc_dapm_widget *w) { - struct snd_soc_dapm_path *p = NULL; + struct snd_soc_dapm_path *p; struct snd_soc_dai *be; snd_soc_dapm_widget_for_each_sink_path(w, p) { From 00a25480cca4a094765084964c753c8f28e0f6fd Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:17 -0500 Subject: [PATCH 0567/1091] ASoC: pxa: remove useless assignment cppcheck warning: sound/soc/pxa/mmp-pcm.c:207:10: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int ret = 0, stream; ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-8-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/pxa/mmp-pcm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/pxa/mmp-pcm.c b/sound/soc/pxa/mmp-pcm.c index 53fc49e32fbc..5d520e18e512 100644 --- a/sound/soc/pxa/mmp-pcm.c +++ b/sound/soc/pxa/mmp-pcm.c @@ -204,7 +204,7 @@ static int mmp_pcm_new(struct snd_soc_component *component, { struct snd_pcm_substream *substream; struct snd_pcm *pcm = rtd->pcm; - int ret = 0, stream; + int ret, stream; for (stream = 0; stream < 2; stream++) { substream = pcm->streams[stream].substream; From bf2a6b44d5e56a12dde6438a2d092475e54d1923 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:18 -0500 Subject: [PATCH 0568/1091] ASoC: sti: sti_uniperif: add missing error check cppcheck warning: sound/soc/sti/sti_uniperif.c:490:6: style: Variable 'ret' is reassigned a value before the old one has been used. [redundantAssignment] ret = devm_snd_soc_register_component(&pdev->dev, ^ sound/soc/sti/sti_uniperif.c:486:6: note: ret is assigned ret = sti_uniperiph_cpu_dai_of(node, priv); ^ sound/soc/sti/sti_uniperif.c:490:6: note: ret is overwritten ret = devm_snd_soc_register_component(&pdev->dev, ^ sti_uniperiph_cpu_dai_of() can return -EINVAL which seems like a good-enough reason to bail. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20210326215927.936377-9-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sti/sti_uniperif.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index 7b9169f04d6e..67315d9b352d 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c @@ -484,6 +484,8 @@ static int sti_uniperiph_probe(struct platform_device *pdev) priv->pdev = pdev; ret = sti_uniperiph_cpu_dai_of(node, priv); + if (ret < 0) + return ret; dev_set_drvdata(&pdev->dev, priv); From 00a820086ddd8c6f3eeeca3a034d234cebf084ba Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:19 -0500 Subject: [PATCH 0569/1091] ASoC: sti: uniperif: align function prototypes cppcheck warning: sound/soc/sti/uniperif_player.c:1049:24: style:inconclusive: Function 'uni_player_init' argument 2 names different: declaration 'uni_player' definition 'player'. [funcArgNamesDifferent] struct uniperif *player) ^ sound/soc/sti/uniperif.h:1375:24: note: Function 'uni_player_init' argument 2 names different: declaration 'uni_player' definition 'player'. struct uniperif *uni_player); ^ sound/soc/sti/uniperif_player.c:1049:24: note: Function 'uni_player_init' argument 2 names different: declaration 'uni_player' definition 'player'. struct uniperif *player) ^ sound/soc/sti/uniperif_reader.c:411:24: style:inconclusive: Function 'uni_reader_init' argument 2 names different: declaration 'uni_reader' definition 'reader'. [funcArgNamesDifferent] struct uniperif *reader) ^ sound/soc/sti/uniperif.h:1380:24: note: Function 'uni_reader_init' argument 2 names different: declaration 'uni_reader' definition 'reader'. struct uniperif *uni_reader); ^ sound/soc/sti/uniperif_reader.c:411:24: note: Function 'uni_reader_init' argument 2 names different: declaration 'uni_reader' definition 'reader'. struct uniperif *reader) ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20210326215927.936377-10-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sti/uniperif.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/sti/uniperif.h b/sound/soc/sti/uniperif.h index a16adeb7c1e9..2a5de328501c 100644 --- a/sound/soc/sti/uniperif.h +++ b/sound/soc/sti/uniperif.h @@ -1372,12 +1372,12 @@ static __maybe_unused const struct snd_pcm_hardware uni_tdm_hw = { /* uniperiph player*/ int uni_player_init(struct platform_device *pdev, - struct uniperif *uni_player); + struct uniperif *player); int uni_player_resume(struct uniperif *player); /* uniperiph reader */ int uni_reader_init(struct platform_device *pdev, - struct uniperif *uni_reader); + struct uniperif *reader); /* common */ int sti_uniperiph_dai_set_fmt(struct snd_soc_dai *dai, From 11033e51b31696fd7949f1abb558cba171ecf0f5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:20 -0500 Subject: [PATCH 0570/1091] ASoC: stm: stm32_adfsdm: fix snprintf format string cppcheck warning: sound/soc/stm/stm32_adfsdm.c:120:2: warning: %d in format string (no. 1) requires 'int' but the argument type is 'unsigned int'. [invalidPrintfArgType_sint] snprintf(str_freq, sizeof(str_freq), "%d\n", freq); ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-11-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_adfsdm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/stm/stm32_adfsdm.c b/sound/soc/stm/stm32_adfsdm.c index 47fae8dd20b4..e6078f50e508 100644 --- a/sound/soc/stm/stm32_adfsdm.c +++ b/sound/soc/stm/stm32_adfsdm.c @@ -117,7 +117,7 @@ static int stm32_adfsdm_set_sysclk(struct snd_soc_dai *dai, int clk_id, /* Set IIO frequency if CODEC is master as clock comes from SPI_IN */ - snprintf(str_freq, sizeof(str_freq), "%d\n", freq); + snprintf(str_freq, sizeof(str_freq), "%u\n", freq); size = iio_write_channel_ext_info(priv->iio_ch, "spi_clk_freq", str_freq, sizeof(str_freq)); if (size != sizeof(str_freq)) { From 54f78aebe803b12e06d49988be88d87823ca16ab Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:21 -0500 Subject: [PATCH 0571/1091] ASoC: sunxi: sun8i-codec: clarify expression cppcheck warning: sound/soc/sunxi/sun8i-codec.c:488:28: style: Clarify calculation precedence for '%' and '?'. [clarifyCalculation] return sample_rate % 4000 ? 22579200 : 24576000; ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Maxime Ripard Link: https://lore.kernel.org/r/20210326215927.936377-12-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sunxi/sun8i-codec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sunxi/sun8i-codec.c b/sound/soc/sunxi/sun8i-codec.c index 460924fc173f..518bfb724a5b 100644 --- a/sound/soc/sunxi/sun8i-codec.c +++ b/sound/soc/sunxi/sun8i-codec.c @@ -485,7 +485,7 @@ static int sun8i_codec_get_lrck_div_order(unsigned int slots, static unsigned int sun8i_codec_get_sysclk_rate(unsigned int sample_rate) { - return sample_rate % 4000 ? 22579200 : 24576000; + return (sample_rate % 4000) ? 22579200 : 24576000; } static int sun8i_codec_hw_params(struct snd_pcm_substream *substream, From 1bc6d7a90b01e30123578761f5e70548ad894445 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:22 -0500 Subject: [PATCH 0572/1091] ASoC: tegra: tegra20_das: clarify expression cppcheck warning: sound/soc/tegra/tegra20_das.c:64:60: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] reg = otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P | ^ sound/soc/tegra/tegra20_das.c:65:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] !!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P | ^ sound/soc/tegra/tegra20_das.c:66:61: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] !!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P | ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20210326215927.936377-13-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_das.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/tegra/tegra20_das.c b/sound/soc/tegra/tegra20_das.c index 79dba878d854..69c651274c12 100644 --- a/sound/soc/tegra/tegra20_das.c +++ b/sound/soc/tegra/tegra20_das.c @@ -61,10 +61,10 @@ int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master, addr = TEGRA20_DAS_DAP_CTRL_SEL + (dap * TEGRA20_DAS_DAP_CTRL_SEL_STRIDE); - reg = otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P | - !!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P | - !!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P | - !!master << TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P; + reg = (otherdap << TEGRA20_DAS_DAP_CTRL_SEL_DAP_CTRL_SEL_P) | + (!!sdata2rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA2_TX_RX_P) | + (!!sdata1rx << TEGRA20_DAS_DAP_CTRL_SEL_DAP_SDATA1_TX_RX_P) | + (!!master << TEGRA20_DAS_DAP_CTRL_SEL_DAP_MS_SEL_P); tegra20_das_write(addr, reg); From 53567ebce407639e3657b5c232bd60970a66f82c Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:23 -0500 Subject: [PATCH 0573/1091] ASoC: tegra: tegra20_das: align function prototypes cppcheck warnings: sound/soc/tegra/tegra20_das.c:35:40: style:inconclusive: Function 'tegra20_das_connect_dap_to_dac' argument 1 names different: declaration 'dap_id' definition 'dap'. [funcArgNamesDifferent] int tegra20_das_connect_dap_to_dac(int dap, int dac) ^ sound/soc/tegra/tegra20_das.h:98:47: note: Function 'tegra20_das_connect_dap_to_dac' argument 1 names different: declaration 'dap_id' definition 'dap'. extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel); ^ sound/soc/tegra/tegra20_das.c:35:40: note: Function 'tegra20_das_connect_dap_to_dac' argument 1 names different: declaration 'dap_id' definition 'dap'. int tegra20_das_connect_dap_to_dac(int dap, int dac) ^ sound/soc/tegra/tegra20_das.c:35:49: style:inconclusive: Function 'tegra20_das_connect_dap_to_dac' argument 2 names different: declaration 'dac_sel' definition 'dac'. [funcArgNamesDifferent] int tegra20_das_connect_dap_to_dac(int dap, int dac) ^ sound/soc/tegra/tegra20_das.h:98:59: note: Function 'tegra20_das_connect_dap_to_dac' argument 2 names different: declaration 'dac_sel' definition 'dac'. extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel); ^ sound/soc/tegra/tegra20_das.c:35:49: note: Function 'tegra20_das_connect_dap_to_dac' argument 2 names different: declaration 'dac_sel' definition 'dac'. int tegra20_das_connect_dap_to_dac(int dap, int dac) ^ sound/soc/tegra/tegra20_das.c:53:40: style:inconclusive: Function 'tegra20_das_connect_dap_to_dap' argument 1 names different: declaration 'dap_id' definition 'dap'. [funcArgNamesDifferent] int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master, ^ sound/soc/tegra/tegra20_das.h:108:47: note: Function 'tegra20_das_connect_dap_to_dap' argument 1 names different: declaration 'dap_id' definition 'dap'. extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel, ^ sound/soc/tegra/tegra20_das.c:53:40: note: Function 'tegra20_das_connect_dap_to_dap' argument 1 names different: declaration 'dap_id' definition 'dap'. int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master, ^ sound/soc/tegra/tegra20_das.c:53:49: style:inconclusive: Function 'tegra20_das_connect_dap_to_dap' argument 2 names different: declaration 'other_dap_sel' definition 'otherdap'. [funcArgNamesDifferent] int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master, ^ sound/soc/tegra/tegra20_das.h:108:59: note: Function 'tegra20_das_connect_dap_to_dap' argument 2 names different: declaration 'other_dap_sel' definition 'otherdap'. extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel, ^ sound/soc/tegra/tegra20_das.c:53:49: note: Function 'tegra20_das_connect_dap_to_dap' argument 2 names different: declaration 'other_dap_sel' definition 'otherdap'. int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master, ^ sound/soc/tegra/tegra20_das.c:75:40: style:inconclusive: Function 'tegra20_das_connect_dac_to_dap' argument 1 names different: declaration 'dac_id' definition 'dac'. [funcArgNamesDifferent] int tegra20_das_connect_dac_to_dap(int dac, int dap) ^ sound/soc/tegra/tegra20_das.h:118:47: note: Function 'tegra20_das_connect_dac_to_dap' argument 1 names different: declaration 'dac_id' definition 'dac'. extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel); ^ sound/soc/tegra/tegra20_das.c:75:40: note: Function 'tegra20_das_connect_dac_to_dap' argument 1 names different: declaration 'dac_id' definition 'dac'. int tegra20_das_connect_dac_to_dap(int dac, int dap) ^ sound/soc/tegra/tegra20_das.c:75:49: style:inconclusive: Function 'tegra20_das_connect_dac_to_dap' argument 2 names different: declaration 'dap_sel' definition 'dap'. [funcArgNamesDifferent] int tegra20_das_connect_dac_to_dap(int dac, int dap) ^ sound/soc/tegra/tegra20_das.h:118:59: note: Function 'tegra20_das_connect_dac_to_dap' argument 2 names different: declaration 'dap_sel' definition 'dap'. extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel); ^ sound/soc/tegra/tegra20_das.c:75:49: note: Function 'tegra20_das_connect_dac_to_dap' argument 2 names different: declaration 'dap_sel' definition 'dap'. int tegra20_das_connect_dac_to_dap(int dac, int dap) ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20210326215927.936377-14-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_das.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/tegra/tegra20_das.h b/sound/soc/tegra/tegra20_das.h index d22abc4d08e6..18e832ded73a 100644 --- a/sound/soc/tegra/tegra20_das.h +++ b/sound/soc/tegra/tegra20_das.h @@ -95,7 +95,7 @@ struct tegra20_das { * dap_id: DAP to connect: TEGRA20_DAS_DAP_ID_* * dac_sel: DAC to connect to: TEGRA20_DAS_DAP_SEL_DAC* */ -extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel); +extern int tegra20_das_connect_dap_to_dac(int dap, int dac); /* * Connect a DAP to another DAP @@ -105,7 +105,7 @@ extern int tegra20_das_connect_dap_to_dac(int dap_id, int dac_sel); * sdata1rx: Is this DAP's SDATA1 pin RX (1) or TX (0) * sdata2rx: Is this DAP's SDATA2 pin RX (1) or TX (0) */ -extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel, +extern int tegra20_das_connect_dap_to_dap(int dap, int otherdap, int master, int sdata1rx, int sdata2rx); @@ -115,6 +115,6 @@ extern int tegra20_das_connect_dap_to_dap(int dap_id, int other_dap_sel, * dac_id: DAC ID to connect: TEGRA20_DAS_DAC_ID_* * dap_sel: DAP to receive input from: TEGRA20_DAS_DAC_SEL_DAP* */ -extern int tegra20_das_connect_dac_to_dap(int dac_id, int dap_sel); +extern int tegra20_das_connect_dac_to_dap(int dac, int dap); #endif From 248d4dc9c3b8ced2cb274581d1c306e7ec617aec Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:24 -0500 Subject: [PATCH 0574/1091] ASoC: ti: omap-abe-twl6040: remove useless assignment cppcheck warning: sound/soc/ti/omap-abe-twl6040.c:173:10: style: Variable 'ret' is assigned a value that is never used. [unreadVariable] int ret = 0; ^ Signed-off-by: Pierre-Louis Bossart Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20210326215927.936377-15-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/ti/omap-abe-twl6040.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ti/omap-abe-twl6040.c b/sound/soc/ti/omap-abe-twl6040.c index 16ea039ff865..91cc9a4f44d7 100644 --- a/sound/soc/ti/omap-abe-twl6040.c +++ b/sound/soc/ti/omap-abe-twl6040.c @@ -170,7 +170,7 @@ static int omap_abe_twl6040_init(struct snd_soc_pcm_runtime *rtd) struct snd_soc_card *card = rtd->card; struct abe_twl6040 *priv = snd_soc_card_get_drvdata(card); int hs_trim; - int ret = 0; + int ret; /* * Configure McPDM offset cancellation based on the HSOTRIM value from From 3d37b27fffb311c521d61144e57ea4d40e31ab9b Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:25 -0500 Subject: [PATCH 0575/1091] ASoC: ti: omap-mcsp: remove duplicate test cppcheck warning: sound/soc/ti/omap-mcbsp.c:379:11: style: The if condition is the same as the previous if condition [duplicateCondition] if (mcbsp->irq) { ^ sound/soc/ti/omap-mcbsp.c:376:11: note: First condition if (mcbsp->irq) ^ sound/soc/ti/omap-mcbsp.c:379:11: note: Second condition if (mcbsp->irq) { ^ Keeping two separate tests was probably intentional for clarity, but since this generates warnings we might as well make cppcheck happy so that we have fewer warnings. Signed-off-by: Pierre-Louis Bossart Acked-by: Peter Ujfalusi Link: https://lore.kernel.org/r/20210326215927.936377-16-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/ti/omap-mcbsp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/sound/soc/ti/omap-mcbsp.c b/sound/soc/ti/omap-mcbsp.c index 6025b30bbe77..db47981768c5 100644 --- a/sound/soc/ti/omap-mcbsp.c +++ b/sound/soc/ti/omap-mcbsp.c @@ -373,10 +373,9 @@ static void omap_mcbsp_free(struct omap_mcbsp *mcbsp) MCBSP_WRITE(mcbsp, WAKEUPEN, 0); /* Disable interrupt requests */ - if (mcbsp->irq) + if (mcbsp->irq) { MCBSP_WRITE(mcbsp, IRQEN, 0); - if (mcbsp->irq) { free_irq(mcbsp->irq, (void *)mcbsp); } else { free_irq(mcbsp->rx_irq, (void *)mcbsp); From 5b920abeea03302e561b036181a6a5be4e53a584 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:26 -0500 Subject: [PATCH 0576/1091] ASoC: ux500: mop500: rename shadowing variable cppcheck warning: sound/soc/ux500/mop500.c:143:23: style: Local variable 'mop500_card' shadows outer variable [shadowVariable] struct snd_soc_card *mop500_card = platform_get_drvdata(pdev); ^ sound/soc/ux500/mop500.c:54:28: note: Shadowed declaration static struct snd_soc_card mop500_card = { ^ sound/soc/ux500/mop500.c:143:23: note: Shadow variable struct snd_soc_card *mop500_card = platform_get_drvdata(pdev); ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-17-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/ux500/mop500.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/ux500/mop500.c b/sound/soc/ux500/mop500.c index cdae1190b930..4f41bb0ab2b0 100644 --- a/sound/soc/ux500/mop500.c +++ b/sound/soc/ux500/mop500.c @@ -140,12 +140,12 @@ static int mop500_probe(struct platform_device *pdev) static int mop500_remove(struct platform_device *pdev) { - struct snd_soc_card *mop500_card = platform_get_drvdata(pdev); + struct snd_soc_card *card = platform_get_drvdata(pdev); pr_debug("%s: Enter.\n", __func__); - snd_soc_unregister_card(mop500_card); - mop500_ab8500_remove(mop500_card); + snd_soc_unregister_card(card); + mop500_ab8500_remove(card); mop500_of_node_put(); return 0; From b4d09a01666fdcab8866f44b72f79e106f14a48d Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 26 Mar 2021 16:59:27 -0500 Subject: [PATCH 0577/1091] ASoC: ux500: mop500: align function prototype cppcheck warning: sound/soc/ux500/mop500_ab8500.c:360:60: style:inconclusive: Function 'mop500_ab8500_machine_init' argument 1 names different: declaration 'runtime' definition 'rtd'. [funcArgNamesDifferent] int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) ^ sound/soc/ux500/mop500_ab8500.h:16:60: note: Function 'mop500_ab8500_machine_init' argument 1 names different: declaration 'runtime' definition 'rtd'. int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *runtime); ^ sound/soc/ux500/mop500_ab8500.c:360:60: note: Function 'mop500_ab8500_machine_init' argument 1 names different: declaration 'runtime' definition 'rtd'. int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd) ^ Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210326215927.936377-18-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/ux500/mop500_ab8500.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/ux500/mop500_ab8500.h b/sound/soc/ux500/mop500_ab8500.h index 99cfd972ea7a..8138a4e9aaf5 100644 --- a/sound/soc/ux500/mop500_ab8500.h +++ b/sound/soc/ux500/mop500_ab8500.h @@ -13,7 +13,7 @@ extern struct snd_soc_ops mop500_ab8500_ops[]; -int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *runtime); +int mop500_ab8500_machine_init(struct snd_soc_pcm_runtime *rtd); void mop500_ab8500_remove(struct snd_soc_card *card); #endif From bb0f78e59777d55e0065d16d070b5d43ae80b769 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Tue, 23 Mar 2021 02:31:05 +0530 Subject: [PATCH 0578/1091] ASoC: Intel: Fix a typo s/defintions/definitions/ Signed-off-by: Bhaskar Chowdhury Link: https://lore.kernel.org/r/20210322210105.1575758-1-unixbhaskar@gmail.com Signed-off-by: Mark Brown --- sound/soc/intel/skylake/skl.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/skylake/skl.h b/sound/soc/intel/skylake/skl.h index 857ea17e3c9f..33ed274fc0cb 100644 --- a/sound/soc/intel/skylake/skl.h +++ b/sound/soc/intel/skylake/skl.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * skl.h - HD Audio skylake defintions. + * skl.h - HD Audio skylake definitions. * * Copyright (C) 2015 Intel Corp * Author: Jeeja KP From 23cf00ddd2e1aacf1873e43f5e0c519c120daf7a Mon Sep 17 00:00:00 2001 From: Matti Vaittinen Date: Mon, 29 Mar 2021 14:41:12 +0300 Subject: [PATCH 0579/1091] gpio: sysfs: Obey valid_mask Do not allow exporting GPIOs which are set invalid by the driver's valid mask. Fixes: 726cb3ba4969 ("gpiolib: Support 'gpio-reserved-ranges' property") Signed-off-by: Matti Vaittinen Reviewed-by: Andy Shevchenko Signed-off-by: Bartosz Golaszewski --- drivers/gpio/gpiolib-sysfs.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/drivers/gpio/gpiolib-sysfs.c b/drivers/gpio/gpiolib-sysfs.c index 26c5466b8179..ae49bb23c6ed 100644 --- a/drivers/gpio/gpiolib-sysfs.c +++ b/drivers/gpio/gpiolib-sysfs.c @@ -458,6 +458,8 @@ static ssize_t export_store(struct class *class, long gpio; struct gpio_desc *desc; int status; + struct gpio_chip *gc; + int offset; status = kstrtol(buf, 0, &gpio); if (status < 0) @@ -469,6 +471,12 @@ static ssize_t export_store(struct class *class, pr_warn("%s: invalid GPIO %ld\n", __func__, gpio); return -EINVAL; } + gc = desc->gdev->chip; + offset = gpio_chip_hwgpio(desc); + if (!gpiochip_line_is_valid(gc, offset)) { + pr_warn("%s: GPIO %ld masked\n", __func__, gpio); + return -EINVAL; + } /* No extra locking here; FLAG_SYSFS just signifies that the * request and export were done by on behalf of userspace, so From d24f847e54214049814b9515771622eaab3f42ab Mon Sep 17 00:00:00 2001 From: Ariel Levkovich Date: Tue, 9 Mar 2021 01:29:01 +0200 Subject: [PATCH 0580/1091] net/mlx5e: Fix mapping of ct_label zero ct_label 0 is a default label each flow has and therefore there can be rules that match on ct_label=0 without a prior rule that set the ct_label to this value. The ct_label value is not used directly in the HW rules and instead it is mapped to some id within a defined range and this id is used to set and match the metadata register which carries the ct_label. If we have a rule that matches on ct_label=0, the hw rule will perform matching on a value that is != 0 because of the mapping from label to id. Since the metadata register default value is 0 and it was never set before to anything else by an action that sets the ct_label, there will always be a mismatch between that register and the value in the rule. To support such rule, a forced mapping of ct_label 0 to id=0 is done so that it will match the metadata register default value of 0. Fixes: 54b154ecfb8c ("net/mlx5e: CT: Map 128 bits labels to 32 bit map ID") Signed-off-by: Ariel Levkovich Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en/tc_ct.c | 36 +++++++++++++++---- 1 file changed, 29 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c index b2cd29847a37..68e54cc1cd16 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_ct.c @@ -185,6 +185,28 @@ mlx5_tc_ct_entry_has_nat(struct mlx5_ct_entry *entry) return !!(entry->tuple_nat_node.next); } +static int +mlx5_get_label_mapping(struct mlx5_tc_ct_priv *ct_priv, + u32 *labels, u32 *id) +{ + if (!memchr_inv(labels, 0, sizeof(u32) * 4)) { + *id = 0; + return 0; + } + + if (mapping_add(ct_priv->labels_mapping, labels, id)) + return -EOPNOTSUPP; + + return 0; +} + +static void +mlx5_put_label_mapping(struct mlx5_tc_ct_priv *ct_priv, u32 id) +{ + if (id) + mapping_remove(ct_priv->labels_mapping, id); +} + static int mlx5_tc_ct_rule_to_tuple(struct mlx5_ct_tuple *tuple, struct flow_rule *rule) { @@ -436,7 +458,7 @@ mlx5_tc_ct_entry_del_rule(struct mlx5_tc_ct_priv *ct_priv, mlx5_tc_rule_delete(netdev_priv(ct_priv->netdev), zone_rule->rule, attr); mlx5e_mod_hdr_detach(ct_priv->dev, ct_priv->mod_hdr_tbl, zone_rule->mh); - mapping_remove(ct_priv->labels_mapping, attr->ct_attr.ct_labels_id); + mlx5_put_label_mapping(ct_priv, attr->ct_attr.ct_labels_id); kfree(attr); } @@ -639,8 +661,8 @@ mlx5_tc_ct_entry_create_mod_hdr(struct mlx5_tc_ct_priv *ct_priv, if (!meta) return -EOPNOTSUPP; - err = mapping_add(ct_priv->labels_mapping, meta->ct_metadata.labels, - &attr->ct_attr.ct_labels_id); + err = mlx5_get_label_mapping(ct_priv, meta->ct_metadata.labels, + &attr->ct_attr.ct_labels_id); if (err) return -EOPNOTSUPP; if (nat) { @@ -677,7 +699,7 @@ mlx5_tc_ct_entry_create_mod_hdr(struct mlx5_tc_ct_priv *ct_priv, err_mapping: dealloc_mod_hdr_actions(&mod_acts); - mapping_remove(ct_priv->labels_mapping, attr->ct_attr.ct_labels_id); + mlx5_put_label_mapping(ct_priv, attr->ct_attr.ct_labels_id); return err; } @@ -745,7 +767,7 @@ mlx5_tc_ct_entry_add_rule(struct mlx5_tc_ct_priv *ct_priv, err_rule: mlx5e_mod_hdr_detach(ct_priv->dev, ct_priv->mod_hdr_tbl, zone_rule->mh); - mapping_remove(ct_priv->labels_mapping, attr->ct_attr.ct_labels_id); + mlx5_put_label_mapping(ct_priv, attr->ct_attr.ct_labels_id); err_mod_hdr: kfree(attr); err_attr: @@ -1197,7 +1219,7 @@ void mlx5_tc_ct_match_del(struct mlx5_tc_ct_priv *priv, struct mlx5_ct_attr *ct_ if (!priv || !ct_attr->ct_labels_id) return; - mapping_remove(priv->labels_mapping, ct_attr->ct_labels_id); + mlx5_put_label_mapping(priv, ct_attr->ct_labels_id); } int @@ -1280,7 +1302,7 @@ mlx5_tc_ct_match_add(struct mlx5_tc_ct_priv *priv, ct_labels[1] = key->ct_labels[1] & mask->ct_labels[1]; ct_labels[2] = key->ct_labels[2] & mask->ct_labels[2]; ct_labels[3] = key->ct_labels[3] & mask->ct_labels[3]; - if (mapping_add(priv->labels_mapping, ct_labels, &ct_attr->ct_labels_id)) + if (mlx5_get_label_mapping(priv, ct_labels, &ct_attr->ct_labels_id)) return -EOPNOTSUPP; mlx5e_tc_match_to_reg_match(spec, LABELS_TO_REG, ct_attr->ct_labels_id, MLX5_CT_LABELS_MASK); From 1f90aedfb496ccccf862c7b7c0889af20c2fc61a Mon Sep 17 00:00:00 2001 From: Maor Dickman Date: Mon, 22 Mar 2021 17:22:03 +0200 Subject: [PATCH 0581/1091] net/mlx5: Delete auxiliary bus driver eth-rep first Delete auxiliary bus drivers flow deletes the eth driver first and then the eth-reps driver but eth-reps devices resources are depend on eth device. Fixed by changing the delete order of auxiliary bus drivers to delete the eth-rep driver first and after it the eth driver. Fixes: 601c10c89cbb ("net/mlx5: Delete custom device management logic") Signed-off-by: Maor Dickman Reviewed-by: Leon Romanovsky Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/dev.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/dev.c b/drivers/net/ethernet/mellanox/mlx5/core/dev.c index b051417ede67..9153c9bda96f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/dev.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/dev.c @@ -191,12 +191,12 @@ static bool is_ib_supported(struct mlx5_core_dev *dev) } enum { - MLX5_INTERFACE_PROTOCOL_ETH_REP, MLX5_INTERFACE_PROTOCOL_ETH, + MLX5_INTERFACE_PROTOCOL_ETH_REP, + MLX5_INTERFACE_PROTOCOL_IB, MLX5_INTERFACE_PROTOCOL_IB_REP, MLX5_INTERFACE_PROTOCOL_MPIB, - MLX5_INTERFACE_PROTOCOL_IB, MLX5_INTERFACE_PROTOCOL_VNET, }; From 3211434dfe7a66fcf55e43961ea524b78336c04c Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Wed, 24 Mar 2021 12:25:06 +0200 Subject: [PATCH 0582/1091] net/mlx5e: Fix ethtool indication of connector type Use connector_type read from PTYS register when it's valid, based on corresponding capability bit. Fixes: 5b4793f81745 ("net/mlx5e: Add support for reading connector type from PTYS") Signed-off-by: Aya Levin Reviewed-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en_ethtool.c | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c index f5f2a8fd0046..53802e18af90 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_ethtool.c @@ -758,11 +758,11 @@ static int get_fec_supported_advertised(struct mlx5_core_dev *dev, return 0; } -static void ptys2ethtool_supported_advertised_port(struct ethtool_link_ksettings *link_ksettings, - u32 eth_proto_cap, - u8 connector_type, bool ext) +static void ptys2ethtool_supported_advertised_port(struct mlx5_core_dev *mdev, + struct ethtool_link_ksettings *link_ksettings, + u32 eth_proto_cap, u8 connector_type) { - if ((!connector_type && !ext) || connector_type >= MLX5E_CONNECTOR_TYPE_NUMBER) { + if (!MLX5_CAP_PCAM_FEATURE(mdev, ptys_connector_type)) { if (eth_proto_cap & (MLX5E_PROT_MASK(MLX5E_10GBASE_CR) | MLX5E_PROT_MASK(MLX5E_10GBASE_SR) | MLX5E_PROT_MASK(MLX5E_40GBASE_CR4) @@ -898,9 +898,9 @@ static int ptys2connector_type[MLX5E_CONNECTOR_TYPE_NUMBER] = { [MLX5E_PORT_OTHER] = PORT_OTHER, }; -static u8 get_connector_port(u32 eth_proto, u8 connector_type, bool ext) +static u8 get_connector_port(struct mlx5_core_dev *mdev, u32 eth_proto, u8 connector_type) { - if ((connector_type || ext) && connector_type < MLX5E_CONNECTOR_TYPE_NUMBER) + if (MLX5_CAP_PCAM_FEATURE(mdev, ptys_connector_type)) return ptys2connector_type[connector_type]; if (eth_proto & @@ -1001,11 +1001,11 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv, data_rate_oper, link_ksettings); eth_proto_oper = eth_proto_oper ? eth_proto_oper : eth_proto_cap; - - link_ksettings->base.port = get_connector_port(eth_proto_oper, - connector_type, ext); - ptys2ethtool_supported_advertised_port(link_ksettings, eth_proto_admin, - connector_type, ext); + connector_type = connector_type < MLX5E_CONNECTOR_TYPE_NUMBER ? + connector_type : MLX5E_PORT_UNKNOWN; + link_ksettings->base.port = get_connector_port(mdev, eth_proto_oper, connector_type); + ptys2ethtool_supported_advertised_port(mdev, link_ksettings, eth_proto_admin, + connector_type); get_lp_advertising(mdev, eth_proto_lp, link_ksettings); if (an_status == MLX5_AN_COMPLETE) From e929e3da537e3c2d97aabbd00530040997dde9ce Mon Sep 17 00:00:00 2001 From: Maor Dickman Date: Mon, 15 Mar 2021 15:20:29 +0200 Subject: [PATCH 0583/1091] net/mlx5: E-switch, Create vport miss group only if src rewrite is supported Create send to vport miss group was added in order to support traffic recirculation to root table with metadata source rewrite. This group is created also in case source rewrite isn't supported. Fixed by creating send to vport miss group only if source rewrite is supported by FW. Fixes: 8e404fefa58b ("net/mlx5e: Match recirculated packet miss in slow table using reg_c1") Signed-off-by: Maor Dickman Reviewed-by: Vlad Buslov Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- .../mellanox/mlx5/core/eswitch_offloads.c | 66 +++++++++++-------- 1 file changed, 38 insertions(+), 28 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c index 8694b83968b4..d4a2f8d1ee9f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eswitch_offloads.c @@ -537,6 +537,14 @@ esw_setup_vport_dests(struct mlx5_flow_destination *dest, struct mlx5_flow_act * return i; } +static bool +esw_src_port_rewrite_supported(struct mlx5_eswitch *esw) +{ + return MLX5_CAP_GEN(esw->dev, reg_c_preserve) && + mlx5_eswitch_vport_match_metadata_enabled(esw) && + MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level); +} + static int esw_setup_dests(struct mlx5_flow_destination *dest, struct mlx5_flow_act *flow_act, @@ -550,9 +558,7 @@ esw_setup_dests(struct mlx5_flow_destination *dest, int err = 0; if (!mlx5_eswitch_termtbl_required(esw, attr, flow_act, spec) && - MLX5_CAP_GEN(esw_attr->in_mdev, reg_c_preserve) && - mlx5_eswitch_vport_match_metadata_enabled(esw) && - MLX5_CAP_ESW_FLOWTABLE_FDB(esw->dev, ignore_flow_level)) + esw_src_port_rewrite_supported(esw)) attr->flags |= MLX5_ESW_ATTR_FLAG_SRC_REWRITE; if (attr->dest_ft) { @@ -1716,36 +1722,40 @@ static int esw_create_offloads_fdb_tables(struct mlx5_eswitch *esw) } esw->fdb_table.offloads.send_to_vport_grp = g; - /* meta send to vport */ - memset(flow_group_in, 0, inlen); - MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, - MLX5_MATCH_MISC_PARAMETERS_2); + if (esw_src_port_rewrite_supported(esw)) { + /* meta send to vport */ + memset(flow_group_in, 0, inlen); + MLX5_SET(create_flow_group_in, flow_group_in, match_criteria_enable, + MLX5_MATCH_MISC_PARAMETERS_2); - match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria); + match_criteria = MLX5_ADDR_OF(create_flow_group_in, flow_group_in, match_criteria); - MLX5_SET(fte_match_param, match_criteria, - misc_parameters_2.metadata_reg_c_0, mlx5_eswitch_get_vport_metadata_mask()); - MLX5_SET(fte_match_param, match_criteria, - misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK); + MLX5_SET(fte_match_param, match_criteria, + misc_parameters_2.metadata_reg_c_0, + mlx5_eswitch_get_vport_metadata_mask()); + MLX5_SET(fte_match_param, match_criteria, + misc_parameters_2.metadata_reg_c_1, ESW_TUN_MASK); - num_vfs = esw->esw_funcs.num_vfs; - if (num_vfs) { - MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix); - MLX5_SET(create_flow_group_in, flow_group_in, end_flow_index, ix + num_vfs - 1); - ix += num_vfs; + num_vfs = esw->esw_funcs.num_vfs; + if (num_vfs) { + MLX5_SET(create_flow_group_in, flow_group_in, start_flow_index, ix); + MLX5_SET(create_flow_group_in, flow_group_in, + end_flow_index, ix + num_vfs - 1); + ix += num_vfs; - g = mlx5_create_flow_group(fdb, flow_group_in); - if (IS_ERR(g)) { - err = PTR_ERR(g); - esw_warn(dev, "Failed to create send-to-vport meta flow group err(%d)\n", - err); - goto send_vport_meta_err; + g = mlx5_create_flow_group(fdb, flow_group_in); + if (IS_ERR(g)) { + err = PTR_ERR(g); + esw_warn(dev, "Failed to create send-to-vport meta flow group err(%d)\n", + err); + goto send_vport_meta_err; + } + esw->fdb_table.offloads.send_to_vport_meta_grp = g; + + err = mlx5_eswitch_add_send_to_vport_meta_rules(esw); + if (err) + goto meta_rule_err; } - esw->fdb_table.offloads.send_to_vport_meta_grp = g; - - err = mlx5_eswitch_add_send_to_vport_meta_rules(esw); - if (err) - goto meta_rule_err; } if (MLX5_CAP_ESW(esw->dev, merged_eswitch)) { From a51bce9698e951fec3fc0624060f124794ec3558 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Sun, 28 Feb 2021 13:50:17 +0200 Subject: [PATCH 0584/1091] net/mlx5e: kTLS, Fix TX counters atomicity Some TLS TX counters increment per socket/connection, and are not protected against parallel modifications from several cores. Switch them to atomic counters by taking them out of the SQ stats into the global atomic TLS stats. In this patch, we touch a single counter 'tx_tls_ctx' that counts the number of device-offloaded TX TLS connections added. Now that this counter can be increased without the for having the SQ context in hand, move it to the mlx5e_ktls_add_tx() callback where it really belongs, out of the fast data-path. This change is not needed for counters that increment only in NAPI context or under the TX lock, as they are already protected. Keep them as tls_* counters under 'struct mlx5e_sq_stats'. Fixes: d2ead1f360e8 ("net/mlx5e: Add kTLS TX HW offload support") Signed-off-by: Tariq Toukan Reviewed-by: Maxim Mikityanskiy Signed-off-by: Saeed Mahameed --- .../mellanox/mlx5/core/en_accel/ktls_tx.c | 5 +- .../mellanox/mlx5/core/en_accel/tls.h | 1 + .../mellanox/mlx5/core/en_accel/tls_stats.c | 47 +++++++++++-------- .../ethernet/mellanox/mlx5/core/en_stats.c | 4 -- .../ethernet/mellanox/mlx5/core/en_stats.h | 2 - 5 files changed, 33 insertions(+), 26 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c index d16def68ecff..51bdf71073f3 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_tx.c @@ -1,6 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR Linux-OpenIB // Copyright (c) 2019 Mellanox Technologies. +#include "en_accel/tls.h" #include "en_accel/ktls_txrx.h" #include "en_accel/ktls_utils.h" @@ -50,6 +51,7 @@ static int mlx5e_ktls_create_tis(struct mlx5_core_dev *mdev, u32 *tisn) struct mlx5e_ktls_offload_context_tx { struct tls_offload_context_tx *tx_ctx; struct tls12_crypto_info_aes_gcm_128 crypto_info; + struct mlx5e_tls_sw_stats *sw_stats; u32 expected_seq; u32 tisn; u32 key_id; @@ -99,6 +101,7 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk, if (err) goto err_create_key; + priv_tx->sw_stats = &priv->tls->sw_stats; priv_tx->expected_seq = start_offload_tcp_sn; priv_tx->crypto_info = *(struct tls12_crypto_info_aes_gcm_128 *)crypto_info; @@ -111,6 +114,7 @@ int mlx5e_ktls_add_tx(struct net_device *netdev, struct sock *sk, goto err_create_tis; priv_tx->ctx_post_pending = true; + atomic64_inc(&priv_tx->sw_stats->tx_tls_ctx); return 0; @@ -452,7 +456,6 @@ bool mlx5e_ktls_handle_tx_skb(struct tls_context *tls_ctx, struct mlx5e_txqsq *s if (unlikely(mlx5e_ktls_tx_offload_test_and_clear_pending(priv_tx))) { mlx5e_ktls_tx_post_param_wqes(sq, priv_tx, false, false); - stats->tls_ctx++; } seq = ntohl(tcp_hdr(skb)->seq); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h index bd270a85c804..5b408904df14 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h @@ -41,6 +41,7 @@ #include "en.h" struct mlx5e_tls_sw_stats { + atomic64_t tx_tls_ctx; atomic64_t tx_tls_drop_metadata; atomic64_t tx_tls_drop_resync_alloc; atomic64_t tx_tls_drop_no_sync_data; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c index b949b9a7538b..a5aabc5c5236 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c @@ -45,49 +45,58 @@ static const struct counter_desc mlx5e_tls_sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_tls_sw_stats, tx_tls_drop_bypass_required) }, }; +static const struct counter_desc mlx5e_ktls_sw_stats_desc[] = { + { MLX5E_DECLARE_STAT(struct mlx5e_tls_sw_stats, tx_tls_ctx) }, +}; + #define MLX5E_READ_CTR_ATOMIC64(ptr, dsc, i) \ atomic64_read((atomic64_t *)((char *)(ptr) + (dsc)[i].offset)) -#define NUM_TLS_SW_COUNTERS ARRAY_SIZE(mlx5e_tls_sw_stats_desc) - -static bool is_tls_atomic_stats(struct mlx5e_priv *priv) +static const struct counter_desc *get_tls_atomic_stats(struct mlx5e_priv *priv) { - return priv->tls && !mlx5_accel_is_ktls_device(priv->mdev); + if (!priv->tls) + return NULL; + if (mlx5_accel_is_ktls_device(priv->mdev)) + return mlx5e_ktls_sw_stats_desc; + return mlx5e_tls_sw_stats_desc; } int mlx5e_tls_get_count(struct mlx5e_priv *priv) { - if (!is_tls_atomic_stats(priv)) + if (!priv->tls) return 0; - - return NUM_TLS_SW_COUNTERS; + if (mlx5_accel_is_ktls_device(priv->mdev)) + return ARRAY_SIZE(mlx5e_ktls_sw_stats_desc); + return ARRAY_SIZE(mlx5e_tls_sw_stats_desc); } int mlx5e_tls_get_strings(struct mlx5e_priv *priv, uint8_t *data) { - unsigned int i, idx = 0; + const struct counter_desc *stats_desc; + unsigned int i, n, idx = 0; - if (!is_tls_atomic_stats(priv)) - return 0; + stats_desc = get_tls_atomic_stats(priv); + n = mlx5e_tls_get_count(priv); - for (i = 0; i < NUM_TLS_SW_COUNTERS; i++) + for (i = 0; i < n; i++) strcpy(data + (idx++) * ETH_GSTRING_LEN, - mlx5e_tls_sw_stats_desc[i].format); + stats_desc[i].format); - return NUM_TLS_SW_COUNTERS; + return n; } int mlx5e_tls_get_stats(struct mlx5e_priv *priv, u64 *data) { - int i, idx = 0; + const struct counter_desc *stats_desc; + unsigned int i, n, idx = 0; - if (!is_tls_atomic_stats(priv)) - return 0; + stats_desc = get_tls_atomic_stats(priv); + n = mlx5e_tls_get_count(priv); - for (i = 0; i < NUM_TLS_SW_COUNTERS; i++) + for (i = 0; i < n; i++) data[idx++] = MLX5E_READ_CTR_ATOMIC64(&priv->tls->sw_stats, - mlx5e_tls_sw_stats_desc, i); + stats_desc, i); - return NUM_TLS_SW_COUNTERS; + return n; } diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 92c5b81427b9..74adaa58189a 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -116,7 +116,6 @@ static const struct counter_desc sw_stats_desc[] = { #ifdef CONFIG_MLX5_EN_TLS { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_packets) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_encrypted_bytes) }, - { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ctx) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_ooo) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_packets) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, tx_tls_dump_bytes) }, @@ -390,7 +389,6 @@ static void mlx5e_stats_grp_sw_update_stats_sq(struct mlx5e_sw_stats *s, #ifdef CONFIG_MLX5_EN_TLS s->tx_tls_encrypted_packets += sq_stats->tls_encrypted_packets; s->tx_tls_encrypted_bytes += sq_stats->tls_encrypted_bytes; - s->tx_tls_ctx += sq_stats->tls_ctx; s->tx_tls_ooo += sq_stats->tls_ooo; s->tx_tls_dump_bytes += sq_stats->tls_dump_bytes; s->tx_tls_dump_packets += sq_stats->tls_dump_packets; @@ -1650,7 +1648,6 @@ static const struct counter_desc sq_stats_desc[] = { #ifdef CONFIG_MLX5_EN_TLS { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_packets) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_bytes) }, - { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ctx) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_ooo) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_packets) }, { MLX5E_DECLARE_TX_STAT(struct mlx5e_sq_stats, tls_dump_bytes) }, @@ -1776,7 +1773,6 @@ static const struct counter_desc qos_sq_stats_desc[] = { #ifdef CONFIG_MLX5_EN_TLS { MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_packets) }, { MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, tls_encrypted_bytes) }, - { MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, tls_ctx) }, { MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, tls_ooo) }, { MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, tls_dump_packets) }, { MLX5E_DECLARE_QOS_TX_STAT(struct mlx5e_sq_stats, tls_dump_bytes) }, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 93c41312fb03..8eb056af79ba 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -191,7 +191,6 @@ struct mlx5e_sw_stats { #ifdef CONFIG_MLX5_EN_TLS u64 tx_tls_encrypted_packets; u64 tx_tls_encrypted_bytes; - u64 tx_tls_ctx; u64 tx_tls_ooo; u64 tx_tls_dump_packets; u64 tx_tls_dump_bytes; @@ -364,7 +363,6 @@ struct mlx5e_sq_stats { #ifdef CONFIG_MLX5_EN_TLS u64 tls_encrypted_packets; u64 tls_encrypted_bytes; - u64 tls_ctx; u64 tls_ooo; u64 tls_dump_packets; u64 tls_dump_bytes; From 6f4fdd530a09c8e2c7368ba5a5b1711e6e5ced10 Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Sun, 28 Feb 2021 15:00:45 +0200 Subject: [PATCH 0585/1091] net/mlx5e: kTLS, Fix RX counters atomicity Some TLS RX counters increment per socket/connection, and are not protected against parallel modifications from several cores. Switch them to atomic counters by taking them out of the RQ stats into the global atomic TLS stats. In this patch, we touch 'rx_tls_ctx/del' that count the number of device-offloaded RX TLS connections added/deleted. These counters are updated in the add/del callbacks, out of the fast data-path. This change is not needed for counters that increment only in NAPI context, as they are protected by the NAPI mechanism. Keep them as tls_* counters under 'struct mlx5e_rq_stats'. Fixes: 76c1e1ac2aae ("net/mlx5e: kTLS, Add kTLS RX stats") Signed-off-by: Tariq Toukan Reviewed-by: Maxim Mikityanskiy Signed-off-by: Saeed Mahameed --- .../mellanox/mlx5/core/en_accel/ktls_rx.c | 22 ++++++++++--------- .../mellanox/mlx5/core/en_accel/tls.h | 2 ++ .../mellanox/mlx5/core/en_accel/tls_stats.c | 2 ++ .../ethernet/mellanox/mlx5/core/en_stats.c | 6 ----- .../ethernet/mellanox/mlx5/core/en_stats.h | 4 ---- 5 files changed, 16 insertions(+), 20 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c index d06532d0baa4..57c5ebd597a7 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c @@ -46,7 +46,8 @@ struct mlx5e_ktls_offload_context_rx { struct tls12_crypto_info_aes_gcm_128 crypto_info; struct accel_rule rule; struct sock *sk; - struct mlx5e_rq_stats *stats; + struct mlx5e_rq_stats *rq_stats; + struct mlx5e_tls_sw_stats *sw_stats; struct completion add_ctx; u32 tirn; u32 key_id; @@ -218,7 +219,7 @@ unlock: return err; err_out: - priv_rx->stats->tls_resync_req_skip++; + priv_rx->rq_stats->tls_resync_req_skip++; err = PTR_ERR(cseg); complete(&priv_rx->add_ctx); goto unlock; @@ -322,7 +323,7 @@ err_dma_unmap: err_free: kfree(buf); err_out: - priv_rx->stats->tls_resync_req_skip++; + priv_rx->rq_stats->tls_resync_req_skip++; return err; } @@ -378,13 +379,13 @@ static int resync_handle_seq_match(struct mlx5e_ktls_offload_context_rx *priv_rx cseg = post_static_params(sq, priv_rx); if (IS_ERR(cseg)) { - priv_rx->stats->tls_resync_res_skip++; + priv_rx->rq_stats->tls_resync_res_skip++; err = PTR_ERR(cseg); goto unlock; } /* Do not increment priv_rx refcnt, CQE handling is empty */ mlx5e_notify_hw(&sq->wq, sq->pc, sq->uar_map, cseg); - priv_rx->stats->tls_resync_res_ok++; + priv_rx->rq_stats->tls_resync_res_ok++; unlock: spin_unlock_bh(&c->async_icosq_lock); @@ -420,13 +421,13 @@ void mlx5e_ktls_handle_get_psv_completion(struct mlx5e_icosq_wqe_info *wi, auth_state = MLX5_GET(tls_progress_params, ctx, auth_state); if (tracker_state != MLX5E_TLS_PROGRESS_PARAMS_RECORD_TRACKER_STATE_TRACKING || auth_state != MLX5E_TLS_PROGRESS_PARAMS_AUTH_STATE_NO_OFFLOAD) { - priv_rx->stats->tls_resync_req_skip++; + priv_rx->rq_stats->tls_resync_req_skip++; goto out; } hw_seq = MLX5_GET(tls_progress_params, ctx, hw_resync_tcp_sn); tls_offload_rx_resync_async_request_end(priv_rx->sk, cpu_to_be32(hw_seq)); - priv_rx->stats->tls_resync_req_end++; + priv_rx->rq_stats->tls_resync_req_end++; out: mlx5e_ktls_priv_rx_put(priv_rx); dma_unmap_single(dev, buf->dma_addr, PROGRESS_PARAMS_PADDED_SIZE, DMA_FROM_DEVICE); @@ -609,7 +610,8 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, priv_rx->rxq = rxq; priv_rx->sk = sk; - priv_rx->stats = &priv->channel_stats[rxq].rq; + priv_rx->rq_stats = &priv->channel_stats[rxq].rq; + priv_rx->sw_stats = &priv->tls->sw_stats; mlx5e_set_ktls_rx_priv_ctx(tls_ctx, priv_rx); rqtn = priv->direct_tir[rxq].rqt.rqtn; @@ -630,7 +632,7 @@ int mlx5e_ktls_add_rx(struct net_device *netdev, struct sock *sk, if (err) goto err_post_wqes; - priv_rx->stats->tls_ctx++; + atomic64_inc(&priv_rx->sw_stats->rx_tls_ctx); return 0; @@ -666,7 +668,7 @@ void mlx5e_ktls_del_rx(struct net_device *netdev, struct tls_context *tls_ctx) if (cancel_work_sync(&resync->work)) mlx5e_ktls_priv_rx_put(priv_rx); - priv_rx->stats->tls_del++; + atomic64_inc(&priv_rx->sw_stats->rx_tls_del); if (priv_rx->rule.rule) mlx5e_accel_fs_del_sk(priv_rx->rule.rule); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h index 5b408904df14..4c9274d390da 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls.h @@ -46,6 +46,8 @@ struct mlx5e_tls_sw_stats { atomic64_t tx_tls_drop_resync_alloc; atomic64_t tx_tls_drop_no_sync_data; atomic64_t tx_tls_drop_bypass_required; + atomic64_t rx_tls_ctx; + atomic64_t rx_tls_del; atomic64_t rx_tls_drop_resync_request; atomic64_t rx_tls_resync_request; atomic64_t rx_tls_resync_reply; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c index a5aabc5c5236..29463bdb7715 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/tls_stats.c @@ -47,6 +47,8 @@ static const struct counter_desc mlx5e_tls_sw_stats_desc[] = { static const struct counter_desc mlx5e_ktls_sw_stats_desc[] = { { MLX5E_DECLARE_STAT(struct mlx5e_tls_sw_stats, tx_tls_ctx) }, + { MLX5E_DECLARE_STAT(struct mlx5e_tls_sw_stats, rx_tls_ctx) }, + { MLX5E_DECLARE_STAT(struct mlx5e_tls_sw_stats, rx_tls_del) }, }; #define MLX5E_READ_CTR_ATOMIC64(ptr, dsc, i) \ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c index 74adaa58189a..88a01c59ce61 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.c @@ -179,8 +179,6 @@ static const struct counter_desc sw_stats_desc[] = { #ifdef CONFIG_MLX5_EN_TLS { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_decrypted_packets) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_decrypted_bytes) }, - { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_ctx) }, - { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_del) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_req_pkt) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_req_start) }, { MLX5E_DECLARE_STAT(struct mlx5e_sw_stats, rx_tls_resync_req_end) }, @@ -341,8 +339,6 @@ static void mlx5e_stats_grp_sw_update_stats_rq_stats(struct mlx5e_sw_stats *s, #ifdef CONFIG_MLX5_EN_TLS s->rx_tls_decrypted_packets += rq_stats->tls_decrypted_packets; s->rx_tls_decrypted_bytes += rq_stats->tls_decrypted_bytes; - s->rx_tls_ctx += rq_stats->tls_ctx; - s->rx_tls_del += rq_stats->tls_del; s->rx_tls_resync_req_pkt += rq_stats->tls_resync_req_pkt; s->rx_tls_resync_req_start += rq_stats->tls_resync_req_start; s->rx_tls_resync_req_end += rq_stats->tls_resync_req_end; @@ -1620,8 +1616,6 @@ static const struct counter_desc rq_stats_desc[] = { #ifdef CONFIG_MLX5_EN_TLS { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_decrypted_packets) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_decrypted_bytes) }, - { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_ctx) }, - { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_del) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_req_pkt) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_req_start) }, { MLX5E_DECLARE_RX_STAT(struct mlx5e_rq_stats, tls_resync_req_end) }, diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h index 8eb056af79ba..adf9b7b8b712 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_stats.h @@ -201,8 +201,6 @@ struct mlx5e_sw_stats { u64 rx_tls_decrypted_packets; u64 rx_tls_decrypted_bytes; - u64 rx_tls_ctx; - u64 rx_tls_del; u64 rx_tls_resync_req_pkt; u64 rx_tls_resync_req_start; u64 rx_tls_resync_req_end; @@ -333,8 +331,6 @@ struct mlx5e_rq_stats { #ifdef CONFIG_MLX5_EN_TLS u64 tls_decrypted_packets; u64 tls_decrypted_bytes; - u64 tls_ctx; - u64 tls_del; u64 tls_resync_req_pkt; u64 tls_resync_req_start; u64 tls_resync_req_end; From a7b76002ae78cd230ee652ccdfedf21aa94fcecc Mon Sep 17 00:00:00 2001 From: Daniel Jurgens Date: Thu, 5 Dec 2019 16:58:10 -0600 Subject: [PATCH 0586/1091] net/mlx5: Don't request more than supported EQs Calculating the number of compeltion EQs based on the number of available IRQ vectors doesn't work now that all async EQs share one IRQ. Thus the max number of EQs can be exceeded on systems with more than approximately 256 CPUs. Take this into account when calculating the number of available completion EQs. Fixes: 81bfa206032a ("net/mlx5: Use a single IRQ for all async EQs") Signed-off-by: Daniel Jurgens Reviewed-by: Parav Pandit Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/eq.c | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/eq.c b/drivers/net/ethernet/mellanox/mlx5/core/eq.c index 174dfbc996c6..1fa9c18563da 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/eq.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/eq.c @@ -931,13 +931,24 @@ void mlx5_core_eq_free_irqs(struct mlx5_core_dev *dev) mutex_unlock(&table->lock); } +#ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING +#define MLX5_MAX_ASYNC_EQS 4 +#else +#define MLX5_MAX_ASYNC_EQS 3 +#endif + int mlx5_eq_table_create(struct mlx5_core_dev *dev) { struct mlx5_eq_table *eq_table = dev->priv.eq_table; + int num_eqs = MLX5_CAP_GEN(dev, max_num_eqs) ? + MLX5_CAP_GEN(dev, max_num_eqs) : + 1 << MLX5_CAP_GEN(dev, log_max_eq); int err; eq_table->num_comp_eqs = - mlx5_irq_get_num_comp(eq_table->irq_table); + min_t(int, + mlx5_irq_get_num_comp(eq_table->irq_table), + num_eqs - MLX5_MAX_ASYNC_EQS); err = create_async_eqs(dev); if (err) { From 929a2faddd55290fbb0b73f453b200ed1b2b2947 Mon Sep 17 00:00:00 2001 From: Dima Chumak Date: Thu, 11 Feb 2021 09:36:33 +0200 Subject: [PATCH 0587/1091] net/mlx5e: Consider geneve_opts for encap contexts Current algorithm for encap keys is legacy from initial vxlan implementation and doesn't take into account all possible fields of a tunnel. For example, for a Geneve tunnel, which may have additional TLV options, they are ignored when comparing encap keys and a rule can be attached to an incorrect encap entry. Fix that by introducing encap_info_equal() operation in struct mlx5e_tc_tunnel. Geneve tunnel type uses custom implementation, which extends generic algorithm and considers options if they are set. Fixes: 7f1a546e3222 ("net/mlx5e: Consider tunnel type for encap contexts") Signed-off-by: Dima Chumak Reviewed-by: Vlad Buslov Signed-off-by: Saeed Mahameed --- .../ethernet/mellanox/mlx5/core/en/tc_tun.h | 10 +++++++ .../mellanox/mlx5/core/en/tc_tun_encap.c | 23 ++++++--------- .../mellanox/mlx5/core/en/tc_tun_geneve.c | 29 +++++++++++++++++++ .../mellanox/mlx5/core/en/tc_tun_gre.c | 1 + .../mellanox/mlx5/core/en/tc_tun_mplsoudp.c | 1 + .../mellanox/mlx5/core/en/tc_tun_vxlan.c | 1 + 6 files changed, 51 insertions(+), 14 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h index 67de2bf36861..e1271998b937 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun.h @@ -21,6 +21,11 @@ enum { MLX5E_TC_TUNNEL_TYPE_MPLSOUDP, }; +struct mlx5e_encap_key { + const struct ip_tunnel_key *ip_tun_key; + struct mlx5e_tc_tunnel *tc_tunnel; +}; + struct mlx5e_tc_tunnel { int tunnel_type; enum mlx5_flow_match_level match_level; @@ -44,6 +49,8 @@ struct mlx5e_tc_tunnel { struct flow_cls_offload *f, void *headers_c, void *headers_v); + bool (*encap_info_equal)(struct mlx5e_encap_key *a, + struct mlx5e_encap_key *b); }; extern struct mlx5e_tc_tunnel vxlan_tunnel; @@ -101,6 +108,9 @@ int mlx5e_tc_tun_parse_udp_ports(struct mlx5e_priv *priv, void *headers_c, void *headers_v); +bool mlx5e_tc_tun_encap_info_equal_generic(struct mlx5e_encap_key *a, + struct mlx5e_encap_key *b); + #endif /* CONFIG_MLX5_ESWITCH */ #endif //__MLX5_EN_TC_TUNNEL_H__ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c index 7f7b0f6dcdf9..9f16ad2c0710 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_encap.c @@ -476,16 +476,11 @@ void mlx5e_detach_decap(struct mlx5e_priv *priv, mlx5e_decap_dealloc(priv, d); } -struct encap_key { - const struct ip_tunnel_key *ip_tun_key; - struct mlx5e_tc_tunnel *tc_tunnel; -}; - -static int cmp_encap_info(struct encap_key *a, - struct encap_key *b) +bool mlx5e_tc_tun_encap_info_equal_generic(struct mlx5e_encap_key *a, + struct mlx5e_encap_key *b) { - return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) || - a->tc_tunnel->tunnel_type != b->tc_tunnel->tunnel_type; + return memcmp(a->ip_tun_key, b->ip_tun_key, sizeof(*a->ip_tun_key)) == 0 && + a->tc_tunnel->tunnel_type == b->tc_tunnel->tunnel_type; } static int cmp_decap_info(struct mlx5e_decap_key *a, @@ -494,7 +489,7 @@ static int cmp_decap_info(struct mlx5e_decap_key *a, return memcmp(&a->key, &b->key, sizeof(b->key)); } -static int hash_encap_info(struct encap_key *key) +static int hash_encap_info(struct mlx5e_encap_key *key) { return jhash(key->ip_tun_key, sizeof(*key->ip_tun_key), key->tc_tunnel->tunnel_type); @@ -516,18 +511,18 @@ static bool mlx5e_decap_take(struct mlx5e_decap_entry *e) } static struct mlx5e_encap_entry * -mlx5e_encap_get(struct mlx5e_priv *priv, struct encap_key *key, +mlx5e_encap_get(struct mlx5e_priv *priv, struct mlx5e_encap_key *key, uintptr_t hash_key) { struct mlx5_eswitch *esw = priv->mdev->priv.eswitch; + struct mlx5e_encap_key e_key; struct mlx5e_encap_entry *e; - struct encap_key e_key; hash_for_each_possible_rcu(esw->offloads.encap_tbl, e, encap_hlist, hash_key) { e_key.ip_tun_key = &e->tun_info->key; e_key.tc_tunnel = e->tunnel; - if (!cmp_encap_info(&e_key, key) && + if (e->tunnel->encap_info_equal(&e_key, key) && mlx5e_encap_take(e)) return e; } @@ -694,8 +689,8 @@ int mlx5e_attach_encap(struct mlx5e_priv *priv, struct mlx5_flow_attr *attr = flow->attr; const struct ip_tunnel_info *tun_info; unsigned long tbl_time_before = 0; - struct encap_key key; struct mlx5e_encap_entry *e; + struct mlx5e_encap_key key; bool entry_created = false; unsigned short family; uintptr_t hash_key; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c index 7ed3f9f79f11..f5b26f5a7de4 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_geneve.c @@ -329,6 +329,34 @@ static int mlx5e_tc_tun_parse_geneve(struct mlx5e_priv *priv, return mlx5e_tc_tun_parse_geneve_options(priv, spec, f); } +static bool mlx5e_tc_tun_encap_info_equal_geneve(struct mlx5e_encap_key *a, + struct mlx5e_encap_key *b) +{ + struct ip_tunnel_info *a_info; + struct ip_tunnel_info *b_info; + bool a_has_opts, b_has_opts; + + if (!mlx5e_tc_tun_encap_info_equal_generic(a, b)) + return false; + + a_has_opts = !!(a->ip_tun_key->tun_flags & TUNNEL_GENEVE_OPT); + b_has_opts = !!(b->ip_tun_key->tun_flags & TUNNEL_GENEVE_OPT); + + /* keys are equal when both don't have any options attached */ + if (!a_has_opts && !b_has_opts) + return true; + + if (a_has_opts != b_has_opts) + return false; + + /* geneve options stored in memory next to ip_tunnel_info struct */ + a_info = container_of(a->ip_tun_key, struct ip_tunnel_info, key); + b_info = container_of(b->ip_tun_key, struct ip_tunnel_info, key); + + return a_info->options_len == b_info->options_len && + memcmp(a_info + 1, b_info + 1, a_info->options_len) == 0; +} + struct mlx5e_tc_tunnel geneve_tunnel = { .tunnel_type = MLX5E_TC_TUNNEL_TYPE_GENEVE, .match_level = MLX5_MATCH_L4, @@ -338,4 +366,5 @@ struct mlx5e_tc_tunnel geneve_tunnel = { .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_geneve, .parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_geneve, .parse_tunnel = mlx5e_tc_tun_parse_geneve, + .encap_info_equal = mlx5e_tc_tun_encap_info_equal_geneve, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_gre.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_gre.c index 2805416c32a3..ada14f0574dc 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_gre.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_gre.c @@ -94,4 +94,5 @@ struct mlx5e_tc_tunnel gre_tunnel = { .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_gretap, .parse_udp_ports = NULL, .parse_tunnel = mlx5e_tc_tun_parse_gretap, + .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c index 3479672e84cf..60952b33b568 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_mplsoudp.c @@ -131,4 +131,5 @@ struct mlx5e_tc_tunnel mplsoudp_tunnel = { .generate_ip_tun_hdr = generate_ip_tun_hdr, .parse_udp_ports = parse_udp_ports, .parse_tunnel = parse_tunnel, + .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic, }; diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c index 038a0f1cecec..4267f3a1059e 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/tc_tun_vxlan.c @@ -150,4 +150,5 @@ struct mlx5e_tc_tunnel vxlan_tunnel = { .generate_ip_tun_hdr = mlx5e_gen_ip_tunnel_header_vxlan, .parse_udp_ports = mlx5e_tc_tun_parse_udp_ports_vxlan, .parse_tunnel = mlx5e_tc_tun_parse_vxlan, + .encap_info_equal = mlx5e_tc_tun_encap_info_equal_generic, }; From 3ff3874fa0b261ef74f2bfb008a82ab1601c11eb Mon Sep 17 00:00:00 2001 From: Tariq Toukan Date: Wed, 10 Feb 2021 14:58:01 +0200 Subject: [PATCH 0588/1091] net/mlx5e: Guarantee room for XSK wakeup NOP on async ICOSQ XSK wakeup flow triggers an IRQ by posting a NOP WQE and hitting the doorbell on the async ICOSQ. It maintains its state so that it doesn't issue another NOP WQE if it has an outstanding one already. For this flow to work properly, the NOP post must not fail. Make sure to reserve room for the NOP WQE in all WQE posts to the async ICOSQ. Fixes: 8d94b590f1e4 ("net/mlx5e: Turn XSK ICOSQ into a general asynchronous one") Fixes: 1182f3659357 ("net/mlx5e: kTLS, Add kTLS RX HW offload support") Fixes: 0419d8c9d8f8 ("net/mlx5e: kTLS, Add kTLS RX resync support") Signed-off-by: Tariq Toukan Reviewed-by: Maxim Mikityanskiy Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en.h | 1 + .../net/ethernet/mellanox/mlx5/core/en/txrx.h | 6 ++++++ .../mellanox/mlx5/core/en_accel/ktls_rx.c | 18 +++++++--------- .../net/ethernet/mellanox/mlx5/core/en_main.c | 21 ++++++++++++++++++- 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en.h b/drivers/net/ethernet/mellanox/mlx5/core/en.h index 304b296fe8b9..bc6f77ea0a31 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en.h @@ -516,6 +516,7 @@ struct mlx5e_icosq { struct mlx5_wq_cyc wq; void __iomem *uar_map; u32 sqn; + u16 reserved_room; unsigned long state; /* control path */ diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h index 2371b83dad9c..055c3bc23733 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/txrx.h @@ -441,4 +441,10 @@ static inline u16 mlx5e_stop_room_for_wqe(u16 wqe_size) return wqe_size * 2 - 1; } +static inline bool mlx5e_icosq_can_post_wqe(struct mlx5e_icosq *sq, u16 wqe_size) +{ + u16 room = sq->reserved_room + mlx5e_stop_room_for_wqe(wqe_size); + + return mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, room); +} #endif diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c index 57c5ebd597a7..19d22a63313f 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_accel/ktls_rx.c @@ -138,11 +138,10 @@ post_static_params(struct mlx5e_icosq *sq, { struct mlx5e_set_tls_static_params_wqe *wqe; struct mlx5e_icosq_wqe_info wi; - u16 pi, num_wqebbs, room; + u16 pi, num_wqebbs; num_wqebbs = MLX5E_TLS_SET_STATIC_PARAMS_WQEBBS; - room = mlx5e_stop_room_for_wqe(num_wqebbs); - if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, room))) + if (unlikely(!mlx5e_icosq_can_post_wqe(sq, num_wqebbs))) return ERR_PTR(-ENOSPC); pi = mlx5e_icosq_get_next_pi(sq, num_wqebbs); @@ -169,11 +168,10 @@ post_progress_params(struct mlx5e_icosq *sq, { struct mlx5e_set_tls_progress_params_wqe *wqe; struct mlx5e_icosq_wqe_info wi; - u16 pi, num_wqebbs, room; + u16 pi, num_wqebbs; num_wqebbs = MLX5E_TLS_SET_PROGRESS_PARAMS_WQEBBS; - room = mlx5e_stop_room_for_wqe(num_wqebbs); - if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, room))) + if (unlikely(!mlx5e_icosq_can_post_wqe(sq, num_wqebbs))) return ERR_PTR(-ENOSPC); pi = mlx5e_icosq_get_next_pi(sq, num_wqebbs); @@ -278,17 +276,15 @@ resync_post_get_progress_params(struct mlx5e_icosq *sq, buf->priv_rx = priv_rx; - BUILD_BUG_ON(MLX5E_KTLS_GET_PROGRESS_WQEBBS != 1); - spin_lock_bh(&sq->channel->async_icosq_lock); - if (unlikely(!mlx5e_wqc_has_room_for(&sq->wq, sq->cc, sq->pc, 1))) { + if (unlikely(!mlx5e_icosq_can_post_wqe(sq, MLX5E_KTLS_GET_PROGRESS_WQEBBS))) { spin_unlock_bh(&sq->channel->async_icosq_lock); err = -ENOSPC; goto err_dma_unmap; } - pi = mlx5e_icosq_get_next_pi(sq, 1); + pi = mlx5e_icosq_get_next_pi(sq, MLX5E_KTLS_GET_PROGRESS_WQEBBS); wqe = MLX5E_TLS_FETCH_GET_PROGRESS_PARAMS_WQE(sq, pi); #define GET_PSV_DS_CNT (DIV_ROUND_UP(sizeof(*wqe), MLX5_SEND_WQE_DS)) @@ -308,7 +304,7 @@ resync_post_get_progress_params(struct mlx5e_icosq *sq, wi = (struct mlx5e_icosq_wqe_info) { .wqe_type = MLX5E_ICOSQ_WQE_GET_PSV_TLS, - .num_wqebbs = 1, + .num_wqebbs = MLX5E_KTLS_GET_PROGRESS_WQEBBS, .tls_get_params.buf = buf, }; icosq_fill_wi(sq, pi, &wi); diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c index 158f947a8503..5db63b9f3b70 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_main.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_main.c @@ -1091,6 +1091,7 @@ static int mlx5e_alloc_icosq(struct mlx5e_channel *c, sq->channel = c; sq->uar_map = mdev->mlx5e_res.bfreg.map; + sq->reserved_room = param->stop_room; param->wq.db_numa_node = cpu_to_node(c->cpu); err = mlx5_wq_cyc_create(mdev, ¶m->wq, sqc_wq, wq, &sq->wq_ctrl); @@ -2350,6 +2351,24 @@ void mlx5e_build_icosq_param(struct mlx5e_priv *priv, mlx5e_build_ico_cq_param(priv, log_wq_size, ¶m->cqp); } +static void mlx5e_build_async_icosq_param(struct mlx5e_priv *priv, + struct mlx5e_params *params, + u8 log_wq_size, + struct mlx5e_sq_param *param) +{ + void *sqc = param->sqc; + void *wq = MLX5_ADDR_OF(sqc, sqc, wq); + + mlx5e_build_sq_param_common(priv, param); + + /* async_icosq is used by XSK only if xdp_prog is active */ + if (params->xdp_prog) + param->stop_room = mlx5e_stop_room_for_wqe(1); /* for XSK NOP */ + MLX5_SET(sqc, sqc, reg_umr, MLX5_CAP_ETH(priv->mdev, reg_umr_sq)); + MLX5_SET(wq, wq, log_wq_sz, log_wq_size); + mlx5e_build_ico_cq_param(priv, log_wq_size, ¶m->cqp); +} + void mlx5e_build_xdpsq_param(struct mlx5e_priv *priv, struct mlx5e_params *params, struct mlx5e_sq_param *param) @@ -2398,7 +2417,7 @@ static void mlx5e_build_channel_param(struct mlx5e_priv *priv, mlx5e_build_sq_param(priv, params, &cparam->txq_sq); mlx5e_build_xdpsq_param(priv, params, &cparam->xdp_sq); mlx5e_build_icosq_param(priv, icosq_log_wq_sz, &cparam->icosq); - mlx5e_build_icosq_param(priv, async_icosq_log_wq_sz, &cparam->async_icosq); + mlx5e_build_async_icosq_param(priv, params, async_icosq_log_wq_sz, &cparam->async_icosq); } int mlx5e_open_channels(struct mlx5e_priv *priv, From d47ec7a0a7271dda08932d6208e4ab65ab0c987c Mon Sep 17 00:00:00 2001 From: Tong Zhu Date: Fri, 19 Mar 2021 14:33:37 -0400 Subject: [PATCH 0589/1091] neighbour: Disregard DEAD dst in neigh_update After a short network outage, the dst_entry is timed out and put in DST_OBSOLETE_DEAD. We are in this code because arp reply comes from this neighbour after network recovers. There is a potential race condition that dst_entry is still in DST_OBSOLETE_DEAD. With that, another neighbour lookup causes more harm than good. In best case all packets in arp_queue are lost. This is counterproductive to the original goal of finding a better path for those packets. I observed a worst case with 4.x kernel where a dst_entry in DST_OBSOLETE_DEAD state is associated with loopback net_device. It leads to an ethernet header with all zero addresses. A packet with all zero source MAC address is quite deadly with mac80211, ath9k and 802.11 block ack. It fails ieee80211_find_sta_by_ifaddr in ath9k (xmit.c). Ath9k flushes tx queue (ath_tx_complete_aggr). BAW (block ack window) is not updated. BAW logic is damaged and ath9k transmission is disabled. Signed-off-by: Tong Zhu Signed-off-by: David S. Miller --- net/core/neighbour.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/core/neighbour.c b/net/core/neighbour.c index e2982b3970b8..8379719d1dce 100644 --- a/net/core/neighbour.c +++ b/net/core/neighbour.c @@ -1379,7 +1379,7 @@ static int __neigh_update(struct neighbour *neigh, const u8 *lladdr, * we can reinject the packet there. */ n2 = NULL; - if (dst) { + if (dst && dst->obsolete != DST_OBSOLETE_DEAD) { n2 = dst_neigh_lookup_skb(dst, skb); if (n2) n1 = n2; From bdc2ab5c61a5c07388f4820ff21e787b4dfd1ced Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Tue, 30 Mar 2021 18:59:59 -0700 Subject: [PATCH 0590/1091] net/rds: Fix a use after free in rds_message_map_pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In rds_message_map_pages, the rm is freed by rds_message_put(rm). But rm is still used by rm->data.op_sg in return value. My patch assigns ERR_CAST(rm->data.op_sg) to err before the rm is freed to avoid the uaf. Fixes: 7dba92037baf3 ("net/rds: Use ERR_PTR for rds_message_alloc_sgs()") Signed-off-by: Lv Yunlong Reviewed-by: Håkon Bugge Signed-off-by: David S. Miller --- net/rds/message.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/rds/message.c b/net/rds/message.c index 071a261fdaab..799034e0f513 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -347,8 +347,9 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in rm->data.op_nents = DIV_ROUND_UP(total_len, PAGE_SIZE); rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs); if (IS_ERR(rm->data.op_sg)) { + void *err = ERR_CAST(rm->data.op_sg); rds_message_put(rm); - return ERR_CAST(rm->data.op_sg); + return err; } for (i = 0; i < rm->data.op_nents; ++i) { From c609e6aae4efcf383fe86b195d1b060befcb3666 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Wed, 31 Mar 2021 09:35:12 -0700 Subject: [PATCH 0591/1091] Revert "net: correct sk_acceptq_is_full()" This reverts commit f211ac154577ec9ccf07c15f18a6abf0d9bdb4ab. We had similar attempt in the past, and we reverted it. History: 64a146513f8f12ba204b7bf5cb7e9505594ead42 [NET]: Revert incorrect accept queue backlog changes. 8488df894d05d6fa41c2bd298c335f944bb0e401 [NET]: Fix bugs in "Whether sock accept queue is full" checking I am adding a fat comment so that future attempts will be much harder. Fixes: f211ac154577 ("net: correct sk_acceptq_is_full()") Cc: iuyacan Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- include/net/sock.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/include/net/sock.h b/include/net/sock.h index 3e3a5da2ce5a..8487f58da36d 100644 --- a/include/net/sock.h +++ b/include/net/sock.h @@ -934,9 +934,13 @@ static inline void sk_acceptq_added(struct sock *sk) WRITE_ONCE(sk->sk_ack_backlog, sk->sk_ack_backlog + 1); } +/* Note: If you think the test should be: + * return READ_ONCE(sk->sk_ack_backlog) >= READ_ONCE(sk->sk_max_ack_backlog); + * Then please take a look at commit 64a146513f8f ("[NET]: Revert incorrect accept queue backlog changes.") + */ static inline bool sk_acceptq_is_full(const struct sock *sk) { - return READ_ONCE(sk->sk_ack_backlog) >= READ_ONCE(sk->sk_max_ack_backlog); + return READ_ONCE(sk->sk_ack_backlog) > READ_ONCE(sk->sk_max_ack_backlog); } /* From 622d13694b5f048c01caa7ba548498d9880d4cb0 Mon Sep 17 00:00:00 2001 From: Ong Boon Leong Date: Wed, 31 Mar 2021 21:25:03 +0800 Subject: [PATCH 0592/1091] xdp: fix xdp_return_frame() kernel BUG throw for page_pool memory model xdp_return_frame() may be called outside of NAPI context to return xdpf back to page_pool. xdp_return_frame() calls __xdp_return() with napi_direct = false. For page_pool memory model, __xdp_return() calls xdp_return_frame_no_direct() unconditionally and below false negative kernel BUG throw happened under preempt-rt build: [ 430.450355] BUG: using smp_processor_id() in preemptible [00000000] code: modprobe/3884 [ 430.451678] caller is __xdp_return+0x1ff/0x2e0 [ 430.452111] CPU: 0 PID: 3884 Comm: modprobe Tainted: G U E 5.12.0-rc2+ #45 Changes in v2: - This patch fixes the issue by making xdp_return_frame_no_direct() is only called if napi_direct = true, as recommended for better by Jesper Dangaard Brouer. Thanks! Fixes: 2539650fadbf ("xdp: Helpers for disabling napi_direct of xdp_return_frame") Signed-off-by: Ong Boon Leong Acked-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- net/core/xdp.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/xdp.c b/net/core/xdp.c index 05354976c1fc..858276e72c68 100644 --- a/net/core/xdp.c +++ b/net/core/xdp.c @@ -350,7 +350,8 @@ static void __xdp_return(void *data, struct xdp_mem_info *mem, bool napi_direct, /* mem->id is valid, checked in xdp_rxq_info_reg_mem_model() */ xa = rhashtable_lookup(mem_id_ht, &mem->id, mem_id_rht_params); page = virt_to_head_page(data); - napi_direct &= !xdp_return_frame_no_direct(); + if (napi_direct && xdp_return_frame_no_direct()) + napi_direct = false; page_pool_put_full_page(xa->page_pool, page, napi_direct); rcu_read_unlock(); break; From 3edf5346e4f2ce2fa0c94651a90a8dda169565ee Mon Sep 17 00:00:00 2001 From: Yufen Yu Date: Wed, 31 Mar 2021 07:53:59 -0400 Subject: [PATCH 0593/1091] block: only update parent bi_status when bio fail For multiple split bios, if one of the bio is fail, the whole should return error to application. But we found there is a race between bio_integrity_verify_fn and bio complete, which return io success to application after one of the bio fail. The race as following: split bio(READ) kworker nvme_complete_rq blk_update_request //split error=0 bio_endio bio_integrity_endio queue_work(kintegrityd_wq, &bip->bip_work); bio_integrity_verify_fn bio_endio //split bio __bio_chain_endio if (!parent->bi_status) nvme_irq blk_update_request //parent error=7 req_bio_endio bio->bi_status = 7 //parent bio parent->bi_status = 0 parent->bi_end_io() // return bi_status=0 The bio has been split as two: split and parent. When split bio completed, it depends on kworker to do endio, while bio_integrity_verify_fn have been interrupted by parent bio complete irq handler. Then, parent bio->bi_status which have been set in irq handler will overwrite by kworker. In fact, even without the above race, we also need to conside the concurrency beteen mulitple split bio complete and update the same parent bi_status. Normally, multiple split bios will be issued to the same hctx and complete from the same irq vector. But if we have updated queue map between multiple split bios, these bios may complete on different hw queue and different irq vector. Then the concurrency update parent bi_status may cause the final status error. Suggested-by: Keith Busch Signed-off-by: Yufen Yu Reviewed-by: Ming Lei Link: https://lore.kernel.org/r/20210331115359.1125679-1-yuyufen@huawei.com Signed-off-by: Jens Axboe --- block/bio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/block/bio.c b/block/bio.c index 963d1d406b3a..50e579088aca 100644 --- a/block/bio.c +++ b/block/bio.c @@ -277,7 +277,7 @@ static struct bio *__bio_chain_endio(struct bio *bio) { struct bio *parent = bio->bi_private; - if (!parent->bi_status) + if (bio->bi_status && !parent->bi_status) parent->bi_status = bio->bi_status; bio_put(bio); return parent; From e92049ae4548ba09e53eaa9c8f6964b07ea274c9 Mon Sep 17 00:00:00 2001 From: Qu Huang Date: Thu, 28 Jan 2021 20:14:25 +0800 Subject: [PATCH 0594/1091] drm/amdkfd: dqm fence memory corruption Amdgpu driver uses 4-byte data type as DQM fence memory, and transmits GPU address of fence memory to microcode through query status PM4 message. However, query status PM4 message definition and microcode processing are all processed according to 8 bytes. Fence memory only allocates 4 bytes of memory, but microcode does write 8 bytes of memory, so there is a memory corruption. Changes since v1: * Change dqm->fence_addr as a u64 pointer to fix this issue, also fix up query_status and amdkfd_fence_wait_timeout function uses 64 bit fence value to make them consistent. Signed-off-by: Qu Huang Reviewed-by: Felix Kuehling Signed-off-by: Felix Kuehling Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c | 6 +++--- drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c | 2 +- drivers/gpu/drm/amd/amdkfd/kfd_priv.h | 8 ++++---- 7 files changed, 12 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c index b258a3dae767..159add0f5aaa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_dbgdev.c @@ -155,7 +155,7 @@ static int dbgdev_diq_submit_ib(struct kfd_dbgdev *dbgdev, /* Wait till CP writes sync code: */ status = amdkfd_fence_wait_timeout( - (unsigned int *) rm_state, + rm_state, QUEUESTATE__ACTIVE, 1500); kfd_gtt_sa_free(dbgdev->dev, mem_obj); diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c index e686ce2bf3b3..4598a9a58125 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.c @@ -1167,7 +1167,7 @@ static int start_cpsch(struct device_queue_manager *dqm) if (retval) goto fail_allocate_vidmem; - dqm->fence_addr = dqm->fence_mem->cpu_ptr; + dqm->fence_addr = (uint64_t *)dqm->fence_mem->cpu_ptr; dqm->fence_gpu_addr = dqm->fence_mem->gpu_addr; init_interrupts(dqm); @@ -1340,8 +1340,8 @@ out: return retval; } -int amdkfd_fence_wait_timeout(unsigned int *fence_addr, - unsigned int fence_value, +int amdkfd_fence_wait_timeout(uint64_t *fence_addr, + uint64_t fence_value, unsigned int timeout_ms) { unsigned long end_jiffies = msecs_to_jiffies(timeout_ms) + jiffies; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h index 7351dd195274..45f815946554 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_device_queue_manager.h @@ -192,7 +192,7 @@ struct device_queue_manager { uint16_t vmid_pasid[VMID_NUM]; uint64_t pipelines_addr; uint64_t fence_gpu_addr; - unsigned int *fence_addr; + uint64_t *fence_addr; struct kfd_mem_obj *fence_mem; bool active_runlist; int sched_policy; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c index 5d541e0cc8ca..f71a7fa6680c 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager.c @@ -347,7 +347,7 @@ fail_create_runlist_ib: } int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, - uint32_t fence_value) + uint64_t fence_value) { uint32_t *buffer, size; int retval = 0; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c index dfaf771a42e6..e3ba0cd3b6fa 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_v9.c @@ -283,7 +283,7 @@ static int pm_unmap_queues_v9(struct packet_manager *pm, uint32_t *buffer, } static int pm_query_status_v9(struct packet_manager *pm, uint32_t *buffer, - uint64_t fence_address, uint32_t fence_value) + uint64_t fence_address, uint64_t fence_value) { struct pm4_mes_query_status *packet; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c index a852e0d7d804..08442e7d9944 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c +++ b/drivers/gpu/drm/amd/amdkfd/kfd_packet_manager_vi.c @@ -263,7 +263,7 @@ static int pm_unmap_queues_vi(struct packet_manager *pm, uint32_t *buffer, } static int pm_query_status_vi(struct packet_manager *pm, uint32_t *buffer, - uint64_t fence_address, uint32_t fence_value) + uint64_t fence_address, uint64_t fence_value) { struct pm4_mes_query_status *packet; diff --git a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h index 09599efa41fc..f304d1f8df5f 100644 --- a/drivers/gpu/drm/amd/amdkfd/kfd_priv.h +++ b/drivers/gpu/drm/amd/amdkfd/kfd_priv.h @@ -1003,8 +1003,8 @@ int pqm_get_wave_state(struct process_queue_manager *pqm, u32 *ctl_stack_used_size, u32 *save_area_used_size); -int amdkfd_fence_wait_timeout(unsigned int *fence_addr, - unsigned int fence_value, +int amdkfd_fence_wait_timeout(uint64_t *fence_addr, + uint64_t fence_value, unsigned int timeout_ms); /* Packet Manager */ @@ -1040,7 +1040,7 @@ struct packet_manager_funcs { uint32_t filter_param, bool reset, unsigned int sdma_engine); int (*query_status)(struct packet_manager *pm, uint32_t *buffer, - uint64_t fence_address, uint32_t fence_value); + uint64_t fence_address, uint64_t fence_value); int (*release_mem)(uint64_t gpu_addr, uint32_t *buffer); /* Packet sizes */ @@ -1062,7 +1062,7 @@ int pm_send_set_resources(struct packet_manager *pm, struct scheduling_resources *res); int pm_send_runlist(struct packet_manager *pm, struct list_head *dqm_queues); int pm_send_query_status(struct packet_manager *pm, uint64_t fence_address, - uint32_t fence_value); + uint64_t fence_value); int pm_send_unmap_queue(struct packet_manager *pm, enum kfd_queue_type type, enum kfd_unmap_queues_filter mode, From 6951c3e4a260f65a16433833d2511e8796dc8625 Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Fri, 26 Mar 2021 16:56:07 -0400 Subject: [PATCH 0595/1091] drm/amdgpu/vangogh: don't check for dpm in is_dpm_running when in suspend Do the same thing we do for Renoir. We can check, but since the sbios has started DPM, it will always return true which causes the driver to skip some of the SMU init when it shouldn't. Reviewed-by: Zhan Liu Acked-by: Evan Quan Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c index 7ddbaecb11c2..101eaa20db9b 100644 --- a/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c +++ b/drivers/gpu/drm/amd/pm/swsmu/smu11/vangogh_ppt.c @@ -384,10 +384,15 @@ static int vangogh_dpm_set_jpeg_enable(struct smu_context *smu, bool enable) static bool vangogh_is_dpm_running(struct smu_context *smu) { + struct amdgpu_device *adev = smu->adev; int ret = 0; uint32_t feature_mask[2]; uint64_t feature_enabled; + /* we need to re-init after suspend so return false */ + if (adev->in_suspend) + return false; + ret = smu_cmn_get_enabled_32_bits_mask(smu, feature_mask, 2); if (ret) From 566c6e25f957ebdb0b6e8073ee291049118f47fb Mon Sep 17 00:00:00 2001 From: Huacai Chen Date: Tue, 30 Mar 2021 23:33:33 +0800 Subject: [PATCH 0596/1091] drm/amdgpu: Set a suitable dev_info.gart_page_size MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In Mesa, dev_info.gart_page_size is used for alignment and it was set to AMDGPU_GPU_PAGE_SIZE(4KB). However, the page table of AMDGPU driver requires an alignment on CPU pages. So, for non-4KB page system, gart_page_size should be max_t(u32, PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE). Signed-off-by: Rui Wang Signed-off-by: Huacai Chen Link: https://github.com/loongson-community/linux-stable/commit/caa9c0a1 [Xi: rebased for drm-next, use max_t for checkpatch, and reworded commit message.] Signed-off-by: Xi Ruoyao BugLink: https://gitlab.freedesktop.org/drm/amd/-/issues/1549 Tested-by: Dan Horák Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c index 64beb3399604..a4e2cf7cada1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_kms.c @@ -778,9 +778,9 @@ int amdgpu_info_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) dev_info->high_va_offset = AMDGPU_GMC_HOLE_END; dev_info->high_va_max = AMDGPU_GMC_HOLE_END | vm_size; } - dev_info->virtual_address_alignment = max((int)PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE); + dev_info->virtual_address_alignment = max_t(u32, PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE); dev_info->pte_fragment_size = (1 << adev->vm_manager.fragment_size) * AMDGPU_GPU_PAGE_SIZE; - dev_info->gart_page_size = AMDGPU_GPU_PAGE_SIZE; + dev_info->gart_page_size = max_t(u32, PAGE_SIZE, AMDGPU_GPU_PAGE_SIZE); dev_info->cu_active_number = adev->gfx.cu_info.number; dev_info->cu_ao_mask = adev->gfx.cu_info.ao_cu_mask; dev_info->ce_ram_size = adev->gfx.ce_ram_size; From e3512fb67093fabdf27af303066627b921ee9bd8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?X=E2=84=B9=20Ruoyao?= Date: Tue, 30 Mar 2021 23:33:34 +0800 Subject: [PATCH 0597/1091] drm/amdgpu: check alignment on CPU page for bo map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The page table of AMDGPU requires an alignment to CPU page so we should check ioctl parameters for it. Return -EINVAL if some parameter is unaligned to CPU page, instead of corrupt the page table sliently. Reviewed-by: Christian König Signed-off-by: Xi Ruoyao Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index 10de2cf344d5..7d2c8b169827 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -2197,8 +2197,8 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, uint64_t eaddr; /* validate the parameters */ - if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK || - size == 0 || size & AMDGPU_GPU_PAGE_MASK) + if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || + size == 0 || size & ~PAGE_MASK) return -EINVAL; /* make sure object fit at this offset */ @@ -2263,8 +2263,8 @@ int amdgpu_vm_bo_replace_map(struct amdgpu_device *adev, int r; /* validate the parameters */ - if (saddr & AMDGPU_GPU_PAGE_MASK || offset & AMDGPU_GPU_PAGE_MASK || - size == 0 || size & AMDGPU_GPU_PAGE_MASK) + if (saddr & ~PAGE_MASK || offset & ~PAGE_MASK || + size == 0 || size & ~PAGE_MASK) return -EINVAL; /* make sure object fit at this offset */ From a58d9166a756a0f4a6618e4f593232593d6df134 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 31 Mar 2021 06:24:43 -0400 Subject: [PATCH 0598/1091] KVM: SVM: load control fields from VMCB12 before checking them Avoid races between check and use of the nested VMCB controls. This for example ensures that the VMRUN intercept is always reflected to the nested hypervisor, instead of being processed by the host. Without this patch, it is possible to end up with svm->nested.hsave pointing to the MSR permission bitmap for nested guests. This bug is CVE-2021-29657. Reported-by: Felix Wilhelm Cc: stable@vger.kernel.org Fixes: 2fcf4876ada ("KVM: nSVM: implement on demand allocation of the nested state") Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm/nested.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 9e4c226dbf7d..061a00f91af5 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -225,7 +225,7 @@ static bool nested_vmcb_check_controls(struct vmcb_control_area *control) return true; } -static bool nested_vmcb_checks(struct vcpu_svm *svm, struct vmcb *vmcb12) +static bool nested_vmcb_check_save(struct vcpu_svm *svm, struct vmcb *vmcb12) { bool vmcb12_lma; @@ -257,7 +257,7 @@ static bool nested_vmcb_checks(struct vcpu_svm *svm, struct vmcb *vmcb12) if (kvm_valid_cr4(&svm->vcpu, vmcb12->save.cr4)) return false; - return nested_vmcb_check_controls(&vmcb12->control); + return true; } static void load_nested_vmcb_control(struct vcpu_svm *svm, @@ -440,7 +440,6 @@ int enter_svm_guest_mode(struct vcpu_svm *svm, u64 vmcb12_gpa, int ret; svm->nested.vmcb12_gpa = vmcb12_gpa; - load_nested_vmcb_control(svm, &vmcb12->control); nested_prepare_vmcb_save(svm, vmcb12); nested_prepare_vmcb_control(svm); @@ -484,7 +483,10 @@ int nested_svm_vmrun(struct vcpu_svm *svm) if (WARN_ON_ONCE(!svm->nested.initialized)) return -EINVAL; - if (!nested_vmcb_checks(svm, vmcb12)) { + load_nested_vmcb_control(svm, &vmcb12->control); + + if (!nested_vmcb_check_save(svm, vmcb12) || + !nested_vmcb_check_controls(&svm->nested.ctl)) { vmcb12->control.exit_code = SVM_EXIT_ERR; vmcb12->control.exit_code_hi = 0; vmcb12->control.exit_info_1 = 0; From 3c346c0c60ab06a021d1c0884a0ef494bc4ee3a7 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Wed, 31 Mar 2021 06:28:01 -0400 Subject: [PATCH 0599/1091] KVM: SVM: ensure that EFER.SVME is set when running nested guest or on nested vmexit Fixing nested_vmcb_check_save to avoid all TOC/TOU races is a bit harder in released kernels, so do the bare minimum by avoiding that EFER.SVME is cleared. This is problematic because svm_set_efer frees the data structures for nested virtualization if EFER.SVME is cleared. Also check that EFER.SVME remains set after a nested vmexit; clearing it could happen if the bit is zero in the save area that is passed to KVM_SET_NESTED_STATE (the save area of the nested state corresponds to the nested hypervisor's state and is restored on the next nested vmexit). Cc: stable@vger.kernel.org Fixes: 2fcf4876ada ("KVM: nSVM: implement on demand allocation of the nested state") Signed-off-by: Paolo Bonzini --- arch/x86/kvm/svm/nested.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/arch/x86/kvm/svm/nested.c b/arch/x86/kvm/svm/nested.c index 061a00f91af5..c9e7b86350d6 100644 --- a/arch/x86/kvm/svm/nested.c +++ b/arch/x86/kvm/svm/nested.c @@ -229,6 +229,13 @@ static bool nested_vmcb_check_save(struct vcpu_svm *svm, struct vmcb *vmcb12) { bool vmcb12_lma; + /* + * FIXME: these should be done after copying the fields, + * to avoid TOC/TOU races. For these save area checks + * the possible damage is limited since kvm_set_cr0 and + * kvm_set_cr4 handle failure; EFER_SVME is an exception + * so it is force-set later in nested_prepare_vmcb_save. + */ if ((vmcb12->save.efer & EFER_SVME) == 0) return false; @@ -382,7 +389,14 @@ static void nested_prepare_vmcb_save(struct vcpu_svm *svm, struct vmcb *vmcb12) svm->vmcb->save.gdtr = vmcb12->save.gdtr; svm->vmcb->save.idtr = vmcb12->save.idtr; kvm_set_rflags(&svm->vcpu, vmcb12->save.rflags); - svm_set_efer(&svm->vcpu, vmcb12->save.efer); + + /* + * Force-set EFER_SVME even though it is checked earlier on the + * VMCB12, because the guest can flip the bit between the check + * and now. Clearing EFER_SVME would call svm_free_nested. + */ + svm_set_efer(&svm->vcpu, vmcb12->save.efer | EFER_SVME); + svm_set_cr0(&svm->vcpu, vmcb12->save.cr0); svm_set_cr4(&svm->vcpu, vmcb12->save.cr4); svm->vmcb->save.cr2 = svm->vcpu.arch.cr2 = vmcb12->save.cr2; @@ -1188,6 +1202,8 @@ static int svm_set_nested_state(struct kvm_vcpu *vcpu, */ if (!(save->cr0 & X86_CR0_PG)) goto out_free; + if (!(save->efer & EFER_SVME)) + goto out_free; /* * All checks done, we can enter guest mode. L1 control fields From c2c647f91aec192f45f0849c225f134183cf4e90 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 25 Mar 2021 14:05:11 -0400 Subject: [PATCH 0600/1091] KVM: x86: reduce pvclock_gtod_sync_lock critical sections There is no need to include changes to vcpu->requests into the pvclock_gtod_sync_lock critical section. The changes to the shared data structures (in pvclock_update_vm_gtod_copy) already occur under the lock. Cc: David Woodhouse Cc: Marcelo Tosatti Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f7d12fca397b..2301623d3c53 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2561,10 +2561,12 @@ static void kvm_gen_update_masterclock(struct kvm *kvm) kvm_hv_invalidate_tsc_page(kvm); - spin_lock(&ka->pvclock_gtod_sync_lock); kvm_make_mclock_inprogress_request(kvm); + /* no guest entries from this point */ + spin_lock(&ka->pvclock_gtod_sync_lock); pvclock_update_vm_gtod_copy(kvm); + spin_unlock(&ka->pvclock_gtod_sync_lock); kvm_for_each_vcpu(i, vcpu, kvm) kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); @@ -2572,8 +2574,6 @@ static void kvm_gen_update_masterclock(struct kvm *kvm) /* guest entries allowed */ kvm_for_each_vcpu(i, vcpu, kvm) kvm_clear_request(KVM_REQ_MCLOCK_INPROGRESS, vcpu); - - spin_unlock(&ka->pvclock_gtod_sync_lock); #endif } @@ -7739,16 +7739,14 @@ static void kvm_hyperv_tsc_notifier(void) struct kvm_arch *ka = &kvm->arch; spin_lock(&ka->pvclock_gtod_sync_lock); - pvclock_update_vm_gtod_copy(kvm); + spin_unlock(&ka->pvclock_gtod_sync_lock); kvm_for_each_vcpu(cpu, vcpu, kvm) kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); kvm_for_each_vcpu(cpu, vcpu, kvm) kvm_clear_request(KVM_REQ_MCLOCK_INPROGRESS, vcpu); - - spin_unlock(&ka->pvclock_gtod_sync_lock); } mutex_unlock(&kvm_lock); } From a83829f56c7ce17d5d05370820e185d9a23d3090 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Thu, 25 Mar 2021 14:11:14 -0400 Subject: [PATCH 0601/1091] KVM: x86: disable interrupts while pvclock_gtod_sync_lock is taken pvclock_gtod_sync_lock can be taken with interrupts disabled if the preempt notifier calls get_kvmclock_ns to update the Xen runstate information: spin_lock include/linux/spinlock.h:354 [inline] get_kvmclock_ns+0x25/0x390 arch/x86/kvm/x86.c:2587 kvm_xen_update_runstate+0x3d/0x2c0 arch/x86/kvm/xen.c:69 kvm_xen_update_runstate_guest+0x74/0x320 arch/x86/kvm/xen.c:100 kvm_xen_runstate_set_preempted arch/x86/kvm/xen.h:96 [inline] kvm_arch_vcpu_put+0x2d8/0x5a0 arch/x86/kvm/x86.c:4062 So change the users of the spinlock to spin_lock_irqsave and spin_unlock_irqrestore. Reported-by: syzbot+b282b65c2c68492df769@syzkaller.appspotmail.com Fixes: 30b5c851af79 ("KVM: x86/xen: Add support for vCPU runstate information") Cc: David Woodhouse Cc: Marcelo Tosatti Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index 2301623d3c53..e1960eed921f 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -2328,7 +2328,7 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) kvm_vcpu_write_tsc_offset(vcpu, offset); raw_spin_unlock_irqrestore(&kvm->arch.tsc_write_lock, flags); - spin_lock(&kvm->arch.pvclock_gtod_sync_lock); + spin_lock_irqsave(&kvm->arch.pvclock_gtod_sync_lock, flags); if (!matched) { kvm->arch.nr_vcpus_matched_tsc = 0; } else if (!already_matched) { @@ -2336,7 +2336,7 @@ static void kvm_synchronize_tsc(struct kvm_vcpu *vcpu, u64 data) } kvm_track_tsc_matching(vcpu); - spin_unlock(&kvm->arch.pvclock_gtod_sync_lock); + spin_unlock_irqrestore(&kvm->arch.pvclock_gtod_sync_lock, flags); } static inline void adjust_tsc_offset_guest(struct kvm_vcpu *vcpu, @@ -2558,15 +2558,16 @@ static void kvm_gen_update_masterclock(struct kvm *kvm) int i; struct kvm_vcpu *vcpu; struct kvm_arch *ka = &kvm->arch; + unsigned long flags; kvm_hv_invalidate_tsc_page(kvm); kvm_make_mclock_inprogress_request(kvm); /* no guest entries from this point */ - spin_lock(&ka->pvclock_gtod_sync_lock); + spin_lock_irqsave(&ka->pvclock_gtod_sync_lock, flags); pvclock_update_vm_gtod_copy(kvm); - spin_unlock(&ka->pvclock_gtod_sync_lock); + spin_unlock_irqrestore(&ka->pvclock_gtod_sync_lock, flags); kvm_for_each_vcpu(i, vcpu, kvm) kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); @@ -2581,17 +2582,18 @@ u64 get_kvmclock_ns(struct kvm *kvm) { struct kvm_arch *ka = &kvm->arch; struct pvclock_vcpu_time_info hv_clock; + unsigned long flags; u64 ret; - spin_lock(&ka->pvclock_gtod_sync_lock); + spin_lock_irqsave(&ka->pvclock_gtod_sync_lock, flags); if (!ka->use_master_clock) { - spin_unlock(&ka->pvclock_gtod_sync_lock); + spin_unlock_irqrestore(&ka->pvclock_gtod_sync_lock, flags); return get_kvmclock_base_ns() + ka->kvmclock_offset; } hv_clock.tsc_timestamp = ka->master_cycle_now; hv_clock.system_time = ka->master_kernel_ns + ka->kvmclock_offset; - spin_unlock(&ka->pvclock_gtod_sync_lock); + spin_unlock_irqrestore(&ka->pvclock_gtod_sync_lock, flags); /* both __this_cpu_read() and rdtsc() should be on the same cpu */ get_cpu(); @@ -2685,13 +2687,13 @@ static int kvm_guest_time_update(struct kvm_vcpu *v) * If the host uses TSC clock, then passthrough TSC as stable * to the guest. */ - spin_lock(&ka->pvclock_gtod_sync_lock); + spin_lock_irqsave(&ka->pvclock_gtod_sync_lock, flags); use_master_clock = ka->use_master_clock; if (use_master_clock) { host_tsc = ka->master_cycle_now; kernel_ns = ka->master_kernel_ns; } - spin_unlock(&ka->pvclock_gtod_sync_lock); + spin_unlock_irqrestore(&ka->pvclock_gtod_sync_lock, flags); /* Keep irq disabled to prevent changes to the clock */ local_irq_save(flags); @@ -7723,6 +7725,7 @@ static void kvm_hyperv_tsc_notifier(void) struct kvm *kvm; struct kvm_vcpu *vcpu; int cpu; + unsigned long flags; mutex_lock(&kvm_lock); list_for_each_entry(kvm, &vm_list, vm_list) @@ -7738,9 +7741,9 @@ static void kvm_hyperv_tsc_notifier(void) list_for_each_entry(kvm, &vm_list, vm_list) { struct kvm_arch *ka = &kvm->arch; - spin_lock(&ka->pvclock_gtod_sync_lock); + spin_lock_irqsave(&ka->pvclock_gtod_sync_lock, flags); pvclock_update_vm_gtod_copy(kvm); - spin_unlock(&ka->pvclock_gtod_sync_lock); + spin_unlock_irqrestore(&ka->pvclock_gtod_sync_lock, flags); kvm_for_each_vcpu(cpu, vcpu, kvm) kvm_make_request(KVM_REQ_CLOCK_UPDATE, vcpu); From 77fcbe823f002ad18426545351fa2fb94f8d5e61 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Wed, 31 Mar 2021 14:41:29 +0200 Subject: [PATCH 0602/1091] KVM: x86: Prevent 'hv_clock->system_time' from going negative in kvm_guest_time_update() When guest time is reset with KVM_SET_CLOCK(0), it is possible for 'hv_clock->system_time' to become a small negative number. This happens because in KVM_SET_CLOCK handling we set 'kvm->arch.kvmclock_offset' based on get_kvmclock_ns(kvm) but when KVM_REQ_CLOCK_UPDATE is handled, kvm_guest_time_update() does (masterclock in use case): hv_clock.system_time = ka->master_kernel_ns + v->kvm->arch.kvmclock_offset; And 'master_kernel_ns' represents the last time when masterclock got updated, it can precede KVM_SET_CLOCK() call. Normally, this is not a problem, the difference is very small, e.g. I'm observing hv_clock.system_time = -70 ns. The issue comes from the fact that 'hv_clock.system_time' is stored as unsigned and 'system_time / 100' in compute_tsc_page_parameters() becomes a very big number. Use 'master_kernel_ns' instead of get_kvmclock_ns() when masterclock is in use and get_kvmclock_base_ns() when it's not to prevent 'system_time' from going negative. Signed-off-by: Vitaly Kuznetsov Message-Id: <20210331124130.337992-2-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- arch/x86/kvm/x86.c | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index e1960eed921f..eca63625aee4 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -5727,6 +5727,7 @@ set_pit2_out: } #endif case KVM_SET_CLOCK: { + struct kvm_arch *ka = &kvm->arch; struct kvm_clock_data user_ns; u64 now_ns; @@ -5745,8 +5746,22 @@ set_pit2_out: * pvclock_update_vm_gtod_copy(). */ kvm_gen_update_masterclock(kvm); - now_ns = get_kvmclock_ns(kvm); - kvm->arch.kvmclock_offset += user_ns.clock - now_ns; + + /* + * This pairs with kvm_guest_time_update(): when masterclock is + * in use, we use master_kernel_ns + kvmclock_offset to set + * unsigned 'system_time' so if we use get_kvmclock_ns() (which + * is slightly ahead) here we risk going negative on unsigned + * 'system_time' when 'user_ns.clock' is very small. + */ + spin_lock_irq(&ka->pvclock_gtod_sync_lock); + if (kvm->arch.use_master_clock) + now_ns = ka->master_kernel_ns; + else + now_ns = get_kvmclock_base_ns(); + ka->kvmclock_offset = user_ns.clock - now_ns; + spin_unlock_irq(&ka->pvclock_gtod_sync_lock); + kvm_make_all_cpus_request(kvm, KVM_REQ_CLOCK_UPDATE); break; } From 55626ca9c6909d077eca71bccbe15fef6e5ad917 Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Fri, 26 Mar 2021 16:55:51 +0100 Subject: [PATCH 0603/1091] selftests: kvm: Check that TSC page value is small after KVM_SET_CLOCK(0) Add a test for the issue when KVM_SET_CLOCK(0) call could cause TSC page value to go very big because of a signedness issue around hv_clock->system_time. Signed-off-by: Vitaly Kuznetsov Message-Id: <20210326155551.17446-3-vkuznets@redhat.com> Signed-off-by: Paolo Bonzini --- tools/testing/selftests/kvm/x86_64/hyperv_clock.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/testing/selftests/kvm/x86_64/hyperv_clock.c b/tools/testing/selftests/kvm/x86_64/hyperv_clock.c index ffbc4555c6e2..7f1d2765572c 100644 --- a/tools/testing/selftests/kvm/x86_64/hyperv_clock.c +++ b/tools/testing/selftests/kvm/x86_64/hyperv_clock.c @@ -80,19 +80,24 @@ static inline void check_tsc_msr_rdtsc(void) GUEST_ASSERT(delta_ns * 100 < (t2 - t1) * 100); } +static inline u64 get_tscpage_ts(struct ms_hyperv_tsc_page *tsc_page) +{ + return mul_u64_u64_shr64(rdtsc(), tsc_page->tsc_scale) + tsc_page->tsc_offset; +} + static inline void check_tsc_msr_tsc_page(struct ms_hyperv_tsc_page *tsc_page) { u64 r1, r2, t1, t2; /* Compare TSC page clocksource with HV_X64_MSR_TIME_REF_COUNT */ - t1 = mul_u64_u64_shr64(rdtsc(), tsc_page->tsc_scale) + tsc_page->tsc_offset; + t1 = get_tscpage_ts(tsc_page); r1 = rdmsr(HV_X64_MSR_TIME_REF_COUNT); /* 10 ms tolerance */ GUEST_ASSERT(r1 >= t1 && r1 - t1 < 100000); nop_loop(); - t2 = mul_u64_u64_shr64(rdtsc(), tsc_page->tsc_scale) + tsc_page->tsc_offset; + t2 = get_tscpage_ts(tsc_page); r2 = rdmsr(HV_X64_MSR_TIME_REF_COUNT); GUEST_ASSERT(r2 >= t1 && r2 - t2 < 100000); } @@ -130,7 +135,11 @@ static void guest_main(struct ms_hyperv_tsc_page *tsc_page, vm_paddr_t tsc_page_ tsc_offset = tsc_page->tsc_offset; /* Call KVM_SET_CLOCK from userspace, check that TSC page was updated */ + GUEST_SYNC(7); + /* Sanity check TSC page timestamp, it should be close to 0 */ + GUEST_ASSERT(get_tscpage_ts(tsc_page) < 100000); + GUEST_ASSERT(tsc_page->tsc_offset != tsc_offset); nop_loop(); From ebf721fbbb6e077864783c8d0146021815bb1f24 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Mon, 22 Mar 2021 12:22:38 +0530 Subject: [PATCH 0604/1091] ASoC: Intel: Fix a typo s/struture/structure/ Signed-off-by: Bhaskar Chowdhury Link: https://lore.kernel.org/r/20210322065238.151920-1-unixbhaskar@gmail.com Signed-off-by: Mark Brown --- sound/soc/intel/atom/sst-mfld-dsp.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/atom/sst-mfld-dsp.h b/sound/soc/intel/atom/sst-mfld-dsp.h index 102b0e7eafb0..8d9e29b16e57 100644 --- a/sound/soc/intel/atom/sst-mfld-dsp.h +++ b/sound/soc/intel/atom/sst-mfld-dsp.h @@ -256,7 +256,7 @@ struct snd_sst_tstamp { u32 channel_peak[8]; } __packed; -/* Stream type params struture for Alloc stream */ +/* Stream type params structure for Alloc stream */ struct snd_sst_str_type { u8 codec_type; /* Codec type */ u8 str_type; /* 1 = voice 2 = music */ From 8cdddd182bd7befae6af49c5fd612893f55d6ccb Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Wed, 24 Mar 2021 16:22:19 +0100 Subject: [PATCH 0605/1091] ACPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead() Commit 496121c02127 ("ACPI: processor: idle: Allow probing on platforms with one ACPI C-state") broke CPU0 hotplug on certain systems, e.g. I'm observing the following on AWS Nitro (e.g r5b.xlarge but other instance types are affected as well): # echo 0 > /sys/devices/system/cpu/cpu0/online # echo 1 > /sys/devices/system/cpu/cpu0/online <10 seconds delay> -bash: echo: write error: Input/output error In fact, the above mentioned commit only revealed the problem and did not introduce it. On x86, to wakeup CPU an NMI is being used and hlt_play_dead()/mwait_play_dead() loops are prepared to handle it: /* * If NMI wants to wake up CPU0, start CPU0. */ if (wakeup_cpu0()) start_cpu0(); cpuidle_play_dead() -> acpi_idle_play_dead() (which is now being called on systems where it wasn't called before the above mentioned commit) serves the same purpose but it doesn't have a path for CPU0. What happens now on wakeup is: - NMI is sent to CPU0 - wakeup_cpu0_nmi() works as expected - we get back to while (1) loop in acpi_idle_play_dead() - safe_halt() puts CPU0 to sleep again. The straightforward/minimal fix is add the special handling for CPU0 on x86 and that's what the patch is doing. Fixes: 496121c02127 ("ACPI: processor: idle: Allow probing on platforms with one ACPI C-state") Signed-off-by: Vitaly Kuznetsov Cc: 5.10+ # 5.10+ Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/smp.h | 1 + arch/x86/kernel/smpboot.c | 2 +- drivers/acpi/processor_idle.c | 7 +++++++ 3 files changed, 9 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index c0538f82c9a2..57ef2094af93 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -132,6 +132,7 @@ void native_play_dead(void); void play_dead_common(void); void wbinvd_on_cpu(int cpu); int wbinvd_on_all_cpus(void); +bool wakeup_cpu0(void); void native_smp_send_reschedule(int cpu); void native_send_call_func_ipi(const struct cpumask *mask); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index 02813a7f3a7c..f877150a91da 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1659,7 +1659,7 @@ void play_dead_common(void) local_irq_disable(); } -static bool wakeup_cpu0(void) +bool wakeup_cpu0(void) { if (smp_processor_id() == 0 && enable_start_cpu0) return true; diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index d93e400940a3..768a6b4d2368 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -29,6 +29,7 @@ */ #ifdef CONFIG_X86 #include +#include #endif #define _COMPONENT ACPI_PROCESSOR_COMPONENT @@ -541,6 +542,12 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) wait_for_freeze(); } else return -ENODEV; + +#if defined(CONFIG_X86) && defined(CONFIG_HOTPLUG_CPU) + /* If NMI wants to wake up CPU0, start CPU0. */ + if (wakeup_cpu0()) + start_cpu0(); +#endif } /* Never reached */ From 1bb4bd266cf39fd2fa711f2d265c558b92df1119 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Wed, 31 Mar 2021 14:59:19 -0400 Subject: [PATCH 0606/1091] radix tree test suite: Register the main thread with the RCU library Several test runners register individual worker threads with the RCU library, but neglect to register the main thread, which can lead to objects being freed while the main thread is in what appears to be an RCU critical section. Reported-by: Chris von Recklinghausen Signed-off-by: Matthew Wilcox (Oracle) --- tools/testing/radix-tree/idr-test.c | 2 ++ tools/testing/radix-tree/multiorder.c | 2 ++ tools/testing/radix-tree/xarray.c | 2 ++ 3 files changed, 6 insertions(+) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 3b796dd5e577..44ceff95a9b3 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -577,6 +577,7 @@ void ida_tests(void) int __weak main(void) { + rcu_register_thread(); radix_tree_init(); idr_checks(); ida_tests(); @@ -584,5 +585,6 @@ int __weak main(void) rcu_barrier(); if (nr_allocated) printf("nr_allocated = %d\n", nr_allocated); + rcu_unregister_thread(); return 0; } diff --git a/tools/testing/radix-tree/multiorder.c b/tools/testing/radix-tree/multiorder.c index 9eae0fb5a67d..e00520cc6349 100644 --- a/tools/testing/radix-tree/multiorder.c +++ b/tools/testing/radix-tree/multiorder.c @@ -224,7 +224,9 @@ void multiorder_checks(void) int __weak main(void) { + rcu_register_thread(); radix_tree_init(); multiorder_checks(); + rcu_unregister_thread(); return 0; } diff --git a/tools/testing/radix-tree/xarray.c b/tools/testing/radix-tree/xarray.c index e61e43efe463..f20e12cbbfd4 100644 --- a/tools/testing/radix-tree/xarray.c +++ b/tools/testing/radix-tree/xarray.c @@ -25,11 +25,13 @@ void xarray_tests(void) int __weak main(void) { + rcu_register_thread(); radix_tree_init(); xarray_tests(); radix_tree_cpu_dead(1); rcu_barrier(); if (nr_allocated) printf("nr_allocated = %d\n", nr_allocated); + rcu_unregister_thread(); return 0; } From 703586410da69eb40062e64d413ca33bd735917a Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Thu, 1 Apr 2021 07:44:48 -0400 Subject: [PATCH 0607/1091] idr test suite: Take RCU read lock in idr_find_test_1 When run on a single CPU, this test would frequently access already-freed memory. Due to timing, this bug never showed up on multi-CPU tests. Reported-by: Chris von Recklinghausen Signed-off-by: Matthew Wilcox (Oracle) --- tools/testing/radix-tree/idr-test.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 44ceff95a9b3..4a9b451b7ba0 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -306,11 +306,15 @@ void idr_find_test_1(int anchor_id, int throbber_id) BUG_ON(idr_alloc(&find_idr, xa_mk_value(anchor_id), anchor_id, anchor_id + 1, GFP_KERNEL) != anchor_id); + rcu_read_lock(); do { int id = 0; void *entry = idr_get_next(&find_idr, &id); + rcu_read_unlock(); BUG_ON(entry != xa_mk_value(id)); + rcu_read_lock(); } while (time(NULL) < start + 11); + rcu_read_unlock(); pthread_join(throbber, NULL); From 094ffbd1d8eaa27ed426feb8530cb1456348b018 Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Thu, 1 Apr 2021 07:46:49 -0400 Subject: [PATCH 0608/1091] idr test suite: Create anchor before launching throbber The throbber could race with creation of the anchor entry and cause the IDR to have zero entries in it, which would cause the test to fail. Signed-off-by: Matthew Wilcox (Oracle) --- tools/testing/radix-tree/idr-test.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 4a9b451b7ba0..6ce7460f3c7a 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -301,11 +301,11 @@ void idr_find_test_1(int anchor_id, int throbber_id) pthread_t throbber; time_t start = time(NULL); - pthread_create(&throbber, NULL, idr_throbber, &throbber_id); - BUG_ON(idr_alloc(&find_idr, xa_mk_value(anchor_id), anchor_id, anchor_id + 1, GFP_KERNEL) != anchor_id); + pthread_create(&throbber, NULL, idr_throbber, &throbber_id); + rcu_read_lock(); do { int id = 0; From 2c7e57a02708a69d0194f9ef2a7b7e54f5a0484a Mon Sep 17 00:00:00 2001 From: "Matthew Wilcox (Oracle)" Date: Thu, 1 Apr 2021 07:50:42 -0400 Subject: [PATCH 0609/1091] idr test suite: Improve reporting from idr_find_test_1 Instead of just reporting an assertion failure, report enough information that we can start diagnosing exactly went wrong. Signed-off-by: Matthew Wilcox (Oracle) --- tools/testing/radix-tree/idr-test.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tools/testing/radix-tree/idr-test.c b/tools/testing/radix-tree/idr-test.c index 6ce7460f3c7a..ca24f6839d50 100644 --- a/tools/testing/radix-tree/idr-test.c +++ b/tools/testing/radix-tree/idr-test.c @@ -296,6 +296,10 @@ static void *idr_throbber(void *arg) return NULL; } +/* + * There are always either 1 or 2 objects in the IDR. If we find nothing, + * or we find something at an ID we didn't expect, that's a bug. + */ void idr_find_test_1(int anchor_id, int throbber_id) { pthread_t throbber; @@ -311,7 +315,12 @@ void idr_find_test_1(int anchor_id, int throbber_id) int id = 0; void *entry = idr_get_next(&find_idr, &id); rcu_read_unlock(); - BUG_ON(entry != xa_mk_value(id)); + if ((id != anchor_id && id != throbber_id) || + entry != xa_mk_value(id)) { + printf("%s(%d, %d): %p at %d\n", __func__, anchor_id, + throbber_id, entry, id); + abort(); + } rcu_read_lock(); } while (time(NULL) < start + 11); rcu_read_unlock(); From de3510e52b0a398261271455562458003b8eea62 Mon Sep 17 00:00:00 2001 From: Damien Le Moal Date: Thu, 1 Apr 2021 07:52:44 +0900 Subject: [PATCH 0610/1091] null_blk: fix command timeout completion handling Memory backed or zoned null block devices may generate actual request timeout errors due to the submission path being blocked on memory allocation or zone locking. Unlike fake timeouts or injected timeouts, the request submission path will call blk_mq_complete_request() or blk_mq_end_request() for these real timeout errors, causing a double completion and use after free situation as the block layer timeout handler executes blk_mq_rq_timed_out() and __blk_mq_free_request() in blk_mq_check_expired(). This problem often triggers a NULL pointer dereference such as: BUG: kernel NULL pointer dereference, address: 0000000000000050 RIP: 0010:blk_mq_sched_mark_restart_hctx+0x5/0x20 ... Call Trace: dd_finish_request+0x56/0x80 blk_mq_free_request+0x37/0x130 null_handle_cmd+0xbf/0x250 [null_blk] ? null_queue_rq+0x67/0xd0 [null_blk] blk_mq_dispatch_rq_list+0x122/0x850 __blk_mq_do_dispatch_sched+0xbb/0x2c0 __blk_mq_sched_dispatch_requests+0x13d/0x190 blk_mq_sched_dispatch_requests+0x30/0x60 __blk_mq_run_hw_queue+0x49/0x90 process_one_work+0x26c/0x580 worker_thread+0x55/0x3c0 ? process_one_work+0x580/0x580 kthread+0x134/0x150 ? kthread_create_worker_on_cpu+0x70/0x70 ret_from_fork+0x1f/0x30 This problem very often triggers when running the full btrfs xfstests on a memory-backed zoned null block device in a VM with limited amount of memory. Avoid this by executing blk_mq_complete_request() in null_timeout_rq() only for commands that are marked for a fake timeout completion using the fake_timeout boolean in struct null_cmd. For timeout errors injected through debugfs, the timeout handler will execute blk_mq_complete_request()i as before. This is safe as the submission path does not execute complete requests in this case. In null_timeout_rq(), also make sure to set the command error field to BLK_STS_TIMEOUT and to propagate this error through to the request completion. Reported-by: Johannes Thumshirn Signed-off-by: Damien Le Moal Tested-by: Johannes Thumshirn Reviewed-by: Johannes Thumshirn Link: https://lore.kernel.org/r/20210331225244.126426-1-damien.lemoal@wdc.com Signed-off-by: Jens Axboe --- drivers/block/null_blk/main.c | 26 +++++++++++++++++++++----- drivers/block/null_blk/null_blk.h | 1 + 2 files changed, 22 insertions(+), 5 deletions(-) diff --git a/drivers/block/null_blk/main.c b/drivers/block/null_blk/main.c index d6c821d48090..51bfd7737552 100644 --- a/drivers/block/null_blk/main.c +++ b/drivers/block/null_blk/main.c @@ -1369,10 +1369,13 @@ static blk_status_t null_handle_cmd(struct nullb_cmd *cmd, sector_t sector, } if (dev->zoned) - cmd->error = null_process_zoned_cmd(cmd, op, - sector, nr_sectors); + sts = null_process_zoned_cmd(cmd, op, sector, nr_sectors); else - cmd->error = null_process_cmd(cmd, op, sector, nr_sectors); + sts = null_process_cmd(cmd, op, sector, nr_sectors); + + /* Do not overwrite errors (e.g. timeout errors) */ + if (cmd->error == BLK_STS_OK) + cmd->error = sts; out: nullb_complete_cmd(cmd); @@ -1451,8 +1454,20 @@ static bool should_requeue_request(struct request *rq) static enum blk_eh_timer_return null_timeout_rq(struct request *rq, bool res) { + struct nullb_cmd *cmd = blk_mq_rq_to_pdu(rq); + pr_info("rq %p timed out\n", rq); - blk_mq_complete_request(rq); + + /* + * If the device is marked as blocking (i.e. memory backed or zoned + * device), the submission path may be blocked waiting for resources + * and cause real timeouts. For these real timeouts, the submission + * path will complete the request using blk_mq_complete_request(). + * Only fake timeouts need to execute blk_mq_complete_request() here. + */ + cmd->error = BLK_STS_TIMEOUT; + if (cmd->fake_timeout) + blk_mq_complete_request(rq); return BLK_EH_DONE; } @@ -1473,6 +1488,7 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, cmd->rq = bd->rq; cmd->error = BLK_STS_OK; cmd->nq = nq; + cmd->fake_timeout = should_timeout_request(bd->rq); blk_mq_start_request(bd->rq); @@ -1489,7 +1505,7 @@ static blk_status_t null_queue_rq(struct blk_mq_hw_ctx *hctx, return BLK_STS_OK; } } - if (should_timeout_request(bd->rq)) + if (cmd->fake_timeout) return BLK_STS_OK; return null_handle_cmd(cmd, sector, nr_sectors, req_op(bd->rq)); diff --git a/drivers/block/null_blk/null_blk.h b/drivers/block/null_blk/null_blk.h index 83504f3cc9d6..4876d5adb12d 100644 --- a/drivers/block/null_blk/null_blk.h +++ b/drivers/block/null_blk/null_blk.h @@ -22,6 +22,7 @@ struct nullb_cmd { blk_status_t error; struct nullb_queue *nq; struct hrtimer timer; + bool fake_timeout; }; struct nullb_queue { From 3618250c8399cb36f4a0fbc48610a178307e1c64 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Wed, 31 Mar 2021 14:14:58 +0000 Subject: [PATCH 0611/1091] powerpc/ptrace: Don't return error when getting/setting FP regs without CONFIG_PPC_FPU_REGS An #ifdef CONFIG_PPC_FPU_REGS is missing in arch_ptrace() leading to the following Oops because [REGSET_FPR] entry is not initialised in native_regsets[]. [ 41.917608] BUG: Unable to handle kernel instruction fetch [ 41.922849] Faulting instruction address: 0xff8fd228 [ 41.927760] Oops: Kernel access of bad area, sig: 11 [#1] [ 41.933089] BE PAGE_SIZE=4K PREEMPT CMPC885 [ 41.940753] Modules linked in: [ 41.943768] CPU: 0 PID: 366 Comm: gdb Not tainted 5.12.0-rc5-s3k-dev-01666-g7aac86a0f057-dirty #4835 [ 41.952800] NIP: ff8fd228 LR: c004d9e0 CTR: ff8fd228 [ 41.957790] REGS: caae9df0 TRAP: 0400 Not tainted (5.12.0-rc5-s3k-dev-01666-g7aac86a0f057-dirty) [ 41.966741] MSR: 40009032 CR: 82004248 XER: 20000000 [ 41.973540] [ 41.973540] GPR00: c004d9b4 caae9eb0 c1b64f60 c1b64520 c0713cd4 caae9eb8 c1bacdfc 00000004 [ 41.973540] GPR08: 00000200 ff8fd228 c1bac700 00001032 28004242 1061aaf4 00000001 106d64a0 [ 41.973540] GPR16: 00000000 00000000 7fa0a774 10610000 7fa0aef9 00000000 10610000 7fa0a538 [ 41.973540] GPR24: 7fa0a580 7fa0a570 c1bacc00 c1b64520 c1bacc00 caae9ee8 00000108 c0713cd4 [ 42.009685] NIP [ff8fd228] 0xff8fd228 [ 42.013300] LR [c004d9e0] __regset_get+0x100/0x124 [ 42.018036] Call Trace: [ 42.020443] [caae9eb0] [c004d9b4] __regset_get+0xd4/0x124 (unreliable) [ 42.026899] [caae9ee0] [c004da94] copy_regset_to_user+0x5c/0xb0 [ 42.032751] [caae9f10] [c002f640] sys_ptrace+0xe4/0x588 [ 42.037915] [caae9f30] [c0011010] ret_from_syscall+0x0/0x28 [ 42.043422] --- interrupt: c00 at 0xfd1f8e4 [ 42.047553] NIP: 0fd1f8e4 LR: 1004a688 CTR: 00000000 [ 42.052544] REGS: caae9f40 TRAP: 0c00 Not tainted (5.12.0-rc5-s3k-dev-01666-g7aac86a0f057-dirty) [ 42.061494] MSR: 0000d032 CR: 48004442 XER: 00000000 [ 42.068551] [ 42.068551] GPR00: 0000001a 7fa0a040 77dad7e0 0000000e 00000170 00000000 7fa0a078 00000004 [ 42.068551] GPR08: 00000000 108deb88 108dda40 106d6010 44004442 1061aaf4 00000001 106d64a0 [ 42.068551] GPR16: 00000000 00000000 7fa0a774 10610000 7fa0aef9 00000000 10610000 7fa0a538 [ 42.068551] GPR24: 7fa0a580 7fa0a570 1078fe00 1078fd70 1078fd70 00000170 0fdd3244 0000000d [ 42.104696] NIP [0fd1f8e4] 0xfd1f8e4 [ 42.108225] LR [1004a688] 0x1004a688 [ 42.111753] --- interrupt: c00 [ 42.114768] Instruction dump: [ 42.117698] XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX [ 42.125443] XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX XXXXXXXX [ 42.133195] ---[ end trace d35616f22ab2100c ]--- Adding the missing #ifdef is not good because gdb doesn't like getting an error when getting registers. Instead, make ptrace return 0s when CONFIG_PPC_FPU_REGS is not set. Fixes: b6254ced4da6 ("powerpc/signal: Don't manage floating point regs when no FPU") Cc: stable@vger.kernel.org Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/9121a44a2d50ba1af18d8aa5ada06c9a3bea8afd.1617200085.git.christophe.leroy@csgroup.eu --- arch/powerpc/kernel/ptrace/Makefile | 4 ++-- arch/powerpc/kernel/ptrace/ptrace-decl.h | 14 -------------- arch/powerpc/kernel/ptrace/ptrace-fpu.c | 10 ++++++++++ arch/powerpc/kernel/ptrace/ptrace-novsx.c | 8 ++++++++ arch/powerpc/kernel/ptrace/ptrace-view.c | 2 -- 5 files changed, 20 insertions(+), 18 deletions(-) diff --git a/arch/powerpc/kernel/ptrace/Makefile b/arch/powerpc/kernel/ptrace/Makefile index 8ebc11d1168d..77abd1a5a508 100644 --- a/arch/powerpc/kernel/ptrace/Makefile +++ b/arch/powerpc/kernel/ptrace/Makefile @@ -6,11 +6,11 @@ CFLAGS_ptrace-view.o += -DUTS_MACHINE='"$(UTS_MACHINE)"' obj-y += ptrace.o ptrace-view.o -obj-$(CONFIG_PPC_FPU_REGS) += ptrace-fpu.o +obj-y += ptrace-fpu.o obj-$(CONFIG_COMPAT) += ptrace32.o obj-$(CONFIG_VSX) += ptrace-vsx.o ifneq ($(CONFIG_VSX),y) -obj-$(CONFIG_PPC_FPU_REGS) += ptrace-novsx.o +obj-y += ptrace-novsx.o endif obj-$(CONFIG_ALTIVEC) += ptrace-altivec.o obj-$(CONFIG_SPE) += ptrace-spe.o diff --git a/arch/powerpc/kernel/ptrace/ptrace-decl.h b/arch/powerpc/kernel/ptrace/ptrace-decl.h index 3487f2c9735c..eafe5f0f6289 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-decl.h +++ b/arch/powerpc/kernel/ptrace/ptrace-decl.h @@ -165,22 +165,8 @@ int ptrace_put_reg(struct task_struct *task, int regno, unsigned long data); extern const struct user_regset_view user_ppc_native_view; /* ptrace-fpu */ -#ifdef CONFIG_PPC_FPU_REGS int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data); int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data); -#else -static inline int -ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data) -{ - return -EIO; -} - -static inline int -ptrace_put_fpr(struct task_struct *child, int index, unsigned long data) -{ - return -EIO; -} -#endif /* ptrace-(no)adv */ void ppc_gethwdinfo(struct ppc_debug_info *dbginfo); diff --git a/arch/powerpc/kernel/ptrace/ptrace-fpu.c b/arch/powerpc/kernel/ptrace/ptrace-fpu.c index 8301cb52dd99..5dca19361316 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-fpu.c +++ b/arch/powerpc/kernel/ptrace/ptrace-fpu.c @@ -8,32 +8,42 @@ int ptrace_get_fpr(struct task_struct *child, int index, unsigned long *data) { +#ifdef CONFIG_PPC_FPU_REGS unsigned int fpidx = index - PT_FPR0; +#endif if (index > PT_FPSCR) return -EIO; +#ifdef CONFIG_PPC_FPU_REGS flush_fp_to_thread(child); if (fpidx < (PT_FPSCR - PT_FPR0)) memcpy(data, &child->thread.TS_FPR(fpidx), sizeof(long)); else *data = child->thread.fp_state.fpscr; +#else + *data = 0; +#endif return 0; } int ptrace_put_fpr(struct task_struct *child, int index, unsigned long data) { +#ifdef CONFIG_PPC_FPU_REGS unsigned int fpidx = index - PT_FPR0; +#endif if (index > PT_FPSCR) return -EIO; +#ifdef CONFIG_PPC_FPU_REGS flush_fp_to_thread(child); if (fpidx < (PT_FPSCR - PT_FPR0)) memcpy(&child->thread.TS_FPR(fpidx), &data, sizeof(long)); else child->thread.fp_state.fpscr = data; +#endif return 0; } diff --git a/arch/powerpc/kernel/ptrace/ptrace-novsx.c b/arch/powerpc/kernel/ptrace/ptrace-novsx.c index b3b36835658a..7433f3db979a 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-novsx.c +++ b/arch/powerpc/kernel/ptrace/ptrace-novsx.c @@ -21,12 +21,16 @@ int fpr_get(struct task_struct *target, const struct user_regset *regset, struct membuf to) { +#ifdef CONFIG_PPC_FPU_REGS BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) != offsetof(struct thread_fp_state, fpr[32])); flush_fp_to_thread(target); return membuf_write(&to, &target->thread.fp_state, 33 * sizeof(u64)); +#else + return membuf_write(&to, &empty_zero_page, 33 * sizeof(u64)); +#endif } /* @@ -46,6 +50,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset, unsigned int pos, unsigned int count, const void *kbuf, const void __user *ubuf) { +#ifdef CONFIG_PPC_FPU_REGS BUILD_BUG_ON(offsetof(struct thread_fp_state, fpscr) != offsetof(struct thread_fp_state, fpr[32])); @@ -53,4 +58,7 @@ int fpr_set(struct task_struct *target, const struct user_regset *regset, return user_regset_copyin(&pos, &count, &kbuf, &ubuf, &target->thread.fp_state, 0, -1); +#else + return 0; +#endif } diff --git a/arch/powerpc/kernel/ptrace/ptrace-view.c b/arch/powerpc/kernel/ptrace/ptrace-view.c index 2bad8068f598..6ccffc65ac97 100644 --- a/arch/powerpc/kernel/ptrace/ptrace-view.c +++ b/arch/powerpc/kernel/ptrace/ptrace-view.c @@ -522,13 +522,11 @@ static const struct user_regset native_regsets[] = { .size = sizeof(long), .align = sizeof(long), .regset_get = gpr_get, .set = gpr_set }, -#ifdef CONFIG_PPC_FPU_REGS [REGSET_FPR] = { .core_note_type = NT_PRFPREG, .n = ELF_NFPREG, .size = sizeof(double), .align = sizeof(double), .regset_get = fpr_get, .set = fpr_set }, -#endif #ifdef CONFIG_ALTIVEC [REGSET_VMX] = { .core_note_type = NT_PPC_VMX, .n = 34, From acca57217c688c5bbbd5140974533d81e8757cc9 Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Wed, 31 Mar 2021 14:07:04 +0000 Subject: [PATCH 0612/1091] powerpc/signal32: Fix Oops on sigreturn with unmapped VDSO PPC32 encounters a KUAP fault when trying to handle a signal with VDSO unmapped. Kernel attempted to read user page (7fc07ec0) - exploit attempt? (uid: 0) BUG: Unable to handle kernel data access on read at 0x7fc07ec0 Faulting instruction address: 0xc00111d4 Oops: Kernel access of bad area, sig: 11 [#1] BE PAGE_SIZE=16K PREEMPT CMPC885 CPU: 0 PID: 353 Comm: sigreturn_vdso Not tainted 5.12.0-rc4-s3k-dev-01553-gb30c310ea220 #4814 NIP: c00111d4 LR: c0005a28 CTR: 00000000 REGS: cadb3dd0 TRAP: 0300 Not tainted (5.12.0-rc4-s3k-dev-01553-gb30c310ea220) MSR: 00009032 CR: 48000884 XER: 20000000 DAR: 7fc07ec0 DSISR: 88000000 GPR00: c0007788 cadb3e90 c28d4a40 7fc07ec0 7fc07ed0 000004e0 7fc07ce0 00000000 GPR08: 00000001 00000001 7fc07ec0 00000000 28000282 1001b828 100a0920 00000000 GPR16: 100cac0c 100b0000 105c43a4 105c5685 100d0000 100d0000 100d0000 100b2e9e GPR24: ffffffff 105c43c8 00000000 7fc07ec8 cadb3f40 cadb3ec8 c28d4a40 00000000 NIP [c00111d4] flush_icache_range+0x90/0xb4 LR [c0005a28] handle_signal32+0x1bc/0x1c4 Call Trace: [cadb3e90] [100d0000] 0x100d0000 (unreliable) [cadb3ec0] [c0007788] do_notify_resume+0x260/0x314 [cadb3f20] [c000c764] syscall_exit_prepare+0x120/0x184 [cadb3f30] [c00100b4] ret_from_syscall+0xc/0x28 --- interrupt: c00 at 0xfe807f8 NIP: 0fe807f8 LR: 10001060 CTR: c0139378 REGS: cadb3f40 TRAP: 0c00 Not tainted (5.12.0-rc4-s3k-dev-01553-gb30c310ea220) MSR: 0000d032 CR: 28000482 XER: 20000000 GPR00: 00000025 7fc081c0 77bb1690 00000000 0000000a 28000482 00000001 0ff03a38 GPR08: 0000d032 00006de5 c28d4a40 00000009 88000482 1001b828 100a0920 00000000 GPR16: 100cac0c 100b0000 105c43a4 105c5685 100d0000 100d0000 100d0000 100b2e9e GPR24: ffffffff 105c43c8 00000000 77ba7628 10002398 10010000 10002124 00024000 NIP [0fe807f8] 0xfe807f8 LR [10001060] 0x10001060 --- interrupt: c00 Instruction dump: 38630010 7c001fac 38630010 4200fff0 7c0004ac 4c00012c 4e800020 7c001fac 2c0a0000 38630010 4082ffcc 4bffffe4 <7c00186c> 2c070000 39430010 4082ff8c ---[ end trace 3973fb72b049cb06 ]--- This is because flush_icache_range() is called on user addresses. The same problem was detected some time ago on PPC64. It was fixed by enabling KUAP in commit 59bee45b9712 ("powerpc/mm: Fix missing KUAP disable in flush_coherent_icache()"). PPC32 doesn't use flush_coherent_icache() and fallbacks on clean_dcache_range() and invalidate_icache_range(). We could fix it similarly by enabling user access in those functions, but this is overkill for just flushing two instructions. The two instructions are 8 bytes aligned, so a single dcbst/icbi is enough to flush them. Do like __patch_instruction() and inline a dcbst followed by an icbi just after the write of the instructions, while user access is still allowed. The isync is not required because rfi will be used to return to user. icbi() is handled as a read so read-write user access is needed. Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/bde9154e5351a5ac7bca3d59cdb5a5e8edacbb79.1617199569.git.christophe.leroy@csgroup.eu --- arch/powerpc/kernel/signal_32.c | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/arch/powerpc/kernel/signal_32.c b/arch/powerpc/kernel/signal_32.c index 75ee918a120a..f651b992fe01 100644 --- a/arch/powerpc/kernel/signal_32.c +++ b/arch/powerpc/kernel/signal_32.c @@ -775,7 +775,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, else prepare_save_user_regs(1); - if (!user_write_access_begin(frame, sizeof(*frame))) + if (!user_access_begin(frame, sizeof(*frame))) goto badframe; /* Put the siginfo & fill in most of the ucontext */ @@ -809,17 +809,15 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, unsafe_put_user(PPC_INST_ADDI + __NR_rt_sigreturn, &mctx->mc_pad[0], failed); unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed); + asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); } unsafe_put_sigset_t(&frame->uc.uc_sigmask, oldset, failed); - user_write_access_end(); + user_access_end(); if (copy_siginfo_to_user(&frame->info, &ksig->info)) goto badframe; - if (tramp == (unsigned long)mctx->mc_pad) - flush_icache_range(tramp, tramp + 2 * sizeof(unsigned long)); - regs->link = tramp; #ifdef CONFIG_PPC_FPU_REGS @@ -844,7 +842,7 @@ int handle_rt_signal32(struct ksignal *ksig, sigset_t *oldset, return 0; failed: - user_write_access_end(); + user_access_end(); badframe: signal_fault(tsk, regs, "handle_rt_signal32", frame); @@ -879,7 +877,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, else prepare_save_user_regs(1); - if (!user_write_access_begin(frame, sizeof(*frame))) + if (!user_access_begin(frame, sizeof(*frame))) goto badframe; sc = (struct sigcontext __user *) &frame->sctx; @@ -908,11 +906,9 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, /* Set up the sigreturn trampoline: li r0,sigret; sc */ unsafe_put_user(PPC_INST_ADDI + __NR_sigreturn, &mctx->mc_pad[0], failed); unsafe_put_user(PPC_INST_SC, &mctx->mc_pad[1], failed); + asm("dcbst %y0; sync; icbi %y0; sync" :: "Z" (mctx->mc_pad[0])); } - user_write_access_end(); - - if (tramp == (unsigned long)mctx->mc_pad) - flush_icache_range(tramp, tramp + 2 * sizeof(unsigned long)); + user_access_end(); regs->link = tramp; @@ -935,7 +931,7 @@ int handle_signal32(struct ksignal *ksig, sigset_t *oldset, return 0; failed: - user_write_access_end(); + user_access_end(); badframe: signal_fault(tsk, regs, "handle_signal32", frame); From 791f9e36599d94af5a76d3f74d04e16326761aae Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Wed, 31 Mar 2021 09:12:19 +0000 Subject: [PATCH 0613/1091] powerpc/vdso: Make sure vdso_wrapper.o is rebuilt everytime vdso.so is rebuilt Commit bce74491c300 ("powerpc/vdso: fix unnecessary rebuilds of vgettimeofday.o") moved vdso32_wrapper.o and vdso64_wrapper.o out of arch/powerpc/kernel/vdso[32/64]/ and removed the dependencies in the Makefile. This leads to the wrappers not being re-build hence the kernel embedding the old vdso library. Add back missing dependencies to ensure vdso32_wrapper.o and vdso64_wrapper.o are rebuilt when vdso32.so.dbg and vdso64.so.dbg are changed. Fixes: bce74491c300 ("powerpc/vdso: fix unnecessary rebuilds of vgettimeofday.o") Cc: stable@vger.kernel.org Signed-off-by: Christophe Leroy Signed-off-by: Michael Ellerman Link: https://lore.kernel.org/r/8bb015bc98c51d8ced581415b7e3d157e18da7c9.1617181918.git.christophe.leroy@csgroup.eu --- arch/powerpc/kernel/Makefile | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/arch/powerpc/kernel/Makefile b/arch/powerpc/kernel/Makefile index 6084fa499aa3..f66b63e81c3b 100644 --- a/arch/powerpc/kernel/Makefile +++ b/arch/powerpc/kernel/Makefile @@ -191,3 +191,7 @@ $(obj)/prom_init_check: $(src)/prom_init_check.sh $(obj)/prom_init.o FORCE targets += prom_init_check clean-files := vmlinux.lds + +# Force dependency (incbin is bad) +$(obj)/vdso32_wrapper.o : $(obj)/vdso32/vdso32.so.dbg +$(obj)/vdso64_wrapper.o : $(obj)/vdso64/vdso64.so.dbg From 844b85dda2f569943e1e018fdd63b6f7d1d6f08e Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 14:18:05 +0100 Subject: [PATCH 0614/1091] ARM: keystone: fix integer overflow warning clang warns about an impossible condition when building with 32-bit phys_addr_t: arch/arm/mach-keystone/keystone.c:79:16: error: result of comparison of constant 51539607551 with expression of type 'phys_addr_t' (aka 'unsigned int') is always false [-Werror,-Wtautological-constant-out-of-range-compare] mem_end > KEYSTONE_HIGH_PHYS_END) { ~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~ arch/arm/mach-keystone/keystone.c:78:16: error: result of comparison of constant 34359738368 with expression of type 'phys_addr_t' (aka 'unsigned int') is always true [-Werror,-Wtautological-constant-out-of-range-compare] if (mem_start < KEYSTONE_HIGH_PHYS_START || ~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~ Change the temporary variable to a fixed-size u64 to avoid the warning. Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor Acked-by: Santosh Shilimkar Link: https://lore.kernel.org/r/20210323131814.2751750-1-arnd@kernel.org' Signed-off-by: Arnd Bergmann --- arch/arm/mach-keystone/keystone.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-keystone/keystone.c b/arch/arm/mach-keystone/keystone.c index cd711bfc591f..2c647bdf8d25 100644 --- a/arch/arm/mach-keystone/keystone.c +++ b/arch/arm/mach-keystone/keystone.c @@ -65,7 +65,7 @@ static void __init keystone_init(void) static long long __init keystone_pv_fixup(void) { long long offset; - phys_addr_t mem_start, mem_end; + u64 mem_start, mem_end; mem_start = memblock_start_of_DRAM(); mem_end = memblock_end_of_DRAM(); @@ -78,7 +78,7 @@ static long long __init keystone_pv_fixup(void) if (mem_start < KEYSTONE_HIGH_PHYS_START || mem_end > KEYSTONE_HIGH_PHYS_END) { pr_crit("Invalid address space for memory (%08llx-%08llx)\n", - (u64)mem_start, (u64)mem_end); + mem_start, mem_end); return 0; } From 040f31196e8b2609613f399793b9225271b79471 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 14:15:23 +0100 Subject: [PATCH 0615/1091] soc/fsl: qbman: fix conflicting alignment attributes When building with W=1, gcc points out that the __packed attribute on struct qm_eqcr_entry conflicts with the 8-byte alignment attribute on struct qm_fd inside it: drivers/soc/fsl/qbman/qman.c:189:1: error: alignment 1 of 'struct qm_eqcr_entry' is less than 8 [-Werror=packed-not-aligned] I assume that the alignment attribute is the correct one, and that qm_eqcr_entry cannot actually be unaligned in memory, so add the same alignment on the outer struct. Fixes: c535e923bb97 ("soc/fsl: Introduce DPAA 1.x QMan device driver") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210323131530.2619900-1-arnd@kernel.org' Signed-off-by: Arnd Bergmann --- drivers/soc/fsl/qbman/qman.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/fsl/qbman/qman.c b/drivers/soc/fsl/qbman/qman.c index a1b9be1d105a..fde4edd83c14 100644 --- a/drivers/soc/fsl/qbman/qman.c +++ b/drivers/soc/fsl/qbman/qman.c @@ -186,7 +186,7 @@ struct qm_eqcr_entry { __be32 tag; struct qm_fd fd; u8 __reserved3[32]; -} __packed; +} __packed __aligned(8); #define QM_EQCR_VERB_VBIT 0x80 #define QM_EQCR_VERB_CMD_MASK 0x61 /* but only one value; */ #define QM_EQCR_VERB_CMD_ENQUEUE 0x01 From 28399a5a6d569c9bdb612345e4933046ca37cde5 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Mon, 8 Mar 2021 16:34:21 +0100 Subject: [PATCH 0616/1091] ARM: omap1: fix building with clang IAS The clang integrated assembler fails to build one file with a complex asm instruction: arch/arm/mach-omap1/ams-delta-fiq-handler.S:249:2: error: invalid instruction, any one of the following would fix this: mov r10, #(1 << (((NR_IRQS_LEGACY + 12) - NR_IRQS_LEGACY) % 32)) @ set deferred_fiq bit ^ arch/arm/mach-omap1/ams-delta-fiq-handler.S:249:2: note: instruction requires: armv6t2 mov r10, #(1 << (((NR_IRQS_LEGACY + 12) - NR_IRQS_LEGACY) % 32)) @ set deferred_fiq bit ^ arch/arm/mach-omap1/ams-delta-fiq-handler.S:249:2: note: instruction requires: thumb2 mov r10, #(1 << (((NR_IRQS_LEGACY + 12) - NR_IRQS_LEGACY) % 32)) @ set deferred_fiq bit ^ The problem is that 'NR_IRQS_LEGACY' is not defined here. Apparently gas does not care because we first add and then subtract this number, leading to the immediate value to be the same regardless of the specific definition of NR_IRQS_LEGACY. Neither the way that 'gas' just silently builds this file, nor the way that clang IAS makes nonsensical suggestions for how to fix it is great. Fortunately there is an easy fix, which is to #include the header that contains the definition. Signed-off-by: Arnd Bergmann Acked-by: Tony Lindgren Link: https://lore.kernel.org/r/20210308153430.2530616-1-arnd@kernel.org' Signed-off-by: Arnd Bergmann --- arch/arm/mach-omap1/ams-delta-fiq-handler.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/mach-omap1/ams-delta-fiq-handler.S b/arch/arm/mach-omap1/ams-delta-fiq-handler.S index 14a6c3eb3298..f745a65d3bd7 100644 --- a/arch/arm/mach-omap1/ams-delta-fiq-handler.S +++ b/arch/arm/mach-omap1/ams-delta-fiq-handler.S @@ -15,6 +15,7 @@ #include #include +#include #include "ams-delta-fiq.h" #include "board-ams-delta.h" From 230ea4c761fc1a8da36044ec358e20b71441efee Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 14:08:27 +0100 Subject: [PATCH 0617/1091] ARM: pxa: mainstone: avoid -Woverride-init warning The default initializer at the start of the array causes a warning when building with W=1: In file included from arch/arm/mach-pxa/mainstone.c:47: arch/arm/mach-pxa/mainstone.h:124:33: error: initialized field overwritten [-Werror=override-init] 124 | #define MAINSTONE_IRQ(x) (MAINSTONE_NR_IRQS + (x)) | ^ arch/arm/mach-pxa/mainstone.h:133:33: note: in expansion of macro 'MAINSTONE_IRQ' 133 | #define MAINSTONE_S0_CD_IRQ MAINSTONE_IRQ(9) | ^~~~~~~~~~~~~ arch/arm/mach-pxa/mainstone.c:506:15: note: in expansion of macro 'MAINSTONE_S0_CD_IRQ' 506 | [5] = MAINSTONE_S0_CD_IRQ, | ^~~~~~~~~~~~~~~~~~~ Rework the initializer to list each element explicitly and only once. Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210323130849.2362001-1-arnd@kernel.org' Signed-off-by: Arnd Bergmann --- arch/arm/mach-pxa/mainstone.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/arch/arm/mach-pxa/mainstone.c b/arch/arm/mach-pxa/mainstone.c index d1010ec26e9f..d237bd030238 100644 --- a/arch/arm/mach-pxa/mainstone.c +++ b/arch/arm/mach-pxa/mainstone.c @@ -502,16 +502,20 @@ static inline void mainstone_init_keypad(void) {} #endif static int mst_pcmcia0_irqs[11] = { - [0 ... 10] = -1, + [0 ... 4] = -1, [5] = MAINSTONE_S0_CD_IRQ, + [6 ... 7] = -1, [8] = MAINSTONE_S0_STSCHG_IRQ, + [9] = -1, [10] = MAINSTONE_S0_IRQ, }; static int mst_pcmcia1_irqs[11] = { - [0 ... 10] = -1, + [0 ... 4] = -1, [5] = MAINSTONE_S1_CD_IRQ, + [6 ... 7] = -1, [8] = MAINSTONE_S1_STSCHG_IRQ, + [9] = -1, [10] = MAINSTONE_S1_IRQ, }; From a2fa9e57a68cd108777ded8f0443483a5fa179ed Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Tue, 23 Mar 2021 14:19:42 +0100 Subject: [PATCH 0618/1091] ARM: mvebu: avoid clang -Wtautological-constant warning Clang warns about the comparison when using a 32-bit phys_addr_t: drivers/bus/mvebu-mbus.c:621:17: error: result of comparison of constant 4294967296 with expression of type 'phys_addr_t' (aka 'unsigned int') is always false [-Werror,-Wtautological-constant-out-of-range-compare] if (reg_start >= 0x100000000ULL) Add a cast to shut up the warning. Signed-off-by: Arnd Bergmann Reviewed-by: Nathan Chancellor Link: https://lore.kernel.org/r/20210323131952.2835509-1-arnd@kernel.org' Signed-off-by: Arnd Bergmann --- drivers/bus/mvebu-mbus.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/bus/mvebu-mbus.c b/drivers/bus/mvebu-mbus.c index dd9e7343a5e3..ea0424922de7 100644 --- a/drivers/bus/mvebu-mbus.c +++ b/drivers/bus/mvebu-mbus.c @@ -618,7 +618,7 @@ mvebu_mbus_find_bridge_hole(uint64_t *start, uint64_t *end) * This part of the memory is above 4 GB, so we don't * care for the MBus bridge hole. */ - if (reg_start >= 0x100000000ULL) + if ((u64)reg_start >= 0x100000000ULL) continue; /* From 4b982bd0f383db9132e892c0c5144117359a6289 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 1 Apr 2021 08:38:34 -0600 Subject: [PATCH 0619/1091] io_uring: don't mark S_ISBLK async work as unbounded S_ISBLK is marked as unbounded work for async preparation, because it doesn't match S_ISREG. That is incorrect, as any read/write to a block device is also a bounded operation. Fix it up and ensure that S_ISBLK isn't marked unbounded. Signed-off-by: Jens Axboe --- fs/io_uring.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 6d7a1b69712b..a16b7df934d1 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -1213,7 +1213,7 @@ static void io_prep_async_work(struct io_kiocb *req) if (req->flags & REQ_F_ISREG) { if (def->hash_reg_file || (ctx->flags & IORING_SETUP_IOPOLL)) io_wq_hash_work(&req->work, file_inode(req->file)); - } else { + } else if (!req->file || !S_ISBLK(file_inode(req->file)->i_mode)) { if (def->unbound_nonreg_file) req->work.flags |= IO_WQ_WORK_UNBOUND; } From 696ee88a7c50f96573f98aa76cc74286033140c1 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 1 Apr 2021 09:55:04 +0100 Subject: [PATCH 0620/1091] io_uring/io-wq: protect against sprintf overflow task_pid may be large enough to not fit into the left space of TASK_COMM_LEN-sized buffers and overflow in sprintf. We not so care about uniqueness, so replace it with safer snprintf(). Reported-by: Alexey Dobriyan Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/1702c6145d7e1c46fbc382f28334c02e1a3d3994.1617267273.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- fs/io-wq.c | 4 ++-- fs/io_uring.c | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/fs/io-wq.c b/fs/io-wq.c index 7434eb40ca8c..433c4d3c3c1c 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -484,7 +484,7 @@ static int io_wqe_worker(void *data) worker->flags |= (IO_WORKER_F_UP | IO_WORKER_F_RUNNING); io_wqe_inc_running(worker); - sprintf(buf, "iou-wrk-%d", wq->task_pid); + snprintf(buf, sizeof(buf), "iou-wrk-%d", wq->task_pid); set_task_comm(current, buf); while (!test_bit(IO_WQ_BIT_EXIT, &wq->state)) { @@ -711,7 +711,7 @@ static int io_wq_manager(void *data) char buf[TASK_COMM_LEN]; int node; - sprintf(buf, "iou-mgr-%d", wq->task_pid); + snprintf(buf, sizeof(buf), "iou-mgr-%d", wq->task_pid); set_task_comm(current, buf); do { diff --git a/fs/io_uring.c b/fs/io_uring.c index a16b7df934d1..4a6701b5065e 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -6718,7 +6718,7 @@ static int io_sq_thread(void *data) char buf[TASK_COMM_LEN]; DEFINE_WAIT(wait); - sprintf(buf, "iou-sqp-%d", sqd->task_pid); + snprintf(buf, sizeof(buf), "iou-sqp-%d", sqd->task_pid); set_task_comm(current, buf); current->pf_io_worker = NULL; From 07204f21577a1d882f0259590c3553fe6a476381 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 1 Apr 2021 12:18:48 +0100 Subject: [PATCH 0621/1091] io_uring: fix EIOCBQUEUED iter revert iov_iter_revert() is done in completion handlers that happensf before read/write returns -EIOCBQUEUED, no need to repeat reverting afterwards. Moreover, even though it may appear being just a no-op, it's actually races with 1) user forging a new iovec of a different size 2) reissue, that is done via io-wq continues completely asynchronously. Fixes: 3e6a0d3c7571c ("io_uring: fix -EAGAIN retry with IOPOLL") Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- fs/io_uring.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 4a6701b5065e..717942474fa9 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -3284,8 +3284,6 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) ret = io_iter_do_read(req, iter); if (ret == -EIOCBQUEUED) { - if (req->async_data) - iov_iter_revert(iter, io_size - iov_iter_count(iter)); goto out_free; } else if (ret == -EAGAIN) { /* IOPOLL retry should happen for io-wq threads */ @@ -3418,8 +3416,6 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) /* no retry on NONBLOCK nor RWF_NOWAIT */ if (ret2 == -EAGAIN && (req->flags & REQ_F_NOWAIT)) goto done; - if (ret2 == -EIOCBQUEUED && req->async_data) - iov_iter_revert(iter, io_size - iov_iter_count(iter)); if (!force_nonblock || ret2 != -EAGAIN) { /* IOPOLL retry should happen for io-wq threads */ if ((req->ctx->flags & IORING_SETUP_IOPOLL) && ret2 == -EAGAIN) From 52cad756b777e82fabe05c728cc62b63b3c61fd3 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Mon, 29 Mar 2021 16:14:35 +0800 Subject: [PATCH 0622/1091] ASoC: intel, keembay-i2s: Fix a dt_binding_check warning The property "dmas" contains two items: DMA "TX" and "RX" channel, Therefore, its value also needs to be written in two parts. Otherwise, below YAML check warning is reported: Documentation/devicetree/bindings/sound/intel,keembay-i2s.example.dt.yaml:\ i2s@20140000: dmas: [[4294967295, 29, 4294967295, 33]] is too short Signed-off-by: Zhen Lei Acked-by: Rob Herring Link: https://lore.kernel.org/r/20210329081435.2200-1-thunder.leizhen@huawei.com Signed-off-by: Mark Brown --- Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml index 6f71294909a5..803627e984f6 100644 --- a/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml +++ b/Documentation/devicetree/bindings/sound/intel,keembay-i2s.yaml @@ -81,6 +81,6 @@ examples: interrupts = ; clock-names = "osc", "apb_clk"; clocks = <&scmi_clk KEEM_BAY_PSS_AUX_I2S3>, <&scmi_clk KEEM_BAY_PSS_I2S3>; - dmas = <&axi_dma0 29 &axi_dma0 33>; + dmas = <&axi_dma0 29>, <&axi_dma0 33>; dma-names = "tx", "rx"; }; From 7a75a8412fdd52a64ee860bd9708d16b1b2aa77a Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Wed, 17 Feb 2021 20:21:19 +0000 Subject: [PATCH 0623/1091] i40e: Fix inconsistent indenting Fixed new static analysis findings: "warn: inconsistent indenting" - introduced lately, reported with lkp and smatch build. Fixes: 4b208eaa8078 ("i40e: Add init and default config of software based DCB") Reported-by: kernel test robot Signed-off-by: Aleksandr Loktionov Signed-off-by: Arkadiusz Kubalewski Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index f67f0cc9dadf..af6c25fa493c 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -6738,9 +6738,9 @@ out: set_bit(__I40E_CLIENT_SERVICE_REQUESTED, pf->state); set_bit(__I40E_CLIENT_L2_CHANGE, pf->state); } - /* registers are set, lets apply */ - if (pf->hw_features & I40E_HW_USE_SET_LLDP_MIB) - ret = i40e_hw_set_dcb_config(pf, new_cfg); + /* registers are set, lets apply */ + if (pf->hw_features & I40E_HW_USE_SET_LLDP_MIB) + ret = i40e_hw_set_dcb_config(pf, new_cfg); } err: @@ -10587,7 +10587,7 @@ static void i40e_rebuild(struct i40e_pf *pf, bool reinit, bool lock_acquired) i40e_aq_set_dcb_parameters(hw, false, NULL); dev_warn(&pf->pdev->dev, "DCB is not supported for X710-T*L 2.5/5G speeds\n"); - pf->flags &= ~I40E_FLAG_DCB_CAPABLE; + pf->flags &= ~I40E_FLAG_DCB_CAPABLE; } else { i40e_aq_set_dcb_parameters(hw, true, NULL); ret = i40e_init_pf_dcb(pf); From 528060ef3e1105c5c3eba66ffbfc80e0825e2cce Mon Sep 17 00:00:00 2001 From: Magnus Karlsson Date: Fri, 19 Mar 2021 10:44:10 +0100 Subject: [PATCH 0624/1091] i40e: fix receiving of single packets in xsk zero-copy mode Fix so that single packets are received immediately instead of in batches of 8. If you sent 1 pps to a system, you received 8 packets every 8 seconds instead of 1 packet every second. The problem behind this was that the work_done reporting from the Tx part of the driver was broken. The work_done reporting in i40e controls not only the reporting back to the napi logic but also the setting of the interrupt throttling logic. When Tx or Rx reports that it has more to do, interrupts are throttled or coalesced and when they both report that they are done, interrupts are armed right away. If the wrong work_done value is returned, the logic will start to throttle interrupts in a situation where it should have just enabled them. This leads to the undesired batching behavior seen in user-space. Fix this by returning the correct boolean value from the Tx xsk zero-copy path. Return true if there is nothing to do or if we got fewer packets to process than we asked for. Return false if we got as many packets as the budget since there might be more packets we can process. Fixes: 3106c580fb7c ("i40e: Use batched xsk Tx interfaces to increase performance") Reported-by: Sreedevi Joshi Signed-off-by: Magnus Karlsson Acked-by: Maciej Fijalkowski Tested-by: Kiran Bhandare Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_xsk.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_xsk.c b/drivers/net/ethernet/intel/i40e/i40e_xsk.c index fc32c5019b0f..12ca84113587 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_xsk.c +++ b/drivers/net/ethernet/intel/i40e/i40e_xsk.c @@ -471,7 +471,7 @@ static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget) nb_pkts = xsk_tx_peek_release_desc_batch(xdp_ring->xsk_pool, descs, budget); if (!nb_pkts) - return false; + return true; if (xdp_ring->next_to_use + nb_pkts >= xdp_ring->count) { nb_processed = xdp_ring->count - xdp_ring->next_to_use; @@ -488,7 +488,7 @@ static bool i40e_xmit_zc(struct i40e_ring *xdp_ring, unsigned int budget) i40e_update_tx_stats(xdp_ring, nb_pkts, total_bytes); - return true; + return nb_pkts < budget; } /** From c3214de929dbf1b7374add8bbed30ce82b197bbb Mon Sep 17 00:00:00 2001 From: Eryk Rybak Date: Tue, 2 Mar 2021 08:46:27 +0100 Subject: [PATCH 0625/1091] i40e: Fix display statistics for veb_tc If veb-stats was enabled, the ethtool stats triggered a warning due to invalid size: 'unexpected stat size for veb.tc_%u_tx_packets'. This was due to an incorrect structure definition for the statistics. Structures and functions have been improved in line with requirements for the presentation of statistics, in particular for the functions: 'i40e_add_ethtool_stats' and 'i40e_add_stat_strings'. Fixes: 1510ae0be2a4 ("i40e: convert VEB TC stats to use an i40e_stats array") Signed-off-by: Eryk Rybak Signed-off-by: Grzegorz Szczurek Reviewed-by: Aleksandr Loktionov Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- .../net/ethernet/intel/i40e/i40e_ethtool.c | 52 ++++++++++++++++--- 1 file changed, 46 insertions(+), 6 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 2c637a5678b3..96d5202a73e8 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -232,6 +232,8 @@ static void __i40e_add_stat_strings(u8 **p, const struct i40e_stats stats[], I40E_STAT(struct i40e_vsi, _name, _stat) #define I40E_VEB_STAT(_name, _stat) \ I40E_STAT(struct i40e_veb, _name, _stat) +#define I40E_VEB_TC_STAT(_name, _stat) \ + I40E_STAT(struct i40e_cp_veb_tc_stats, _name, _stat) #define I40E_PFC_STAT(_name, _stat) \ I40E_STAT(struct i40e_pfc_stats, _name, _stat) #define I40E_QUEUE_STAT(_name, _stat) \ @@ -266,11 +268,18 @@ static const struct i40e_stats i40e_gstrings_veb_stats[] = { I40E_VEB_STAT("veb.rx_unknown_protocol", stats.rx_unknown_protocol), }; +struct i40e_cp_veb_tc_stats { + u64 tc_rx_packets; + u64 tc_rx_bytes; + u64 tc_tx_packets; + u64 tc_tx_bytes; +}; + static const struct i40e_stats i40e_gstrings_veb_tc_stats[] = { - I40E_VEB_STAT("veb.tc_%u_tx_packets", tc_stats.tc_tx_packets), - I40E_VEB_STAT("veb.tc_%u_tx_bytes", tc_stats.tc_tx_bytes), - I40E_VEB_STAT("veb.tc_%u_rx_packets", tc_stats.tc_rx_packets), - I40E_VEB_STAT("veb.tc_%u_rx_bytes", tc_stats.tc_rx_bytes), + I40E_VEB_TC_STAT("veb.tc_%u_tx_packets", tc_tx_packets), + I40E_VEB_TC_STAT("veb.tc_%u_tx_bytes", tc_tx_bytes), + I40E_VEB_TC_STAT("veb.tc_%u_rx_packets", tc_rx_packets), + I40E_VEB_TC_STAT("veb.tc_%u_rx_bytes", tc_rx_bytes), }; static const struct i40e_stats i40e_gstrings_misc_stats[] = { @@ -2217,6 +2226,29 @@ static int i40e_get_sset_count(struct net_device *netdev, int sset) } } +/** + * i40e_get_veb_tc_stats - copy VEB TC statistics to formatted structure + * @tc: the TC statistics in VEB structure (veb->tc_stats) + * @i: the index of traffic class in (veb->tc_stats) structure to copy + * + * Copy VEB TC statistics from structure of arrays (veb->tc_stats) to + * one dimensional structure i40e_cp_veb_tc_stats. + * Produce formatted i40e_cp_veb_tc_stats structure of the VEB TC + * statistics for the given TC. + **/ +static struct i40e_cp_veb_tc_stats +i40e_get_veb_tc_stats(struct i40e_veb_tc_stats *tc, unsigned int i) +{ + struct i40e_cp_veb_tc_stats veb_tc = { + .tc_rx_packets = tc->tc_rx_packets[i], + .tc_rx_bytes = tc->tc_rx_bytes[i], + .tc_tx_packets = tc->tc_tx_packets[i], + .tc_tx_bytes = tc->tc_tx_bytes[i], + }; + + return veb_tc; +} + /** * i40e_get_pfc_stats - copy HW PFC statistics to formatted structure * @pf: the PF device structure @@ -2301,8 +2333,16 @@ static void i40e_get_ethtool_stats(struct net_device *netdev, i40e_gstrings_veb_stats); for (i = 0; i < I40E_MAX_TRAFFIC_CLASS; i++) - i40e_add_ethtool_stats(&data, veb_stats ? veb : NULL, - i40e_gstrings_veb_tc_stats); + if (veb_stats) { + struct i40e_cp_veb_tc_stats veb_tc = + i40e_get_veb_tc_stats(&veb->tc_stats, i); + + i40e_add_ethtool_stats(&data, &veb_tc, + i40e_gstrings_veb_tc_stats); + } else { + i40e_add_ethtool_stats(&data, NULL, + i40e_gstrings_veb_tc_stats); + } i40e_add_ethtool_stats(&data, pf, i40e_gstrings_stats); From 185f2e5f51c2029efd9dd26cceb968a44fe053c6 Mon Sep 17 00:00:00 2001 From: Peter Collingbourne Date: Thu, 1 Apr 2021 09:51:10 -0700 Subject: [PATCH 0626/1091] arm64: fix inline asm in load_unaligned_zeropad() The inline asm's addr operand is marked as input-only, however in the case where an exception is taken it may be modified by the BIC instruction on the exception path. Fix the problem by using a temporary register as the destination register for the BIC instruction. Signed-off-by: Peter Collingbourne Cc: stable@vger.kernel.org Link: https://linux-review.googlesource.com/id/I84538c8a2307d567b4f45bb20b715451005f9617 Link: https://lore.kernel.org/r/20210401165110.3952103-1-pcc@google.com Signed-off-by: Will Deacon --- arch/arm64/include/asm/word-at-a-time.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/word-at-a-time.h b/arch/arm64/include/asm/word-at-a-time.h index 3333950b5909..ea487218db79 100644 --- a/arch/arm64/include/asm/word-at-a-time.h +++ b/arch/arm64/include/asm/word-at-a-time.h @@ -53,7 +53,7 @@ static inline unsigned long find_zero(unsigned long mask) */ static inline unsigned long load_unaligned_zeropad(const void *addr) { - unsigned long ret, offset; + unsigned long ret, tmp; /* Load word from unaligned pointer addr */ asm( @@ -61,9 +61,9 @@ static inline unsigned long load_unaligned_zeropad(const void *addr) "2:\n" " .pushsection .fixup,\"ax\"\n" " .align 2\n" - "3: and %1, %2, #0x7\n" - " bic %2, %2, #0x7\n" - " ldr %0, [%2]\n" + "3: bic %1, %2, #0x7\n" + " ldr %0, [%1]\n" + " and %1, %2, #0x7\n" " lsl %1, %1, #0x3\n" #ifndef __AARCH64EB__ " lsr %0, %0, %1\n" @@ -73,7 +73,7 @@ static inline unsigned long load_unaligned_zeropad(const void *addr) " b 2b\n" " .popsection\n" _ASM_EXTABLE(1b, 3b) - : "=&r" (ret), "=&r" (offset) + : "=&r" (ret), "=&r" (tmp) : "r" (addr), "Q" (*(unsigned long *)addr)); return ret; From 9deb193af69d3fd6dd8e47f292b67c805a787010 Mon Sep 17 00:00:00 2001 From: "Steven Rostedt (VMware)" Date: Thu, 1 Apr 2021 13:54:40 -0400 Subject: [PATCH 0627/1091] tracing: Fix stack trace event size Commit cbc3b92ce037 fixed an issue to modify the macros of the stack trace event so that user space could parse it properly. Originally the stack trace format to user space showed that the called stack was a dynamic array. But it is not actually a dynamic array, in the way that other dynamic event arrays worked, and this broke user space parsing for it. The update was to make the array look to have 8 entries in it. Helper functions were added to make it parse it correctly, as the stack was dynamic, but was determined by the size of the event stored. Although this fixed user space on how it read the event, it changed the internal structure used for the stack trace event. It changed the array size from [0] to [8] (added 8 entries). This increased the size of the stack trace event by 8 words. The size reserved on the ring buffer was the size of the stack trace event plus the number of stack entries found in the stack trace. That commit caused the amount to be 8 more than what was needed because it did not expect the caller field to have any size. This produced 8 entries of garbage (and reading random data) from the stack trace event: -0 [002] d... 1976396.837549: => trace_event_raw_event_sched_switch => __traceiter_sched_switch => __schedule => schedule_idle => do_idle => cpu_startup_entry => secondary_startup_64_no_verify => 0xc8c5e150ffff93de => 0xffff93de => 0 => 0 => 0xc8c5e17800000000 => 0x1f30affff93de => 0x00000004 => 0x200000000 Instead, subtract the size of the caller field from the size of the event to make sure that only the amount needed to store the stack trace is reserved. Link: https://lore.kernel.org/lkml/your-ad-here.call-01617191565-ext-9692@work.hours/ Cc: stable@vger.kernel.org Fixes: cbc3b92ce037 ("tracing: Set kernel_stack's caller size properly") Reported-by: Vasily Gorbik Tested-by: Vasily Gorbik Acked-by: Vasily Gorbik Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/kernel/trace/trace.c b/kernel/trace/trace.c index eccb4e1187cc..5c777627212f 100644 --- a/kernel/trace/trace.c +++ b/kernel/trace/trace.c @@ -2984,7 +2984,8 @@ static void __ftrace_trace_stack(struct trace_buffer *buffer, size = nr_entries * sizeof(unsigned long); event = __trace_buffer_lock_reserve(buffer, TRACE_STACK, - sizeof(*entry) + size, trace_ctx); + (sizeof(*entry) - sizeof(entry->caller)) + size, + trace_ctx); if (!event) goto out; entry = ring_buffer_event_data(event); From 628166c37c16250612da926c010fe6c84d086ac1 Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Thu, 1 Apr 2021 22:00:13 +0800 Subject: [PATCH 0628/1091] ASoC: Intel: Boards: cml_da7219_max98390: add capture stream for echo reference enable speaker capture dai link for feedback path Signed-off-by: Mac Chiang Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/1617285613-29457-1-git-send-email-mac.chiang@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/bxt_da7219_max98357a.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/intel/boards/bxt_da7219_max98357a.c b/sound/soc/intel/boards/bxt_da7219_max98357a.c index 0c0a717823c4..9ffef396f8f2 100644 --- a/sound/soc/intel/boards/bxt_da7219_max98357a.c +++ b/sound/soc/intel/boards/bxt_da7219_max98357a.c @@ -813,6 +813,7 @@ static int broxton_audio_probe(struct platform_device *pdev) if (ctx->spkamp == SPKAMP_MAX98390) { broxton_dais[i].codecs = max98390_codec; broxton_dais[i].num_codecs = ARRAY_SIZE(max98390_codec); + broxton_dais[i].dpcm_capture = 1; } } /* DIALOG_CODEC is connected to SSP0 */ From 7582207b1059129e59eb92026fca2cfc088a74fc Mon Sep 17 00:00:00 2001 From: Md Haris Iqbal Date: Thu, 25 Mar 2021 16:32:57 +0100 Subject: [PATCH 0629/1091] RDMA/rtrs-clt: Close rtrs client conn before destroying rtrs clt session files KASAN detected the following BUG: BUG: KASAN: use-after-free in rtrs_clt_update_wc_stats+0x41/0x100 [rtrs_client] Read of size 8 at addr ffff88bf2fb4adc0 by task swapper/0/0 CPU: 0 PID: 0 Comm: swapper/0 Tainted: G O 5.4.84-pserver #5.4.84-1+feature+linux+5.4.y+dbg+20201216.1319+b6b887b~deb10 Hardware name: Supermicro H8QG6/H8QG6, BIOS 3.00 09/04/2012 Call Trace: dump_stack+0x96/0xe0 print_address_description.constprop.4+0x1f/0x300 ? irq_work_claim+0x2e/0x50 __kasan_report.cold.8+0x78/0x92 ? rtrs_clt_update_wc_stats+0x41/0x100 [rtrs_client] kasan_report+0x10/0x20 rtrs_clt_update_wc_stats+0x41/0x100 [rtrs_client] rtrs_clt_rdma_done+0xb1/0x760 [rtrs_client] ? lockdep_hardirqs_on+0x1a8/0x290 ? process_io_rsp+0xb0/0xb0 [rtrs_client] ? mlx4_ib_destroy_cq+0x100/0x100 [mlx4_ib] ? add_interrupt_randomness+0x1a2/0x340 __ib_process_cq+0x97/0x100 [ib_core] ib_poll_handler+0x41/0xb0 [ib_core] irq_poll_softirq+0xe0/0x260 __do_softirq+0x127/0x672 irq_exit+0xd1/0xe0 do_IRQ+0xa3/0x1d0 common_interrupt+0xf/0xf RIP: 0010:cpuidle_enter_state+0xea/0x780 Code: 31 ff e8 99 48 47 ff 80 7c 24 08 00 74 12 9c 58 f6 c4 02 0f 85 53 05 00 00 31 ff e8 b0 6f 53 ff e8 ab 4f 5e ff fb 8b 44 24 04 <85> c0 0f 89 f3 01 00 00 48 8d 7b 14 e8 65 1e 77 ff c7 43 14 00 00 RSP: 0018:ffffffffab007d58 EFLAGS: 00000246 ORIG_RAX: ffffffffffffffca RAX: 0000000000000002 RBX: ffff88b803d69800 RCX: ffffffffa91a8298 RDX: 0000000000000007 RSI: dffffc0000000000 RDI: ffffffffab021414 RBP: ffffffffab6329e0 R08: 0000000000000002 R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000002 R13: 000000bf39d82466 R14: ffffffffab632aa0 R15: ffffffffab632ae0 ? lockdep_hardirqs_on+0x1a8/0x290 ? cpuidle_enter_state+0xe5/0x780 cpuidle_enter+0x3c/0x60 do_idle+0x2fb/0x390 ? arch_cpu_idle_exit+0x40/0x40 ? schedule+0x94/0x120 cpu_startup_entry+0x19/0x1b start_kernel+0x5da/0x61b ? thread_stack_cache_init+0x6/0x6 ? load_ucode_amd_bsp+0x6f/0xc4 ? init_amd_microcode+0xa6/0xa6 ? x86_family+0x5/0x20 ? load_ucode_bsp+0x182/0x1fd secondary_startup_64+0xa4/0xb0 Allocated by task 5730: save_stack+0x19/0x80 __kasan_kmalloc.constprop.9+0xc1/0xd0 kmem_cache_alloc_trace+0x15b/0x350 alloc_sess+0xf4/0x570 [rtrs_client] rtrs_clt_open+0x3b4/0x780 [rtrs_client] find_and_get_or_create_sess+0x649/0x9d0 [rnbd_client] rnbd_clt_map_device+0xd7/0xf50 [rnbd_client] rnbd_clt_map_device_store+0x4ee/0x970 [rnbd_client] kernfs_fop_write+0x141/0x240 vfs_write+0xf3/0x280 ksys_write+0xba/0x150 do_syscall_64+0x68/0x270 entry_SYSCALL_64_after_hwframe+0x49/0xbe Freed by task 5822: save_stack+0x19/0x80 __kasan_slab_free+0x125/0x170 kfree+0xe7/0x3f0 kobject_put+0xd3/0x240 rtrs_clt_destroy_sess_files+0x3f/0x60 [rtrs_client] rtrs_clt_close+0x3c/0x80 [rtrs_client] close_rtrs+0x45/0x80 [rnbd_client] rnbd_client_exit+0x10f/0x2bd [rnbd_client] __x64_sys_delete_module+0x27b/0x340 do_syscall_64+0x68/0x270 entry_SYSCALL_64_after_hwframe+0x49/0xbe When rtrs_clt_close is triggered, it iterates over all the present rtrs_clt_sess and triggers close on them. However, the call to rtrs_clt_destroy_sess_files is done before the rtrs_clt_close_conns. This is incorrect since during the initialization phase we allocate rtrs_clt_sess first, and then we go ahead and create rtrs_clt_con for it. If we free the rtrs_clt_sess structure before closing the rtrs_clt_con, it may so happen that an inflight IO completion would trigger the function rtrs_clt_rdma_done, which would lead to the above UAF case. Hence close the rtrs_clt_con connections first, and then trigger the destruction of session files. Fixes: 6a98d71daea1 ("RDMA/rtrs: client: main functionality") Link: https://lore.kernel.org/r/20210325153308.1214057-12-gi-oh.kim@ionos.com Signed-off-by: Md Haris Iqbal Signed-off-by: Jack Wang Signed-off-by: Gioh Kim Signed-off-by: Jason Gunthorpe --- drivers/infiniband/ulp/rtrs/rtrs-clt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/infiniband/ulp/rtrs/rtrs-clt.c b/drivers/infiniband/ulp/rtrs/rtrs-clt.c index 0a08b4b742a3..6734329cca33 100644 --- a/drivers/infiniband/ulp/rtrs/rtrs-clt.c +++ b/drivers/infiniband/ulp/rtrs/rtrs-clt.c @@ -2720,8 +2720,8 @@ void rtrs_clt_close(struct rtrs_clt *clt) /* Now it is safe to iterate over all paths without locks */ list_for_each_entry_safe(sess, tmp, &clt->paths_list, s.entry) { - rtrs_clt_destroy_sess_files(sess, NULL); rtrs_clt_close_conns(sess, true); + rtrs_clt_destroy_sess_files(sess, NULL); kobject_put(&sess->kobj); } free_clt(clt); From 06ab134ce8ecfa5a69e850f88f81c8a4c3fa91df Mon Sep 17 00:00:00 2001 From: Dave Marchevsky Date: Wed, 31 Mar 2021 17:07:47 -0700 Subject: [PATCH 0630/1091] bpf: Refcount task stack in bpf_get_task_stack On x86 the struct pt_regs * grabbed by task_pt_regs() points to an offset of task->stack. The pt_regs are later dereferenced in __bpf_get_stack (e.g. by user_mode() check). This can cause a fault if the task in question exits while bpf_get_task_stack is executing, as warned by task_stack_page's comment: * When accessing the stack of a non-current task that might exit, use * try_get_task_stack() instead. task_stack_page will return a pointer * that could get freed out from under you. Taking the comment's advice and using try_get_task_stack() and put_task_stack() to hold task->stack refcount, or bail early if it's already 0. Incrementing stack_refcount will ensure the task's stack sticks around while we're using its data. I noticed this bug while testing a bpf task iter similar to bpf_iter_task_stack in selftests, except mine grabbed user stack, and getting intermittent crashes, which resulted in dumps like: BUG: unable to handle page fault for address: 0000000000003fe0 \#PF: supervisor read access in kernel mode \#PF: error_code(0x0000) - not-present page RIP: 0010:__bpf_get_stack+0xd0/0x230 Call Trace: bpf_prog_0a2be35c092cb190_get_task_stacks+0x5d/0x3ec bpf_iter_run_prog+0x24/0x81 __task_seq_show+0x58/0x80 bpf_seq_read+0xf7/0x3d0 vfs_read+0x91/0x140 ksys_read+0x59/0xd0 do_syscall_64+0x48/0x120 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: fa28dcb82a38 ("bpf: Introduce helper bpf_get_task_stack()") Signed-off-by: Dave Marchevsky Signed-off-by: Alexei Starovoitov Acked-by: Song Liu Link: https://lore.kernel.org/bpf/20210401000747.3648767-1-davemarchevsky@fb.com --- kernel/bpf/stackmap.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c index be35bfb7fb13..6fbc2abe9c91 100644 --- a/kernel/bpf/stackmap.c +++ b/kernel/bpf/stackmap.c @@ -517,9 +517,17 @@ const struct bpf_func_proto bpf_get_stack_proto = { BPF_CALL_4(bpf_get_task_stack, struct task_struct *, task, void *, buf, u32, size, u64, flags) { - struct pt_regs *regs = task_pt_regs(task); + struct pt_regs *regs; + long res; - return __bpf_get_stack(regs, task, NULL, buf, size, flags); + if (!try_get_task_stack(task)) + return -EFAULT; + + regs = task_pt_regs(task); + res = __bpf_get_stack(regs, task, NULL, buf, size, flags); + put_task_stack(task); + + return res; } BTF_ID_LIST_SINGLE(bpf_get_task_stack_btf_ids, struct, task_struct) From 6a3193cdd5e5b96ac65f04ee42555c216da332af Mon Sep 17 00:00:00 2001 From: Sean Christopherson Date: Mon, 22 Mar 2021 16:44:38 -0700 Subject: [PATCH 0631/1091] kbuild: lto: Merge module sections if and only if CONFIG_LTO_CLANG is enabled Merge module sections only when using Clang LTO. With ld.bfd, merging sections does not appear to update the symbol tables for the module, e.g. 'readelf -s' shows the value that a symbol would have had, if sections were not merged. ld.lld does not show this problem. The stale symbol table breaks gdb's function disassembler, and presumably other things, e.g. gdb -batch -ex "file arch/x86/kvm/kvm.ko" -ex "disassemble kvm_init" reads the wrong bytes and dumps garbage. Fixes: dd2776222abb ("kbuild: lto: merge module sections") Cc: Nick Desaulniers Signed-off-by: Sean Christopherson Reviewed-by: Sami Tolvanen Tested-by: Sami Tolvanen Signed-off-by: Kees Cook Link: https://lore.kernel.org/r/20210322234438.502582-1-seanjc@google.com --- scripts/module.lds.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/scripts/module.lds.S b/scripts/module.lds.S index 168cd27e6122..2c52535f9b56 100644 --- a/scripts/module.lds.S +++ b/scripts/module.lds.S @@ -20,6 +20,7 @@ SECTIONS { __patchable_function_entries : { *(__patchable_function_entries) } +#ifdef CONFIG_LTO_CLANG /* * With CONFIG_LTO_CLANG, LLD always enables -fdata-sections and * -ffunction-sections, which increases the size of the final module. @@ -41,6 +42,7 @@ SECTIONS { } .text : { *(.text .text.[0-9a-zA-Z_]*) } +#endif } /* bring in arch-specific sections */ From 5620b135aea49a8f41c86aaecfcb1598a7774121 Mon Sep 17 00:00:00 2001 From: Stephen Boyd Date: Thu, 25 Mar 2021 14:28:22 -0700 Subject: [PATCH 0632/1091] drm/msm: Set drvdata to NULL when msm_drm_init() fails We should set the platform device's driver data to NULL here so that code doesn't assume the struct drm_device pointer is valid when it could have been destroyed. The lifetime of this pointer is managed by a kref but when msm_drm_init() fails we call drm_dev_put() on the pointer which will free the pointer's memory. This driver uses the component model, so there's sort of two "probes" in this file, one for the platform device i.e. msm_pdev_probe() and one for the component i.e. msm_drm_bind(). The msm_drm_bind() code is using the platform device's driver data to store struct drm_device so the two functions are intertwined. This relationship becomes a problem for msm_pdev_shutdown() when it tests the NULL-ness of the pointer to see if it should call drm_atomic_helper_shutdown(). The NULL test is a proxy check for if the pointer has been freed by kref_put(). If the drm_device has been destroyed, then we shouldn't call the shutdown helper, and we know that is the case if msm_drm_init() failed, therefore set the driver data to NULL so that this pointer liveness is tracked properly. Fixes: 9d5cbf5fe46e ("drm/msm: add shutdown support for display platform_driver") Cc: Dmitry Baryshkov Cc: Fabio Estevam Cc: Krishna Manikandan Signed-off-by: Stephen Boyd Message-Id: <20210325212822.3663144-1-swboyd@chromium.org> Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/msm_drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c index a5c6b8c23336..196907689c82 100644 --- a/drivers/gpu/drm/msm/msm_drv.c +++ b/drivers/gpu/drm/msm/msm_drv.c @@ -570,6 +570,7 @@ err_free_priv: kfree(priv); err_put_drm_dev: drm_dev_put(ddev); + platform_set_drvdata(pdev, NULL); return ret; } From 2b0b219e5ff8bcc673d3a2cb6f327b3c62c5637d Mon Sep 17 00:00:00 2001 From: John Stultz Date: Tue, 30 Mar 2021 01:34:08 +0000 Subject: [PATCH 0633/1091] drm/msm: Fix removal of valid error case when checking speed_bin Commit 7bf168c8fe8c ("drm/msm: Fix speed-bin support not to access outside valid memory"), reworked the nvmem reading of "speed_bin", but in doing so dropped handling of the -ENOENT case which was previously documented as "fine". That change resulted in the db845c board display to fail to start, with the following error: adreno 5000000.gpu: [drm:a6xx_gpu_init] *ERROR* failed to read speed-bin (-2). Some OPPs may not be supported by hardware Thus, this patch simply re-adds the ENOENT handling so the lack of the speed_bin entry isn't fatal for display, and gets things working on db845c. Cc: Rob Clark Cc: Sean Paul Cc: Jordan Crouse Cc: Eric Anholt Cc: Douglas Anderson Cc: linux-arm-msm@vger.kernel.org Cc: freedreno@lists.freedesktop.org Cc: Bjorn Andersson Cc: YongQin Liu Reported-by: YongQin Liu Fixes: 7bf168c8fe8c ("drm/msm: Fix speed-bin support not to access outside valid memory") Signed-off-by: John Stultz Reviewed-by: Akhil P Oommen Reviewed-by: Douglas Anderson Message-Id: <20210330013408.2532048-1-john.stultz@linaro.org> Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 690409ca8a18..cb2df8736ca8 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1406,7 +1406,13 @@ static int a6xx_set_supported_hw(struct device *dev, struct a6xx_gpu *a6xx_gpu, int ret; ret = nvmem_cell_read_u16(dev, "speed_bin", &speedbin); - if (ret) { + /* + * -ENOENT means that the platform doesn't support speedbin which is + * fine + */ + if (ret == -ENOENT) { + return 0; + } else if (ret) { DRM_DEV_ERROR(dev, "failed to read speed-bin (%d). Some OPPs may not be supported by hardware", ret); From 25fc94b2f02d832fa8e29419699dcc20b0b05c6a Mon Sep 17 00:00:00 2001 From: Lorenz Bauer Date: Fri, 26 Mar 2021 16:05:00 +0000 Subject: [PATCH 0634/1091] bpf: link: Refuse non-O_RDWR flags in BPF_OBJ_GET Invoking BPF_OBJ_GET on a pinned bpf_link checks the path access permissions based on file_flags, but the returned fd ignores flags. This means that any user can acquire a "read-write" fd for a pinned link with mode 0664 by invoking BPF_OBJ_GET with BPF_F_RDONLY in file_flags. The fd can be used to invoke BPF_LINK_DETACH, etc. Fix this by refusing non-O_RDWR flags in BPF_OBJ_GET. This works because OBJ_GET by default returns a read write mapping and libbpf doesn't expose a way to override this behaviour for programs and links. Fixes: 70ed506c3bbc ("bpf: Introduce pinnable bpf_link abstraction") Signed-off-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov Acked-by: Andrii Nakryiko Acked-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210326160501.46234-1-lmb@cloudflare.com --- kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index 1576ff331ee4..dc56237d6960 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -547,7 +547,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags) else if (type == BPF_TYPE_MAP) ret = bpf_map_new_fd(raw, f_flags); else if (type == BPF_TYPE_LINK) - ret = bpf_link_new_fd(raw); + ret = (f_flags != O_RDWR) ? -EINVAL : bpf_link_new_fd(raw); else return -ENOENT; From d37300ed182131f1757895a62e556332857417e5 Mon Sep 17 00:00:00 2001 From: Lorenz Bauer Date: Fri, 26 Mar 2021 16:05:01 +0000 Subject: [PATCH 0635/1091] bpf: program: Refuse non-O_RDWR flags in BPF_OBJ_GET As for bpf_link, refuse creating a non-O_RDWR fd. Since program fds currently don't allow modifications this is a precaution, not a straight up bug fix. Signed-off-by: Lorenz Bauer Signed-off-by: Alexei Starovoitov Acked-by: Andrii Nakryiko Acked-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210326160501.46234-2-lmb@cloudflare.com --- kernel/bpf/inode.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/bpf/inode.c b/kernel/bpf/inode.c index dc56237d6960..d2de2abec35b 100644 --- a/kernel/bpf/inode.c +++ b/kernel/bpf/inode.c @@ -543,7 +543,7 @@ int bpf_obj_get_user(const char __user *pathname, int flags) return PTR_ERR(raw); if (type == BPF_TYPE_PROG) - ret = bpf_prog_new_fd(raw); + ret = (f_flags != O_RDWR) ? -EINVAL : bpf_prog_new_fd(raw); else if (type == BPF_TYPE_MAP) ret = bpf_map_new_fd(raw, f_flags); else if (type == BPF_TYPE_LINK) From df662016310aa4475d7986fd726af45c8fe4f362 Mon Sep 17 00:00:00 2001 From: Ciara Loftus Date: Wed, 31 Mar 2021 06:12:16 +0000 Subject: [PATCH 0636/1091] libbpf: Ensure umem pointer is non-NULL before dereferencing Calls to xsk_socket__create dereference the umem to access the fill_save and comp_save pointers. Make sure the umem is non-NULL before doing this. Fixes: 2f6324a3937f ("libbpf: Support shared umems between queues and devices") Signed-off-by: Ciara Loftus Signed-off-by: Alexei Starovoitov Acked-by: Magnus Karlsson Link: https://lore.kernel.org/bpf/20210331061218.1647-2-ciara.loftus@intel.com --- tools/lib/bpf/xsk.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c index 526fc35c0b23..443b0cfb45e8 100644 --- a/tools/lib/bpf/xsk.c +++ b/tools/lib/bpf/xsk.c @@ -1019,6 +1019,9 @@ int xsk_socket__create(struct xsk_socket **xsk_ptr, const char *ifname, struct xsk_ring_cons *rx, struct xsk_ring_prod *tx, const struct xsk_socket_config *usr_config) { + if (!umem) + return -EFAULT; + return xsk_socket__create_shared(xsk_ptr, ifname, queue_id, umem, rx, tx, umem->fill_save, umem->comp_save, usr_config); From 43f1bc1efff16f553dd573d02eb7a15750925568 Mon Sep 17 00:00:00 2001 From: Ciara Loftus Date: Wed, 31 Mar 2021 06:12:17 +0000 Subject: [PATCH 0637/1091] libbpf: Restore umem state after socket create failure If the call to xsk_socket__create fails, the user may want to retry the socket creation using the same umem. Ensure that the umem is in the same state on exit if the call fails by: 1. ensuring the umem _save pointers are unmodified. 2. not unmapping the set of umem rings that were set up with the umem during xsk_umem__create, since those maps existed before the call to xsk_socket__create and should remain in tact even in the event of failure. Fixes: 2f6324a3937f ("libbpf: Support shared umems between queues and devices") Signed-off-by: Ciara Loftus Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20210331061218.1647-3-ciara.loftus@intel.com --- tools/lib/bpf/xsk.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c index 443b0cfb45e8..5098d9e3b55a 100644 --- a/tools/lib/bpf/xsk.c +++ b/tools/lib/bpf/xsk.c @@ -743,26 +743,30 @@ static struct xsk_ctx *xsk_get_ctx(struct xsk_umem *umem, int ifindex, return NULL; } -static void xsk_put_ctx(struct xsk_ctx *ctx) +static void xsk_put_ctx(struct xsk_ctx *ctx, bool unmap) { struct xsk_umem *umem = ctx->umem; struct xdp_mmap_offsets off; int err; - if (--ctx->refcount == 0) { - err = xsk_get_mmap_offsets(umem->fd, &off); - if (!err) { - munmap(ctx->fill->ring - off.fr.desc, - off.fr.desc + umem->config.fill_size * - sizeof(__u64)); - munmap(ctx->comp->ring - off.cr.desc, - off.cr.desc + umem->config.comp_size * - sizeof(__u64)); - } + if (--ctx->refcount) + return; - list_del(&ctx->list); - free(ctx); - } + if (!unmap) + goto out_free; + + err = xsk_get_mmap_offsets(umem->fd, &off); + if (err) + goto out_free; + + munmap(ctx->fill->ring - off.fr.desc, off.fr.desc + umem->config.fill_size * + sizeof(__u64)); + munmap(ctx->comp->ring - off.cr.desc, off.cr.desc + umem->config.comp_size * + sizeof(__u64)); + +out_free: + list_del(&ctx->list); + free(ctx); } static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk, @@ -797,8 +801,6 @@ static struct xsk_ctx *xsk_create_ctx(struct xsk_socket *xsk, memcpy(ctx->ifname, ifname, IFNAMSIZ - 1); ctx->ifname[IFNAMSIZ - 1] = '\0'; - umem->fill_save = NULL; - umem->comp_save = NULL; ctx->fill = fill; ctx->comp = comp; list_add(&ctx->list, &umem->ctx_list); @@ -854,6 +856,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, struct xsk_socket *xsk; struct xsk_ctx *ctx; int err, ifindex; + bool unmap = umem->fill_save != fill; if (!umem || !xsk_ptr || !(rx || tx)) return -EFAULT; @@ -994,6 +997,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, } *xsk_ptr = xsk; + umem->fill_save = NULL; + umem->comp_save = NULL; return 0; out_mmap_tx: @@ -1005,7 +1010,7 @@ out_mmap_rx: munmap(rx_map, off.rx.desc + xsk->config.rx_size * sizeof(struct xdp_desc)); out_put_ctx: - xsk_put_ctx(ctx); + xsk_put_ctx(ctx, unmap); out_socket: if (--umem->refcount) close(xsk->fd); @@ -1071,7 +1076,7 @@ void xsk_socket__delete(struct xsk_socket *xsk) } } - xsk_put_ctx(ctx); + xsk_put_ctx(ctx, true); umem->refcount--; /* Do not close an fd that also has an associated umem connected From ca7a83e2487ad0bc9a3e0e7a8645354aa1782f13 Mon Sep 17 00:00:00 2001 From: Ciara Loftus Date: Wed, 31 Mar 2021 06:12:18 +0000 Subject: [PATCH 0638/1091] libbpf: Only create rx and tx XDP rings when necessary Prior to this commit xsk_socket__create(_shared) always attempted to create the rx and tx rings for the socket. However this causes an issue when the socket being setup is that which shares the fd with the UMEM. If a previous call to this function failed with this socket after the rings were set up, a subsequent call would always fail because the rings are not torn down after the first call and when we try to set them up again we encounter an error because they already exist. Solve this by remembering whether the rings were set up by introducing new bools to struct xsk_umem which represent the ring setup status and using them to determine whether or not to set up the rings. Fixes: 1cad07884239 ("libbpf: add support for using AF_XDP sockets") Signed-off-by: Ciara Loftus Signed-off-by: Alexei Starovoitov Link: https://lore.kernel.org/bpf/20210331061218.1647-4-ciara.loftus@intel.com --- tools/lib/bpf/xsk.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c index 5098d9e3b55a..d24b5cc720ec 100644 --- a/tools/lib/bpf/xsk.c +++ b/tools/lib/bpf/xsk.c @@ -59,6 +59,8 @@ struct xsk_umem { int fd; int refcount; struct list_head ctx_list; + bool rx_ring_setup_done; + bool tx_ring_setup_done; }; struct xsk_ctx { @@ -857,6 +859,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, struct xsk_ctx *ctx; int err, ifindex; bool unmap = umem->fill_save != fill; + bool rx_setup_done = false, tx_setup_done = false; if (!umem || !xsk_ptr || !(rx || tx)) return -EFAULT; @@ -884,6 +887,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, } } else { xsk->fd = umem->fd; + rx_setup_done = umem->rx_ring_setup_done; + tx_setup_done = umem->tx_ring_setup_done; } ctx = xsk_get_ctx(umem, ifindex, queue_id); @@ -902,7 +907,7 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, } xsk->ctx = ctx; - if (rx) { + if (rx && !rx_setup_done) { err = setsockopt(xsk->fd, SOL_XDP, XDP_RX_RING, &xsk->config.rx_size, sizeof(xsk->config.rx_size)); @@ -910,8 +915,10 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, err = -errno; goto out_put_ctx; } + if (xsk->fd == umem->fd) + umem->rx_ring_setup_done = true; } - if (tx) { + if (tx && !tx_setup_done) { err = setsockopt(xsk->fd, SOL_XDP, XDP_TX_RING, &xsk->config.tx_size, sizeof(xsk->config.tx_size)); @@ -919,6 +926,8 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, err = -errno; goto out_put_ctx; } + if (xsk->fd == umem->fd) + umem->rx_ring_setup_done = true; } err = xsk_get_mmap_offsets(xsk->fd, &off); From 6b9fbe16955152626557ec6f439f3407b7769941 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 1 Apr 2021 07:46:24 +0300 Subject: [PATCH 0639/1091] drivers: net: fix memory leak in atusb_probe syzbot reported memory leak in atusb_probe()[1]. The problem was in atusb_alloc_urbs(). Since urb is anchored, we need to release the reference to correctly free the urb backtrace: [] kmalloc include/linux/slab.h:559 [inline] [] usb_alloc_urb+0x66/0xe0 drivers/usb/core/urb.c:74 [] atusb_alloc_urbs drivers/net/ieee802154/atusb.c:362 [inline][2] [] atusb_probe+0x158/0x820 drivers/net/ieee802154/atusb.c:1038 [1] Reported-by: syzbot+28a246747e0a465127f3@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin Signed-off-by: David S. Miller --- drivers/net/ieee802154/atusb.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ieee802154/atusb.c b/drivers/net/ieee802154/atusb.c index 0dd0ba915ab9..23ee0b14cbfa 100644 --- a/drivers/net/ieee802154/atusb.c +++ b/drivers/net/ieee802154/atusb.c @@ -365,6 +365,7 @@ static int atusb_alloc_urbs(struct atusb *atusb, int n) return -ENOMEM; } usb_anchor_urb(urb, &atusb->idle_urbs); + usb_free_urb(urb); n--; } return 0; From 98184612aca0a9ee42b8eb0262a49900ee9eef0d Mon Sep 17 00:00:00 2001 From: Norman Maurer Date: Thu, 1 Apr 2021 08:59:17 +0200 Subject: [PATCH 0640/1091] net: udp: Add support for getsockopt(..., ..., UDP_GRO, ..., ...); Support for UDP_GRO was added in the past but the implementation for getsockopt was missed which did lead to an error when we tried to retrieve the setting for UDP_GRO. This patch adds the missing switch case for UDP_GRO Fixes: e20cf8d3f1f7 ("udp: implement GRO for plain UDP sockets.") Signed-off-by: Norman Maurer Reviewed-by: David Ahern Signed-off-by: David S. Miller --- net/ipv4/udp.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 4a0478b17243..99d743eb9dc4 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -2754,6 +2754,10 @@ int udp_lib_getsockopt(struct sock *sk, int level, int optname, val = up->gso_size; break; + case UDP_GRO: + val = up->gro_enabled; + break; + /* The following two cannot be changed on UDP sockets, the return is * always 0 (which corresponds to the full checksum coverage of UDP). */ case UDPLITE_SEND_CSCOV: From a0b96b4a62745397aee662670cfc2157bac03f55 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 1 Apr 2021 16:27:52 +0300 Subject: [PATCH 0641/1091] drivers: net: fix memory leak in peak_usb_create_dev syzbot reported memory leak in peak_usb. The problem was in case of failure after calling ->dev_init()[2] in peak_usb_create_dev()[1]. The data allocated int dev_init() wasn't freed, so simple ->dev_free() call fix this problem. backtrace: [<0000000079d6542a>] kmalloc include/linux/slab.h:552 [inline] [<0000000079d6542a>] kzalloc include/linux/slab.h:682 [inline] [<0000000079d6542a>] pcan_usb_fd_init+0x156/0x210 drivers/net/can/usb/peak_usb/pcan_usb_fd.c:868 [2] [<00000000c09f9057>] peak_usb_create_dev drivers/net/can/usb/peak_usb/pcan_usb_core.c:851 [inline] [1] [<00000000c09f9057>] peak_usb_probe+0x389/0x490 drivers/net/can/usb/peak_usb/pcan_usb_core.c:949 Reported-by: syzbot+91adee8d9ebb9193d22d@syzkaller.appspotmail.com Signed-off-by: Pavel Skripkin Signed-off-by: David S. Miller --- drivers/net/can/usb/peak_usb/pcan_usb_core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/drivers/net/can/usb/peak_usb/pcan_usb_core.c b/drivers/net/can/usb/peak_usb/pcan_usb_core.c index 573b11559d73..28e916a04047 100644 --- a/drivers/net/can/usb/peak_usb/pcan_usb_core.c +++ b/drivers/net/can/usb/peak_usb/pcan_usb_core.c @@ -857,7 +857,7 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, if (dev->adapter->dev_set_bus) { err = dev->adapter->dev_set_bus(dev, 0); if (err) - goto lbl_unregister_candev; + goto adap_dev_free; } /* get device number early */ @@ -869,6 +869,10 @@ static int peak_usb_create_dev(const struct peak_usb_adapter *peak_usb_adapter, return 0; +adap_dev_free: + if (dev->adapter->dev_free) + dev->adapter->dev_free(dev); + lbl_unregister_candev: unregister_candev(netdev); From 86581852d7710990d8af9dadfe9a661f0abf2114 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 1 Apr 2021 18:57:44 +0200 Subject: [PATCH 0642/1091] mptcp: forbit mcast-related sockopt on MPTCP sockets Unrolling mcast state at msk dismantel time is bug prone, as syzkaller reported: ====================================================== WARNING: possible circular locking dependency detected 5.11.0-syzkaller #0 Not tainted ------------------------------------------------------ syz-executor905/8822 is trying to acquire lock: ffffffff8d678fe8 (rtnl_mutex){+.+.}-{3:3}, at: ipv6_sock_mc_close+0xd7/0x110 net/ipv6/mcast.c:323 but task is already holding lock: ffff888024390120 (sk_lock-AF_INET6){+.+.}-{0:0}, at: lock_sock include/net/sock.h:1600 [inline] ffff888024390120 (sk_lock-AF_INET6){+.+.}-{0:0}, at: mptcp6_release+0x57/0x130 net/mptcp/protocol.c:3507 which lock already depends on the new lock. Instead we can simply forbit any mcast-related setsockopt Fixes: 717e79c867ca5 ("mptcp: Add setsockopt()/getsockopt() socket operations") Signed-off-by: Paolo Abeni Reviewed-by: Mat Martineau Signed-off-by: David S. Miller --- net/mptcp/protocol.c | 45 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index 1590b9d4cde2..e06cea0a3c54 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -2878,6 +2878,48 @@ static int mptcp_setsockopt_v6(struct mptcp_sock *msk, int optname, return ret; } +static bool mptcp_unsupported(int level, int optname) +{ + if (level == SOL_IP) { + switch (optname) { + case IP_ADD_MEMBERSHIP: + case IP_ADD_SOURCE_MEMBERSHIP: + case IP_DROP_MEMBERSHIP: + case IP_DROP_SOURCE_MEMBERSHIP: + case IP_BLOCK_SOURCE: + case IP_UNBLOCK_SOURCE: + case MCAST_JOIN_GROUP: + case MCAST_LEAVE_GROUP: + case MCAST_JOIN_SOURCE_GROUP: + case MCAST_LEAVE_SOURCE_GROUP: + case MCAST_BLOCK_SOURCE: + case MCAST_UNBLOCK_SOURCE: + case MCAST_MSFILTER: + return true; + } + return false; + } + if (level == SOL_IPV6) { + switch (optname) { + case IPV6_ADDRFORM: + case IPV6_ADD_MEMBERSHIP: + case IPV6_DROP_MEMBERSHIP: + case IPV6_JOIN_ANYCAST: + case IPV6_LEAVE_ANYCAST: + case MCAST_JOIN_GROUP: + case MCAST_LEAVE_GROUP: + case MCAST_JOIN_SOURCE_GROUP: + case MCAST_LEAVE_SOURCE_GROUP: + case MCAST_BLOCK_SOURCE: + case MCAST_UNBLOCK_SOURCE: + case MCAST_MSFILTER: + return true; + } + return false; + } + return false; +} + static int mptcp_setsockopt(struct sock *sk, int level, int optname, sockptr_t optval, unsigned int optlen) { @@ -2886,6 +2928,9 @@ static int mptcp_setsockopt(struct sock *sk, int level, int optname, pr_debug("msk=%p", msk); + if (mptcp_unsupported(level, optname)) + return -ENOPROTOOPT; + if (level == SOL_SOCKET) return mptcp_setsockopt_sol_socket(msk, optname, optval, optlen); From 0a3cc57978d1d1448312f8973bd84dca4a71433a Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Thu, 1 Apr 2021 18:57:45 +0200 Subject: [PATCH 0643/1091] mptcp: revert "mptcp: provide subflow aware release function" This change reverts commit ad98dd37051e ("mptcp: provide subflow aware release function"). The latter introduced a deadlock spotted by syzkaller and is not needed anymore after the previous commit. Fixes: ad98dd37051e ("mptcp: provide subflow aware release function") Signed-off-by: Paolo Abeni Reviewed-by: Mat Martineau Signed-off-by: David S. Miller --- net/mptcp/protocol.c | 55 ++------------------------------------------ 1 file changed, 2 insertions(+), 53 deletions(-) diff --git a/net/mptcp/protocol.c b/net/mptcp/protocol.c index e06cea0a3c54..4bde960e19dc 100644 --- a/net/mptcp/protocol.c +++ b/net/mptcp/protocol.c @@ -11,7 +11,6 @@ #include #include #include -#include #include #include #include @@ -20,7 +19,6 @@ #include #if IS_ENABLED(CONFIG_MPTCP_IPV6) #include -#include #endif #include #include @@ -3464,34 +3462,10 @@ static __poll_t mptcp_poll(struct file *file, struct socket *sock, return mask; } -static int mptcp_release(struct socket *sock) -{ - struct mptcp_subflow_context *subflow; - struct sock *sk = sock->sk; - struct mptcp_sock *msk; - - if (!sk) - return 0; - - lock_sock(sk); - - msk = mptcp_sk(sk); - - mptcp_for_each_subflow(msk, subflow) { - struct sock *ssk = mptcp_subflow_tcp_sock(subflow); - - ip_mc_drop_socket(ssk); - } - - release_sock(sk); - - return inet_release(sock); -} - static const struct proto_ops mptcp_stream_ops = { .family = PF_INET, .owner = THIS_MODULE, - .release = mptcp_release, + .release = inet_release, .bind = mptcp_bind, .connect = mptcp_stream_connect, .socketpair = sock_no_socketpair, @@ -3583,35 +3557,10 @@ void __init mptcp_proto_init(void) } #if IS_ENABLED(CONFIG_MPTCP_IPV6) -static int mptcp6_release(struct socket *sock) -{ - struct mptcp_subflow_context *subflow; - struct mptcp_sock *msk; - struct sock *sk = sock->sk; - - if (!sk) - return 0; - - lock_sock(sk); - - msk = mptcp_sk(sk); - - mptcp_for_each_subflow(msk, subflow) { - struct sock *ssk = mptcp_subflow_tcp_sock(subflow); - - ip_mc_drop_socket(ssk); - ipv6_sock_mc_close(ssk); - ipv6_sock_ac_close(ssk); - } - - release_sock(sk); - return inet6_release(sock); -} - static const struct proto_ops mptcp_v6_stream_ops = { .family = PF_INET6, .owner = THIS_MODULE, - .release = mptcp6_release, + .release = inet6_release, .bind = mptcp_bind, .connect = mptcp_stream_connect, .socketpair = sock_no_socketpair, From 5482a9a1a8fd23fbb57afc6d409e12713aa93fa5 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Tue, 30 Mar 2021 08:19:56 +0100 Subject: [PATCH 0644/1091] scsi: hpsa: Use __packed on individual structs, not header-wide The hpsa driver uses data structures which contain a combination of driver internals and commands sent directly to the hardware. To manage alignment for the hardware portions the driver used #pragma pack(1). Commit f749d8b7a989 ("scsi: hpsa: Correct dev cmds outstanding for retried cmds") switched an existing variable from int to bool. Due to the pragma an atomic_t in the same data structure ended up being misaligned and broke boot on ia64. Add __packed to every struct and union in the header file. Subsequent commits will address the actual atomic_t misalignment regression. The commit is a no-op at least on ia64: $ diff -u <(objdump -d -r old.o) <(objdump -d -r new.o) Link: https://lore.kernel.org/r/20210330071958.3788214-1-slyfox@gentoo.org Fixes: f749d8b7a989 ("scsi: hpsa: Correct dev cmds outstanding for retried cmds") CC: linux-ia64@vger.kernel.org CC: storagedev@microchip.com CC: linux-scsi@vger.kernel.org CC: Joe Szczypek CC: Scott Benesh CC: Scott Teel CC: Tomas Henzl CC: "Martin K. Petersen" CC: Don Brace Reported-by: John Paul Adrian Glaubitz Suggested-by: Don Brace Reviewed-by: Arnd Bergmann Signed-off-by: Sergei Trofimovich Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa_cmd.h | 68 ++++++++++++++++++++--------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index d126bb877250..280e933d27e7 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -20,6 +20,8 @@ #ifndef HPSA_CMD_H #define HPSA_CMD_H +#include + /* general boundary defintions */ #define SENSEINFOBYTES 32 /* may vary between hbas */ #define SG_ENTRIES_IN_CMD 32 /* Max SG entries excluding chain blocks */ @@ -200,12 +202,10 @@ union u64bit { MAX_EXT_TARGETS + 1) /* + 1 is for the controller itself */ /* SCSI-3 Commands */ -#pragma pack(1) - #define HPSA_INQUIRY 0x12 struct InquiryData { u8 data_byte[36]; -}; +} __packed; #define HPSA_REPORT_LOG 0xc2 /* Report Logical LUNs */ #define HPSA_REPORT_PHYS 0xc3 /* Report Physical LUNs */ @@ -221,7 +221,7 @@ struct raid_map_disk_data { u8 xor_mult[2]; /**< XOR multipliers for this position, * valid for data disks only */ u8 reserved[2]; -}; +} __packed; struct raid_map_data { __le32 structure_size; /* Size of entire structure in bytes */ @@ -247,14 +247,14 @@ struct raid_map_data { __le16 dekindex; /* Data encryption key index. */ u8 reserved[16]; struct raid_map_disk_data data[RAID_MAP_MAX_ENTRIES]; -}; +} __packed; struct ReportLUNdata { u8 LUNListLength[4]; u8 extended_response_flag; u8 reserved[3]; u8 LUN[HPSA_MAX_LUN][8]; -}; +} __packed; struct ext_report_lun_entry { u8 lunid[8]; @@ -269,20 +269,20 @@ struct ext_report_lun_entry { u8 lun_count; /* multi-lun device, how many luns */ u8 redundant_paths; u32 ioaccel_handle; /* ioaccel1 only uses lower 16 bits */ -}; +} __packed; struct ReportExtendedLUNdata { u8 LUNListLength[4]; u8 extended_response_flag; u8 reserved[3]; struct ext_report_lun_entry LUN[HPSA_MAX_PHYS_LUN]; -}; +} __packed; struct SenseSubsystem_info { u8 reserved[36]; u8 portname[8]; u8 reserved1[1108]; -}; +} __packed; /* BMIC commands */ #define BMIC_READ 0x26 @@ -317,7 +317,7 @@ union SCSI3Addr { u8 Targ:6; u8 Mode:2; /* b10 */ } LogUnit; -}; +} __packed; struct PhysDevAddr { u32 TargetId:24; @@ -325,20 +325,20 @@ struct PhysDevAddr { u32 Mode:2; /* 2 level target device addr */ union SCSI3Addr Target[2]; -}; +} __packed; struct LogDevAddr { u32 VolId:30; u32 Mode:2; u8 reserved[4]; -}; +} __packed; union LUNAddr { u8 LunAddrBytes[8]; union SCSI3Addr SCSI3Lun[4]; struct PhysDevAddr PhysDev; struct LogDevAddr LogDev; -}; +} __packed; struct CommandListHeader { u8 ReplyQueue; @@ -346,7 +346,7 @@ struct CommandListHeader { __le16 SGTotal; __le64 tag; union LUNAddr LUN; -}; +} __packed; struct RequestBlock { u8 CDBLen; @@ -365,18 +365,18 @@ struct RequestBlock { #define GET_DIR(tad) (((tad) >> 6) & 0x03) u16 Timeout; u8 CDB[16]; -}; +} __packed; struct ErrDescriptor { __le64 Addr; __le32 Len; -}; +} __packed; struct SGDescriptor { __le64 Addr; __le32 Len; __le32 Ext; -}; +} __packed; union MoreErrInfo { struct { @@ -390,7 +390,8 @@ union MoreErrInfo { u8 offense_num; /* byte # of offense 0-base */ u32 offense_value; } Invalid_Cmd; -}; +} __packed; + struct ErrorInfo { u8 ScsiStatus; u8 SenseLen; @@ -398,7 +399,7 @@ struct ErrorInfo { u32 ResidualCnt; union MoreErrInfo MoreErrInfo; u8 SenseInfo[SENSEINFOBYTES]; -}; +} __packed; /* Command types */ #define CMD_IOCTL_PEND 0x01 #define CMD_SCSI 0x03 @@ -451,7 +452,7 @@ struct CommandList { bool retry_pending; struct hpsa_scsi_dev_t *device; atomic_t refcount; /* Must be last to avoid memset in hpsa_cmd_init() */ -} __aligned(COMMANDLIST_ALIGNMENT); +} __packed __aligned(COMMANDLIST_ALIGNMENT); /* Max S/G elements in I/O accelerator command */ #define IOACCEL1_MAXSGENTRIES 24 @@ -489,7 +490,7 @@ struct io_accel1_cmd { __le64 host_addr; /* 0x70 - 0x77 */ u8 CISS_LUN[8]; /* 0x78 - 0x7F */ struct SGDescriptor SG[IOACCEL1_MAXSGENTRIES]; -} __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT); +} __packed __aligned(IOACCEL1_COMMANDLIST_ALIGNMENT); #define IOACCEL1_FUNCTION_SCSIIO 0x00 #define IOACCEL1_SGLOFFSET 32 @@ -519,7 +520,7 @@ struct ioaccel2_sg_element { u8 chain_indicator; #define IOACCEL2_CHAIN 0x80 #define IOACCEL2_LAST_SG 0x40 -}; +} __packed; /* * SCSI Response Format structure for IO Accelerator Mode 2 @@ -559,7 +560,7 @@ struct io_accel2_scsi_response { u8 sense_data_len; /* sense/response data length */ u8 resid_cnt[4]; /* residual count */ u8 sense_data_buff[32]; /* sense/response data buffer */ -}; +} __packed; /* * Structure for I/O accelerator (mode 2 or m2) commands. @@ -592,7 +593,7 @@ struct io_accel2_cmd { __le32 tweak_upper; /* Encryption tweak, upper 4 bytes */ struct ioaccel2_sg_element sg[IOACCEL2_MAXSGENTRIES]; struct io_accel2_scsi_response error_data; -} __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT); +} __packed __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT); /* * defines for Mode 2 command struct @@ -618,7 +619,7 @@ struct hpsa_tmf_struct { __le64 abort_tag; /* cciss tag of SCSI cmd or TMF to abort */ __le64 error_ptr; /* Error Pointer */ __le32 error_len; /* Error Length */ -} __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT); +} __packed __aligned(IOACCEL2_COMMANDLIST_ALIGNMENT); /* Configuration Table Structure */ struct HostWrite { @@ -626,7 +627,7 @@ struct HostWrite { __le32 command_pool_addr_hi; __le32 CoalIntDelay; __le32 CoalIntCount; -}; +} __packed; #define SIMPLE_MODE 0x02 #define PERFORMANT_MODE 0x04 @@ -675,7 +676,7 @@ struct CfgTable { #define HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_STATE_CHANGE (1 << 30) #define HPSA_EVENT_NOTIFY_ACCEL_IO_PATH_CONFIG_CHANGE (1 << 31) __le32 clear_event_notify; -}; +} __packed; #define NUM_BLOCKFETCH_ENTRIES 8 struct TransTable_struct { @@ -686,14 +687,14 @@ struct TransTable_struct { __le32 RepQCtrAddrHigh32; #define MAX_REPLY_QUEUES 64 struct vals32 RepQAddr[MAX_REPLY_QUEUES]; -}; +} __packed; struct hpsa_pci_info { unsigned char bus; unsigned char dev_fn; unsigned short domain; u32 board_id; -}; +} __packed; struct bmic_identify_controller { u8 configured_logical_drive_count; /* offset 0 */ @@ -702,7 +703,7 @@ struct bmic_identify_controller { u8 pad2[136]; u8 controller_mode; /* offset 292 */ u8 pad3[32]; -}; +} __packed; struct bmic_identify_physical_device { @@ -845,7 +846,7 @@ struct bmic_identify_physical_device { u8 max_link_rate[256]; u8 neg_phys_link_rate[256]; u8 box_conn_name[8]; -} __attribute((aligned(512))); +} __packed __attribute((aligned(512))); struct bmic_sense_subsystem_info { u8 primary_slot_number; @@ -858,7 +859,7 @@ struct bmic_sense_subsystem_info { u8 secondary_array_serial_number[32]; u8 secondary_cache_serial_number[32]; u8 pad[332]; -}; +} __packed; struct bmic_sense_storage_box_params { u8 reserved[36]; @@ -870,7 +871,6 @@ struct bmic_sense_storage_box_params { u8 reserver_3[84]; u8 phys_connector[2]; u8 reserved_4[296]; -}; +} __packed; -#pragma pack() #endif /* HPSA_CMD_H */ From 02ec144292bc424a5800d45d4cb472c66e97c520 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Tue, 30 Mar 2021 08:19:57 +0100 Subject: [PATCH 0645/1091] scsi: hpsa: Fix boot on ia64 (atomic_t alignment) Boot failure was observed on an HP rx3600 ia64 machine with RAID bus controller: Hewlett-Packard Company Smart Array P600: kernel unaligned access to 0xe000000105dd8b95, ip=0xa000000100b87551 kernel unaligned access to 0xe000000105dd8e95, ip=0xa000000100b87551 hpsa 0000:14:01.0: Controller reports max supported commands of 0 Using 16 instead. Ensure that firmware is up to date. swapper/0[1]: error during unaligned kernel access The unaligned access comes from 'struct CommandList' that happens to be packed. Commit f749d8b7a989 ("scsi: hpsa: Correct dev cmds outstanding for retried cmds") introduced unexpected padding and unaligned atomic_t from natural alignment to something else. This change removes packing annotation from a struct not intended to be sent to controller as is. This restores natural `atomic_t` alignment. The change was tested on the same rx3600 machine. Link: https://lore.kernel.org/r/20210330071958.3788214-2-slyfox@gentoo.org Fixes: f749d8b7a989 ("scsi: hpsa: Correct dev cmds outstanding for retried cmds") CC: linux-ia64@vger.kernel.org CC: linux-kernel@vger.kernel.org CC: storagedev@microchip.com CC: linux-scsi@vger.kernel.org CC: Joe Szczypek CC: Scott Benesh CC: Scott Teel CC: Tomas Henzl CC: "Martin K. Petersen" CC: Don Brace Reported-by: John Paul Adrian Glaubitz Suggested-by: Don Brace Reviewed-by: Arnd Bergmann Signed-off-by: Sergei Trofimovich Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa_cmd.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 280e933d27e7..885b1f1fb20a 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -452,7 +452,7 @@ struct CommandList { bool retry_pending; struct hpsa_scsi_dev_t *device; atomic_t refcount; /* Must be last to avoid memset in hpsa_cmd_init() */ -} __packed __aligned(COMMANDLIST_ALIGNMENT); +} __aligned(COMMANDLIST_ALIGNMENT); /* Max S/G elements in I/O accelerator command */ #define IOACCEL1_MAXSGENTRIES 24 From e01a00ff62adca8ec464f3c8d82cfa0e8d8728dd Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Tue, 30 Mar 2021 08:19:58 +0100 Subject: [PATCH 0646/1091] scsi: hpsa: Add an assert to prevent __packed reintroduction Link: https://lore.kernel.org/r/20210330071958.3788214-3-slyfox@gentoo.org Fixes: f749d8b7a989 ("scsi: hpsa: Correct dev cmds outstanding for retried cmds") CC: linux-ia64@vger.kernel.org CC: storagedev@microchip.com CC: linux-scsi@vger.kernel.org CC: Joe Szczypek CC: Scott Benesh CC: Scott Teel CC: Tomas Henzl CC: "Martin K. Petersen" CC: Don Brace Reported-by: John Paul Adrian Glaubitz Suggested-by: Don Brace Reviewed-by: Arnd Bergmann Signed-off-by: Sergei Trofimovich Signed-off-by: Martin K. Petersen --- drivers/scsi/hpsa_cmd.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/drivers/scsi/hpsa_cmd.h b/drivers/scsi/hpsa_cmd.h index 885b1f1fb20a..ba6a3aa8d954 100644 --- a/drivers/scsi/hpsa_cmd.h +++ b/drivers/scsi/hpsa_cmd.h @@ -22,6 +22,9 @@ #include +#include /* static_assert */ +#include /* offsetof */ + /* general boundary defintions */ #define SENSEINFOBYTES 32 /* may vary between hbas */ #define SG_ENTRIES_IN_CMD 32 /* Max SG entries excluding chain blocks */ @@ -454,6 +457,15 @@ struct CommandList { atomic_t refcount; /* Must be last to avoid memset in hpsa_cmd_init() */ } __aligned(COMMANDLIST_ALIGNMENT); +/* + * Make sure our embedded atomic variable is aligned. Otherwise we break atomic + * operations on architectures that don't support unaligned atomics like IA64. + * + * The assert guards against reintroductin against unwanted __packed to + * the struct CommandList. + */ +static_assert(offsetof(struct CommandList, refcount) % __alignof__(atomic_t) == 0); + /* Max S/G elements in I/O accelerator command */ #define IOACCEL1_MAXSGENTRIES 24 #define IOACCEL2_MAXSGENTRIES 28 From 1235fc569e0bf541ddda0a1224d4c6fa6d914890 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Thu, 1 Apr 2021 00:39:08 -0700 Subject: [PATCH 0647/1091] scsi: ufs: core: Fix task management request completion timeout ufshcd_tmc_handler() calls blk_mq_tagset_busy_iter(fn = ufshcd_compl_tm()), but since blk_mq_tagset_busy_iter() only iterates over all reserved tags and requests which are not in IDLE state, ufshcd_compl_tm() never gets a chance to run. Thus, TMR always ends up with completion timeout. Fix it by calling blk_mq_start_request() in __ufshcd_issue_tm_cmd(). Link: https://lore.kernel.org/r/1617262750-4864-2-git-send-email-cang@codeaurora.org Fixes: 69a6c269c097 ("scsi: ufs: Use blk_{get,put}_request() to allocate and free TMFs") Reviewed-by: Bart Van Assche Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index c86760788c72..564918ffc026 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6404,6 +6404,7 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, spin_lock_irqsave(host->host_lock, flags); task_tag = hba->nutrs + free_slot; + blk_mq_start_request(req); treq->req_header.dword_0 |= cpu_to_be32(task_tag); From 4b42d557a8add52b9a9924fb31e40a218aab7801 Mon Sep 17 00:00:00 2001 From: Can Guo Date: Thu, 1 Apr 2021 00:39:09 -0700 Subject: [PATCH 0648/1091] scsi: ufs: core: Fix wrong Task Tag used in task management request UPIUs In __ufshcd_issue_tm_cmd(), it is not correct to use hba->nutrs + req->tag as the Task Tag in a TMR UPIU. Directly use req->tag as the Task Tag. Fixes: e293313262d3 ("scsi: ufs: Fix broken task management command implementation") Link: https://lore.kernel.org/r/1617262750-4864-3-git-send-email-cang@codeaurora.org Reviewed-by: Bart Van Assche Signed-off-by: Can Guo Signed-off-by: Martin K. Petersen --- drivers/scsi/ufs/ufshcd.c | 30 +++++++++++++----------------- 1 file changed, 13 insertions(+), 17 deletions(-) diff --git a/drivers/scsi/ufs/ufshcd.c b/drivers/scsi/ufs/ufshcd.c index 564918ffc026..d3d05e997c13 100644 --- a/drivers/scsi/ufs/ufshcd.c +++ b/drivers/scsi/ufs/ufshcd.c @@ -6386,38 +6386,34 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, DECLARE_COMPLETION_ONSTACK(wait); struct request *req; unsigned long flags; - int free_slot, task_tag, err; + int task_tag, err; /* - * Get free slot, sleep if slots are unavailable. - * Even though we use wait_event() which sleeps indefinitely, - * the maximum wait time is bounded by %TM_CMD_TIMEOUT. + * blk_get_request() is used here only to get a free tag. */ req = blk_get_request(q, REQ_OP_DRV_OUT, 0); if (IS_ERR(req)) return PTR_ERR(req); req->end_io_data = &wait; - free_slot = req->tag; - WARN_ON_ONCE(free_slot < 0 || free_slot >= hba->nutmrs); ufshcd_hold(hba, false); spin_lock_irqsave(host->host_lock, flags); - task_tag = hba->nutrs + free_slot; blk_mq_start_request(req); + task_tag = req->tag; treq->req_header.dword_0 |= cpu_to_be32(task_tag); - memcpy(hba->utmrdl_base_addr + free_slot, treq, sizeof(*treq)); - ufshcd_vops_setup_task_mgmt(hba, free_slot, tm_function); + memcpy(hba->utmrdl_base_addr + task_tag, treq, sizeof(*treq)); + ufshcd_vops_setup_task_mgmt(hba, task_tag, tm_function); /* send command to the controller */ - __set_bit(free_slot, &hba->outstanding_tasks); + __set_bit(task_tag, &hba->outstanding_tasks); /* Make sure descriptors are ready before ringing the task doorbell */ wmb(); - ufshcd_writel(hba, 1 << free_slot, REG_UTP_TASK_REQ_DOOR_BELL); + ufshcd_writel(hba, 1 << task_tag, REG_UTP_TASK_REQ_DOOR_BELL); /* Make sure that doorbell is committed immediately */ wmb(); @@ -6437,24 +6433,24 @@ static int __ufshcd_issue_tm_cmd(struct ufs_hba *hba, ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_ERR); dev_err(hba->dev, "%s: task management cmd 0x%.2x timed-out\n", __func__, tm_function); - if (ufshcd_clear_tm_cmd(hba, free_slot)) - dev_WARN(hba->dev, "%s: unable clear tm cmd (slot %d) after timeout\n", - __func__, free_slot); + if (ufshcd_clear_tm_cmd(hba, task_tag)) + dev_WARN(hba->dev, "%s: unable to clear tm cmd (slot %d) after timeout\n", + __func__, task_tag); err = -ETIMEDOUT; } else { err = 0; - memcpy(treq, hba->utmrdl_base_addr + free_slot, sizeof(*treq)); + memcpy(treq, hba->utmrdl_base_addr + task_tag, sizeof(*treq)); ufshcd_add_tm_upiu_trace(hba, task_tag, UFS_TM_COMP); } spin_lock_irqsave(hba->host->host_lock, flags); - __clear_bit(free_slot, &hba->outstanding_tasks); + __clear_bit(task_tag, &hba->outstanding_tasks); spin_unlock_irqrestore(hba->host->host_lock, flags); + ufshcd_release(hba); blk_put_request(req); - ufshcd_release(hba); return err; } From 23c1075ae83adaf14ea3f727c40368799f80bccc Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Wed, 17 Mar 2021 23:08:38 +0800 Subject: [PATCH 0649/1091] riscv: Drop const annotation for sp The const annotation should not be used for 'sp', or it will become read only and lead to bad stack output. Fixes: dec822771b01 ("riscv: stacktrace: Move register keyword to beginning of declaration") Signed-off-by: Kefeng Wang Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/stacktrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/kernel/stacktrace.c b/arch/riscv/kernel/stacktrace.c index 3f893c9d9d85..2b3e0cb90d78 100644 --- a/arch/riscv/kernel/stacktrace.c +++ b/arch/riscv/kernel/stacktrace.c @@ -14,7 +14,7 @@ #include -register const unsigned long sp_in_global __asm__("sp"); +register unsigned long sp_in_global __asm__("sp"); #ifdef CONFIG_FRAME_POINTER From 285a76bb2cf51b0c74c634f2aaccdb93e1f2a359 Mon Sep 17 00:00:00 2001 From: Ben Dooks Date: Mon, 29 Mar 2021 10:57:49 +0100 Subject: [PATCH 0650/1091] riscv: evaluate put_user() arg before enabling user access The header has a problem with put_user(a, ptr) if the 'a' is not a simple variable, such as a function. This can lead to the compiler producing code as so: 1: enable_user_access() 2: evaluate 'a' into register 'r' 3: put 'r' to 'ptr' 4: disable_user_acess() The issue is that 'a' is now being evaluated with the user memory protections disabled. So we try and force the evaulation by assigning 'x' to __val at the start, and hoping the compiler barriers in enable_user_access() do the job of ordering step 2 before step 1. This has shown up in a bug where 'a' sleeps and thus schedules out and loses the SR_SUM flag. This isn't sufficient to fully fix, but should reduce the window of opportunity. The first instance of this we found is in scheudle_tail() where the code does: $ less -N kernel/sched/core.c 4263 if (current->set_child_tid) 4264 put_user(task_pid_vnr(current), current->set_child_tid); Here, the task_pid_vnr(current) is called within the block that has enabled the user memory access. This can be made worse with KASAN which makes task_pid_vnr() a rather large call with plenty of opportunity to sleep. Signed-off-by: Ben Dooks Reported-by: syzbot+e74b94fe601ab9552d69@syzkaller.appspotmail.com Suggested-by: Arnd Bergman -- Changes since v1: - fixed formatting and updated the patch description with more info Changes since v2: - fixed commenting on __put_user() (schwab@linux-m68k.org) Change since v3: - fixed RFC in patch title. Should be ready to merge. Signed-off-by: Palmer Dabbelt --- arch/riscv/include/asm/uaccess.h | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/arch/riscv/include/asm/uaccess.h b/arch/riscv/include/asm/uaccess.h index 824b2c9da75b..f944062c9d99 100644 --- a/arch/riscv/include/asm/uaccess.h +++ b/arch/riscv/include/asm/uaccess.h @@ -306,7 +306,9 @@ do { \ * data types like structures or arrays. * * @ptr must have pointer-to-simple-variable type, and @x must be assignable - * to the result of dereferencing @ptr. + * to the result of dereferencing @ptr. The value of @x is copied to avoid + * re-ordering where @x is evaluated inside the block that enables user-space + * access (thus bypassing user space protection if @x is a function). * * Caller must check the pointer with access_ok() before calling this * function. @@ -316,12 +318,13 @@ do { \ #define __put_user(x, ptr) \ ({ \ __typeof__(*(ptr)) __user *__gu_ptr = (ptr); \ + __typeof__(*__gu_ptr) __val = (x); \ long __pu_err = 0; \ \ __chk_user_ptr(__gu_ptr); \ \ __enable_user_access(); \ - __put_user_nocheck(x, __gu_ptr, __pu_err); \ + __put_user_nocheck(__val, __gu_ptr, __pu_err); \ __disable_user_access(); \ \ __pu_err; \ From ac8d0b901f0033b783156ab2dc1a0e73ec42409b Mon Sep 17 00:00:00 2001 From: Zihao Yu Date: Wed, 17 Mar 2021 16:17:25 +0800 Subject: [PATCH 0651/1091] riscv,entry: fix misaligned base for excp_vect_table In RV64, the size of each entry in excp_vect_table is 8 bytes. If the base of the table is not 8-byte aligned, loading an entry in the table will raise a misaligned exception. Although such exception will be handled by opensbi/bbl, this still causes performance degradation. Signed-off-by: Zihao Yu Reviewed-by: Anup Patel Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/entry.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index 744f3209c48d..76274a4a1d8e 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -447,6 +447,7 @@ ENDPROC(__switch_to) #endif .section ".rodata" + .align LGREG /* Exception vector table */ ENTRY(excp_vect_table) RISCV_PTR do_trap_insn_misaligned From 9d8c7d92015ece9a2139a259cef781a41845d2c0 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Mon, 22 Mar 2021 16:38:36 +0800 Subject: [PATCH 0652/1091] riscv: remove unneeded semicolon Eliminate the following coccicheck warning: ./arch/riscv/mm/kasan_init.c:219:2-3: Unneeded semicolon Reported-by: Abaci Robot Signed-off-by: Yang Li Signed-off-by: Palmer Dabbelt --- arch/riscv/mm/kasan_init.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/mm/kasan_init.c b/arch/riscv/mm/kasan_init.c index 4f85c6d0ddf8..937d13ce9ab8 100644 --- a/arch/riscv/mm/kasan_init.c +++ b/arch/riscv/mm/kasan_init.c @@ -216,7 +216,7 @@ void __init kasan_init(void) break; kasan_populate(kasan_mem_to_shadow(start), kasan_mem_to_shadow(end)); - }; + } for (i = 0; i < PTRS_PER_PTE; i++) set_pte(&kasan_early_shadow_pte[i], From 1adbc2941eee8acbe3c7dc6b51cdbc5a9bf19565 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Tue, 30 Mar 2021 21:25:31 +0800 Subject: [PATCH 0653/1091] riscv: Make NUMA depend on MMU NUMA is useless when NOMMU, and it leads some build error, make it depend on MMU. Reported-by: kernel test robot Signed-off-by: Kefeng Wang Signed-off-by: Palmer Dabbelt --- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 87d7b52f278f..0d0cf67359cb 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -314,7 +314,7 @@ endchoice # Common NUMA Features config NUMA bool "NUMA Memory Allocation and Scheduler Support" - depends on SMP + depends on SMP && MMU select GENERIC_ARCH_NUMA select OF_NUMA select ARCH_SUPPORTS_NUMA_BALANCING From 9b5b872215fe6d1ca6a1ef411f130bd58e269012 Mon Sep 17 00:00:00 2001 From: Christian Brauner Date: Fri, 2 Apr 2021 10:29:36 +0200 Subject: [PATCH 0654/1091] file: fix close_range() for unshare+cloexec syzbot reported a bug when putting the last reference to a tasks file descriptor table. Debugging this showed we didn't recalculate the current maximum fd number for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC after we unshared the file descriptors table. So max_fd could exceed the current fdtable maximum causing us to set excessive bits. As a concrete example, let's say the user requested everything from fd 4 to ~0UL to be closed and their current fdtable size is 256 with their highest open fd being 4. With CLOSE_RANGE_UNSHARE the caller will end up with a new fdtable which has room for 64 file descriptors since that is the lowest fdtable size we accept. But now max_fd will still point to 255 and needs to be adjusted. Fix this by retrieving the correct maximum fd value in __range_cloexec(). Reported-by: syzbot+283ce5a46486d6acdbaf@syzkaller.appspotmail.com Fixes: 582f1fb6b721 ("fs, close_range: add flag CLOSE_RANGE_CLOEXEC") Fixes: fec8a6a69103 ("close_range: unshare all fds for CLOSE_RANGE_UNSHARE | CLOSE_RANGE_CLOEXEC") Cc: Christoph Hellwig Cc: Giuseppe Scrivano Cc: Al Viro Cc: linux-fsdevel@vger.kernel.org Cc: stable@vger.kernel.org Signed-off-by: Christian Brauner --- fs/file.c | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) diff --git a/fs/file.c b/fs/file.c index f3a4bac2cbe9..f633348029a5 100644 --- a/fs/file.c +++ b/fs/file.c @@ -629,17 +629,30 @@ int close_fd(unsigned fd) } EXPORT_SYMBOL(close_fd); /* for ksys_close() */ +/** + * last_fd - return last valid index into fd table + * @cur_fds: files struct + * + * Context: Either rcu read lock or files_lock must be held. + * + * Returns: Last valid index into fdtable. + */ +static inline unsigned last_fd(struct fdtable *fdt) +{ + return fdt->max_fds - 1; +} + static inline void __range_cloexec(struct files_struct *cur_fds, unsigned int fd, unsigned int max_fd) { struct fdtable *fdt; - if (fd > max_fd) - return; - + /* make sure we're using the correct maximum value */ spin_lock(&cur_fds->file_lock); fdt = files_fdtable(cur_fds); - bitmap_set(fdt->close_on_exec, fd, max_fd - fd + 1); + max_fd = min(last_fd(fdt), max_fd); + if (fd <= max_fd) + bitmap_set(fdt->close_on_exec, fd, max_fd - fd + 1); spin_unlock(&cur_fds->file_lock); } From f8b78caf21d5bc3fcfc40c18898f9d52ed1451a5 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Fri, 20 Nov 2020 17:10:28 +0000 Subject: [PATCH 0655/1091] block: don't ignore REQ_NOWAIT for direct IO If IOCB_NOWAIT is set on submission, then that needs to get propagated to REQ_NOWAIT on the block side. Otherwise we completely lose this information, and any issuer of IOCB_NOWAIT IO will potentially end up blocking on eg request allocation on the storage side. Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- fs/block_dev.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/block_dev.c b/fs/block_dev.c index 28d583fcdc2c..09d6f7229db9 100644 --- a/fs/block_dev.c +++ b/fs/block_dev.c @@ -275,6 +275,8 @@ __blkdev_direct_IO_simple(struct kiocb *iocb, struct iov_iter *iter, bio.bi_opf = dio_bio_write_op(iocb); task_io_account_write(ret); } + if (iocb->ki_flags & IOCB_NOWAIT) + bio.bi_opf |= REQ_NOWAIT; if (iocb->ki_flags & IOCB_HIPRI) bio_set_polled(&bio, iocb); @@ -428,6 +430,8 @@ static ssize_t __blkdev_direct_IO(struct kiocb *iocb, struct iov_iter *iter, bio->bi_opf = dio_bio_write_op(iocb); task_io_account_write(bio->bi_iter.bi_size); } + if (iocb->ki_flags & IOCB_NOWAIT) + bio->bi_opf |= REQ_NOWAIT; dio->size += bio->bi_iter.bi_size; pos += bio->bi_iter.bi_size; From 9fbd3088351b92e8c2cef6e37a39decb12a8d5bb Mon Sep 17 00:00:00 2001 From: Rob Clark Date: Wed, 24 Mar 2021 18:23:52 -0700 Subject: [PATCH 0656/1091] drm/msm: Fix a5xx/a6xx timestamps They were reading a counter that was configured to ALWAYS_COUNT (ie. cycles that the GPU is doing something) rather than ALWAYS_ON. This isn't the thing that userspace is looking for. Signed-off-by: Rob Clark Acked-by: Jordan Crouse Message-Id: <20210325012358.1759770-2-robdclark@gmail.com> Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a5xx_gpu.c | 4 ++-- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c index 7e553d3efeb2..ce13d49e615b 100644 --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c @@ -1386,8 +1386,8 @@ static int a5xx_pm_suspend(struct msm_gpu *gpu) static int a5xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) { - *value = gpu_read64(gpu, REG_A5XX_RBBM_PERFCTR_CP_0_LO, - REG_A5XX_RBBM_PERFCTR_CP_0_HI); + *value = gpu_read64(gpu, REG_A5XX_RBBM_ALWAYSON_COUNTER_LO, + REG_A5XX_RBBM_ALWAYSON_COUNTER_HI); return 0; } diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index cb2df8736ca8..5b438f3e4bf9 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -1228,8 +1228,8 @@ static int a6xx_get_timestamp(struct msm_gpu *gpu, uint64_t *value) /* Force the GPU power on so we can read this register */ a6xx_gmu_set_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); - *value = gpu_read64(gpu, REG_A6XX_RBBM_PERFCTR_CP_0_LO, - REG_A6XX_RBBM_PERFCTR_CP_0_HI); + *value = gpu_read64(gpu, REG_A6XX_CP_ALWAYS_ON_COUNTER_LO, + REG_A6XX_CP_ALWAYS_ON_COUNTER_HI); a6xx_gmu_clear_oob(&a6xx_gpu->gmu, GMU_OOB_PERFCOUNTER_SET); mutex_unlock(&perfcounter_oob); From 6ddbfa1f5adbd5dea14ff66778ca58257f09f17d Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 31 Mar 2021 17:02:23 +0300 Subject: [PATCH 0657/1091] drm/msm: a6xx: fix version check for the A650 SQE microcode I suppose the microcode version check for a650 is incorrect. It checks for the version 1.95, while the firmware released have major version of 0: 0.91 (vulnerable), 0.99 (fixing the issue). Lower version requirements to accept firmware 0.99. Fixes: 8490f02a3ca4 ("drm/msm: a6xx: Make sure the SQE microcode is safe") Cc: Akhil P Oommen Cc: Jordan Crouse Signed-off-by: Dmitry Baryshkov Acked-by: Jordan Crouse Message-Id: <20210331140223.3771449-1-dmitry.baryshkov@linaro.org> Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/adreno/a6xx_gpu.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c index 5b438f3e4bf9..d553f62f4eeb 100644 --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c @@ -567,17 +567,17 @@ static bool a6xx_ucode_check_version(struct a6xx_gpu *a6xx_gpu, } else { /* * a650 tier targets don't need whereami but still need to be - * equal to or newer than 1.95 for other security fixes + * equal to or newer than 0.95 for other security fixes */ if (adreno_is_a650(adreno_gpu)) { - if ((buf[0] & 0xfff) >= 0x195) { + if ((buf[0] & 0xfff) >= 0x095) { ret = true; goto out; } DRM_DEV_ERROR(&gpu->pdev->dev, "a650 SQE ucode is too old. Have version %x need at least %x\n", - buf[0] & 0xfff, 0x195); + buf[0] & 0xfff, 0x095); } /* From ebbb165d2c0c44ffbf480e209f745ed4b0d5560a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Apr 2021 16:07:42 +0200 Subject: [PATCH 0658/1091] ASoC: Intel: Unify the thinkpad10 and aegex10 byt-match quirks There is no reason to have separate quirk-handlers / byt_machine_id-s for these. These are both cases of BYT devices with a 10EC5640 ACPI HID while using a rt5672 codec. The Dell Venue 10 Pro 5055 is another example of such a device, instead of adding a third byt_machine_id definition for this Dell model, make change the 2 existing cases into a generic BYT_RT5672 byt_machine_id in preparation for adding a quirk for the Dell Venue 10 Pro 5055. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210402140747.174716-2-hdegoede@redhat.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-byt-match.c | 32 +++++++------------ 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index d1febbb53b70..4596d128fff5 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c @@ -11,13 +11,12 @@ static unsigned long byt_machine_id; -#define BYT_THINKPAD_10 1 +#define BYT_RT5672 1 #define BYT_POV_P1006W 2 -#define BYT_AEGEX_10 3 -static int byt_thinkpad10_quirk_cb(const struct dmi_system_id *id) +static int byt_rt5672_quirk_cb(const struct dmi_system_id *id) { - byt_machine_id = BYT_THINKPAD_10; + byt_machine_id = BYT_RT5672; return 1; } @@ -27,36 +26,30 @@ static int byt_pov_p1006w_quirk_cb(const struct dmi_system_id *id) return 1; } -static int byt_aegex10_quirk_cb(const struct dmi_system_id *id) -{ - byt_machine_id = BYT_AEGEX_10; - return 1; -} - static const struct dmi_system_id byt_table[] = { { - .callback = byt_thinkpad10_quirk_cb, + .callback = byt_rt5672_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 8"), }, }, { - .callback = byt_thinkpad10_quirk_cb, + .callback = byt_rt5672_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad 10"), }, }, { - .callback = byt_thinkpad10_quirk_cb, + .callback = byt_rt5672_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "ThinkPad Tablet B"), }, }, { - .callback = byt_thinkpad10_quirk_cb, + .callback = byt_rt5672_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Miix 2 10"), @@ -75,7 +68,7 @@ static const struct dmi_system_id byt_table[] = { }, { /* Aegex 10 tablet (RU2) */ - .callback = byt_aegex10_quirk_cb, + .callback = byt_rt5672_quirk_cb, .matches = { DMI_MATCH(DMI_SYS_VENDOR, "AEGEX"), DMI_MATCH(DMI_PRODUCT_VERSION, "RU2"), @@ -84,8 +77,8 @@ static const struct dmi_system_id byt_table[] = { { } }; -/* The Thinkapd 10 and Aegex 10 tablets have the same ID problem */ -static struct snd_soc_acpi_mach byt_thinkpad_10 = { +/* Various devices use an ACPI id of 10EC5640 while using a rt5672 codec */ +static struct snd_soc_acpi_mach byt_rt5672 = { .id = "10EC5640", .drv_name = "cht-bsw-rt5672", .fw_filename = "intel/fw_sst_0f28.bin", @@ -110,9 +103,8 @@ static struct snd_soc_acpi_mach *byt_quirk(void *arg) dmi_check_system(byt_table); switch (byt_machine_id) { - case BYT_THINKPAD_10: - case BYT_AEGEX_10: - return &byt_thinkpad_10; + case BYT_RT5672: + return &byt_rt5672; case BYT_POV_P1006W: return &byt_pov_p1006w; default: From 17d49b07a8bb3fdc630a44240c7d7e2a18e14b93 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Apr 2021 16:07:43 +0200 Subject: [PATCH 0659/1091] ASoC: Intel: Baytrail: Add quirk for the Dell Venue 10 Pro 5055 tablet The Dell Venue 10 Pro 5055 tablet uses an ACPI HID of 10EC5640 while using a rt5672 codec (instead of a rt5640 codec). Add a quirk for this. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210402140747.174716-3-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/common/soc-acpi-intel-byt-match.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-byt-match.c b/sound/soc/intel/common/soc-acpi-intel-byt-match.c index 4596d128fff5..510a5f38b7f1 100644 --- a/sound/soc/intel/common/soc-acpi-intel-byt-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-byt-match.c @@ -74,6 +74,14 @@ static const struct dmi_system_id byt_table[] = { DMI_MATCH(DMI_PRODUCT_VERSION, "RU2"), }, }, + { + /* Dell Venue 10 Pro 5055 */ + .callback = byt_rt5672_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"), + }, + }, { } }; From c9b3c63392e578ea74411b29a720ace77ae9041f Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Apr 2021 16:07:44 +0200 Subject: [PATCH 0660/1091] ASoC: Intel: cht_bsw_rt5672: Add support for Bay Trail CR / SSP0 The rt5672 codec is used on some Bay Trail CR boards, on these SoCs SSP2 is not available and SSP0 should be used instead. At support for this. This has been tested on a Dell Venue 10 Pro 5055. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210402140747.174716-4-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_rt5672.c | 75 ++++++++++++++++++++----- 1 file changed, 61 insertions(+), 14 deletions(-) diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 10c88ef2f85d..10d5ed20e4e8 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -21,6 +21,7 @@ #include #include "../../codecs/rt5670.h" #include "../atom/sst-atom-controls.h" +#include "../common/soc-intel-quirks.h" /* The platform clock #3 outputs 19.2Mhz clock to codec as I2S MCLK */ @@ -31,6 +32,7 @@ struct cht_mc_private { struct snd_soc_jack headset; char codec_name[SND_ACPI_I2C_ID_LEN]; struct clk *mclk; + bool use_ssp0; }; /* Headset jack detection DAPM pins */ @@ -121,16 +123,26 @@ static const struct snd_soc_dapm_route cht_audio_map[] = { {"Ext Spk", NULL, "SPOLN"}, {"Ext Spk", NULL, "SPORP"}, {"Ext Spk", NULL, "SPORN"}, + {"Headphone", NULL, "Platform Clock"}, + {"Headset Mic", NULL, "Platform Clock"}, + {"Int Mic", NULL, "Platform Clock"}, + {"Ext Spk", NULL, "Platform Clock"}, +}; + +static const struct snd_soc_dapm_route cht_audio_ssp0_map[] = { + {"AIF1 Playback", NULL, "ssp0 Tx"}, + {"ssp0 Tx", NULL, "modem_out"}, + {"modem_in", NULL, "ssp0 Rx"}, + {"ssp0 Rx", NULL, "AIF1 Capture"}, +}; + +static const struct snd_soc_dapm_route cht_audio_ssp2_map[] = { {"AIF1 Playback", NULL, "ssp2 Tx"}, {"ssp2 Tx", NULL, "codec_out0"}, {"ssp2 Tx", NULL, "codec_out1"}, {"codec_in0", NULL, "ssp2 Rx"}, {"codec_in1", NULL, "ssp2 Rx"}, {"ssp2 Rx", NULL, "AIF1 Capture"}, - {"Headphone", NULL, "Platform Clock"}, - {"Headset Mic", NULL, "Platform Clock"}, - {"Int Mic", NULL, "Platform Clock"}, - {"Ext Spk", NULL, "Platform Clock"}, }; static const struct snd_kcontrol_new cht_mc_controls[] = { @@ -197,6 +209,18 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) | RT5670_AD_MONO_R_FILTER, RT5670_CLK_SEL_I2S1_ASRC); + if (ctx->use_ssp0) { + ret = snd_soc_dapm_add_routes(&runtime->card->dapm, + cht_audio_ssp0_map, + ARRAY_SIZE(cht_audio_ssp0_map)); + } else { + ret = snd_soc_dapm_add_routes(&runtime->card->dapm, + cht_audio_ssp2_map, + ARRAY_SIZE(cht_audio_ssp2_map)); + } + if (ret) + return ret; + ret = snd_soc_card_jack_new(runtime->card, "Headset", SND_JACK_HEADSET | SND_JACK_BTN_0 | SND_JACK_BTN_1 | SND_JACK_BTN_2, @@ -239,18 +263,26 @@ static int cht_codec_init(struct snd_soc_pcm_runtime *runtime) static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params) { + struct cht_mc_private *ctx = snd_soc_card_get_drvdata(rtd->card); struct snd_interval *rate = hw_param_interval(params, SNDRV_PCM_HW_PARAM_RATE); struct snd_interval *channels = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); - int ret; + int ret, bits; /* The DSP will covert the FE rate to 48k, stereo, 24bits */ rate->min = rate->max = 48000; channels->min = channels->max = 2; - /* set SSP2 to 24-bit */ - params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + if (ctx->use_ssp0) { + /* set SSP0 to 16-bit */ + params_set_format(params, SNDRV_PCM_FORMAT_S16_LE); + bits = 16; + } else { + /* set SSP2 to 24-bit */ + params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); + bits = 24; + } /* * The default mode for the cpu-dai is TDM 4 slot. The default mode @@ -274,6 +306,12 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, return ret; } + ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_cpu(rtd, 0), 0x3, 0x3, 2, bits); + if (ret < 0) { + dev_err(rtd->dev, "can't set I2S config, err %d\n", ret); + return ret; + } + return 0; } @@ -414,6 +452,7 @@ static int snd_cht_mc_probe(struct platform_device *pdev) const char *platform_name; struct acpi_device *adev; bool sof_parent; + int dai_index = 0; int i; drv = devm_kzalloc(&pdev->dev, sizeof(*drv), GFP_KERNEL); @@ -422,19 +461,27 @@ static int snd_cht_mc_probe(struct platform_device *pdev) strcpy(drv->codec_name, RT5672_I2C_DEFAULT); + /* find index of codec dai */ + for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { + if (!strcmp(cht_dailink[i].codecs->name, RT5672_I2C_DEFAULT)) { + dai_index = i; + break; + } + } + /* fixup codec name based on HID */ adev = acpi_dev_get_first_match_dev(mach->id, NULL, -1); if (adev) { snprintf(drv->codec_name, sizeof(drv->codec_name), "i2c-%s", acpi_dev_name(adev)); put_device(&adev->dev); - for (i = 0; i < ARRAY_SIZE(cht_dailink); i++) { - if (!strcmp(cht_dailink[i].codecs->name, - RT5672_I2C_DEFAULT)) { - cht_dailink[i].codecs->name = drv->codec_name; - break; - } - } + cht_dailink[dai_index].codecs->name = drv->codec_name; + } + + /* Use SSP0 on Bay Trail CR devices */ + if (soc_intel_is_byt() && mach->mach_params.acpi_ipc_irq_index == 0) { + cht_dailink[dai_index].cpus->dai_name = "ssp0-port"; + drv->use_ssp0 = true; } /* override plaform name, if required */ From 84cb0d5581b6a7bd5d96013f67e9f2eb0c7b4378 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Apr 2021 16:07:45 +0200 Subject: [PATCH 0661/1091] ASoC: rt5670: Add a quirk for the Dell Venue 10 Pro 5055 Add a quirk with the jack-detect and dmic settings necessary to make jack-detect and the builtin mic work on Dell Venue 10 Pro 5055 tablets. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210402140747.174716-5-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 8dcda24f3ceb..810d0e72eac7 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -2980,6 +2980,18 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { RT5670_GPIO1_IS_IRQ | RT5670_JD_MODE3), }, + { + .callback = rt5670_quirk_cb, + .ident = "Dell Venue 10 Pro 5055", + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), + DMI_MATCH(DMI_PRODUCT_NAME, "Venue 10 Pro 5055"), + }, + .driver_data = (unsigned long *)(RT5670_DMIC_EN | + RT5670_DMIC2_INR | + RT5670_GPIO1_IS_IRQ | + RT5670_JD_MODE1), + }, { .callback = rt5670_quirk_cb, .ident = "Aegex 10 tablet (RU2)", From 3d534537648bd7d7a82f2becc9ded99a4b228a6a Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Apr 2021 16:07:46 +0200 Subject: [PATCH 0662/1091] ASoC: rt5670: Add a rt5670_components() helper The rt5670 codec driver uses DMI quirks to configure the DMIC data-pins, which means that it knows which DMIC interface is used on a specific device. ATM we duplicate this DMI matching inside the UCM profiles to select the right DMIC interface. Add a rt5670_components() helper which the machine-driver can use to set the components string of the card so that UCM can get the info from the components string. This way we only need to add new DMI quirks in one place. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210402140747.174716-6-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5670.c | 39 +++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/rt5670.h | 2 ++ 2 files changed, 41 insertions(+) diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 810d0e72eac7..ecbaf129a6e3 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -3007,6 +3007,45 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { {} }; +const char *rt5670_components(void) +{ + unsigned long quirk; + bool dmic1 = false; + bool dmic2 = false; + bool dmic3 = false; + + if (quirk_override) { + quirk = quirk_override; + } else { + dmi_check_system(dmi_platform_intel_quirks); + quirk = rt5670_quirk; + } + + if ((quirk & RT5670_DMIC1_IN2P) || + (quirk & RT5670_DMIC1_GPIO6) || + (quirk & RT5670_DMIC1_GPIO7)) + dmic1 = true; + + if ((quirk & RT5670_DMIC2_INR) || + (quirk & RT5670_DMIC2_GPIO8)) + dmic2 = true; + + if (quirk & RT5670_DMIC3_GPIO5) + dmic3 = true; + + if (dmic1 && dmic2) + return "cfg-spk:2 cfg-mic:dmics12"; + else if (dmic1) + return "cfg-spk:2 cfg-mic:dmic1"; + else if (dmic2) + return "cfg-spk:2 cfg-mic:dmic2"; + else if (dmic3) + return "cfg-spk:2 cfg-mic:dmic3"; + + return NULL; +} +EXPORT_SYMBOL_GPL(rt5670_components); + static int rt5670_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index 6fb3c369ee98..5b230897f630 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h @@ -2024,4 +2024,6 @@ void rt5670_jack_suspend(struct snd_soc_component *component); void rt5670_jack_resume(struct snd_soc_component *component); int rt5670_set_jack_detect(struct snd_soc_component *component, struct snd_soc_jack *jack); +const char *rt5670_components(void); + #endif /* __RT5670_H__ */ From e992a51b1d14317f414d4b9935966dca96ac0b36 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 2 Apr 2021 16:07:47 +0200 Subject: [PATCH 0663/1091] ASoC: Intel: cht_bsw_rt5672: Set card.components string Set the card.components string using the new rt5670_components() helper which returns a components string based on the DMI quirks inside the rt5670 codec driver. Signed-off-by: Hans de Goede Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210402140747.174716-7-hdegoede@redhat.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/cht_bsw_rt5672.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 10d5ed20e4e8..e358632f50d7 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -493,6 +493,8 @@ static int snd_cht_mc_probe(struct platform_device *pdev) if (ret_val) return ret_val; + snd_soc_card_cht.components = rt5670_components(); + drv->mclk = devm_clk_get(&pdev->dev, "pmc_plt_clk_3"); if (IS_ERR(drv->mclk)) { dev_err(&pdev->dev, From 12aca1ce9ee33af3751aec5e55a5900747cbdd4b Mon Sep 17 00:00:00 2001 From: Kalyan Thota Date: Fri, 2 Apr 2021 04:54:53 -0700 Subject: [PATCH 0664/1091] drm/msm/disp/dpu1: program 3d_merge only if block is attached Update the 3d merge as active in the data path only if the hw block is selected in the configuration. Reported-by: Stephen Boyd Fixes: 73bfb790ac78 ("msm:disp:dpu1: setup display datapath for SC7180 target") Signed-off-by: Kalyan Thota Message-Id: <1617364493-13518-1-git-send-email-kalyan_t@codeaurora.org> Signed-off-by: Rob Clark --- drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c index 8981cfa9dbc3..92e6f1b94738 100644 --- a/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c +++ b/drivers/gpu/drm/msm/disp/dpu1/dpu_hw_ctl.c @@ -496,7 +496,9 @@ static void dpu_hw_ctl_intf_cfg_v1(struct dpu_hw_ctl *ctx, DPU_REG_WRITE(c, CTL_TOP, mode_sel); DPU_REG_WRITE(c, CTL_INTF_ACTIVE, intf_active); - DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, BIT(cfg->merge_3d - MERGE_3D_0)); + if (cfg->merge_3d) + DPU_REG_WRITE(c, CTL_MERGE_3D_ACTIVE, + BIT(cfg->merge_3d - MERGE_3D_0)); } static void dpu_hw_ctl_intf_cfg(struct dpu_hw_ctl *ctx, From 230d50d448acb6639991440913299e50cacf1daf Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Thu, 1 Apr 2021 20:41:15 -0600 Subject: [PATCH 0665/1091] io_uring: move reissue into regular IO path It's non-obvious how retry is done for block backed files, when it happens off the kiocb done path. It also makes it tricky to deal with the iov_iter handling. Just mark the req as needing a reissue, and handling it from the submission path instead. This makes it directly obvious that we're not re-importing the iovec from userspace past the submit point, and it means that we can just reuse our usual -EAGAIN retry path from the read/write handling. At some point in the future, we'll gain the ability to always reliably return -EAGAIN through the stack. A previous attempt on the block side didn't pan out and got reverted, hence the need to check for this information out-of-band right now. Signed-off-by: Jens Axboe --- fs/io_uring.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 717942474fa9..8be542050648 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -697,6 +697,7 @@ enum { REQ_F_NO_FILE_TABLE_BIT, REQ_F_LTIMEOUT_ACTIVE_BIT, REQ_F_COMPLETE_INLINE_BIT, + REQ_F_REISSUE_BIT, /* not a real bit, just to check we're not overflowing the space */ __REQ_F_LAST_BIT, @@ -740,6 +741,8 @@ enum { REQ_F_LTIMEOUT_ACTIVE = BIT(REQ_F_LTIMEOUT_ACTIVE_BIT), /* completion is deferred through io_comp_state */ REQ_F_COMPLETE_INLINE = BIT(REQ_F_COMPLETE_INLINE_BIT), + /* caller should reissue async */ + REQ_F_REISSUE = BIT(REQ_F_REISSUE_BIT), }; struct async_poll { @@ -2503,8 +2506,10 @@ static void __io_complete_rw(struct io_kiocb *req, long res, long res2, if (req->rw.kiocb.ki_flags & IOCB_WRITE) kiocb_end_write(req); - if ((res == -EAGAIN || res == -EOPNOTSUPP) && io_rw_reissue(req)) + if ((res == -EAGAIN || res == -EOPNOTSUPP) && io_rw_should_reissue(req)) { + req->flags |= REQ_F_REISSUE; return; + } if (res != req->result) req_set_fail_links(req); if (req->flags & REQ_F_BUFFER_SELECTED) @@ -3283,9 +3288,7 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) ret = io_iter_do_read(req, iter); - if (ret == -EIOCBQUEUED) { - goto out_free; - } else if (ret == -EAGAIN) { + if (ret == -EAGAIN || (req->flags & REQ_F_REISSUE)) { /* IOPOLL retry should happen for io-wq threads */ if (!force_nonblock && !(req->ctx->flags & IORING_SETUP_IOPOLL)) goto done; @@ -3295,6 +3298,8 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) /* some cases will consume bytes even on error returns */ iov_iter_revert(iter, io_size - iov_iter_count(iter)); ret = 0; + } else if (ret == -EIOCBQUEUED) { + goto out_free; } else if (ret <= 0 || ret == io_size || !force_nonblock || (req->flags & REQ_F_NOWAIT) || !(req->flags & REQ_F_ISREG)) { /* read all, failed, already did sync or don't want to retry */ @@ -3407,6 +3412,9 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) else ret2 = -EINVAL; + if (req->flags & REQ_F_REISSUE) + ret2 = -EAGAIN; + /* * Raw bdev writes will return -EOPNOTSUPP for IOCB_NOWAIT. Just * retry them without IOCB_NOWAIT. @@ -6160,6 +6168,7 @@ static void io_wq_submit_work(struct io_wq_work *work) ret = -ECANCELED; if (!ret) { + req->flags &= ~REQ_F_REISSUE; do { ret = io_issue_sqe(req, 0); /* From 442dc00f82a9727dc0c48c44f792c168f593c6df Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Fri, 2 Apr 2021 10:56:18 +0200 Subject: [PATCH 0666/1091] selinux: make nslot handling in avtab more robust 1. Make sure all fileds are initialized in avtab_init(). 2. Slightly refactor avtab_alloc() to use the above fact. 3. Use h->nslot == 0 as a sentinel in the access functions to prevent dereferencing h->htable when it's not allocated. Cc: stable@vger.kernel.org Signed-off-by: Ondrej Mosnacek Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 6dcb6aa4db7f..2aee4c965c25 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -109,7 +109,7 @@ static int avtab_insert(struct avtab *h, struct avtab_key *key, struct avtab_dat struct avtab_node *prev, *cur, *newnode; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h) + if (!h || !h->nslot) return -EINVAL; hvalue = avtab_hash(key, h->mask); @@ -154,7 +154,7 @@ avtab_insert_nonunique(struct avtab *h, struct avtab_key *key, struct avtab_datu struct avtab_node *prev, *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h) + if (!h || !h->nslot) return NULL; hvalue = avtab_hash(key, h->mask); for (prev = NULL, cur = h->htable[hvalue]; @@ -184,7 +184,7 @@ struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *key) struct avtab_node *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h) + if (!h || !h->nslot) return NULL; hvalue = avtab_hash(key, h->mask); @@ -220,7 +220,7 @@ avtab_search_node(struct avtab *h, struct avtab_key *key) struct avtab_node *cur; u16 specified = key->specified & ~(AVTAB_ENABLED|AVTAB_ENABLED_OLD); - if (!h) + if (!h || !h->nslot) return NULL; hvalue = avtab_hash(key, h->mask); @@ -295,6 +295,7 @@ void avtab_destroy(struct avtab *h) } kvfree(h->htable); h->htable = NULL; + h->nel = 0; h->nslot = 0; h->mask = 0; } @@ -303,14 +304,15 @@ void avtab_init(struct avtab *h) { h->htable = NULL; h->nel = 0; + h->nslot = 0; + h->mask = 0; } int avtab_alloc(struct avtab *h, u32 nrules) { - u32 mask = 0; u32 shift = 0; u32 work = nrules; - u32 nslot = 0; + u32 nslot; if (nrules == 0) goto avtab_alloc_out; @@ -324,16 +326,15 @@ int avtab_alloc(struct avtab *h, u32 nrules) nslot = 1 << shift; if (nslot > MAX_AVTAB_HASH_BUCKETS) nslot = MAX_AVTAB_HASH_BUCKETS; - mask = nslot - 1; h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL); if (!h->htable) return -ENOMEM; - avtab_alloc_out: - h->nel = 0; h->nslot = nslot; - h->mask = mask; + h->mask = nslot - 1; + +avtab_alloc_out: pr_debug("SELinux: %d avtab hash slots, %d rules.\n", h->nslot, nrules); return 0; From d8f5f0ea5b86300390b026b6c6e7836b7150814a Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Fri, 2 Apr 2021 10:56:19 +0200 Subject: [PATCH 0667/1091] selinux: fix cond_list corruption when changing booleans Currently, duplicate_policydb_cond_list() first copies the whole conditional avtab and then tries to link to the correct entries in cond_dup_av_list() using avtab_search(). However, since the conditional avtab may contain multiple entries with the same key, this approach often fails to find the right entry, potentially leading to wrong rules being activated/deactivated when booleans are changed. To fix this, instead start with an empty conditional avtab and add the individual entries one-by-one while building the new av_lists. This approach leads to the correct result, since each entry is present in the av_lists exactly once. The issue can be reproduced with Fedora policy as follows: # sesearch -s ftpd_t -t public_content_rw_t -c dir -p create -A allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True allow ftpd_t public_content_rw_t:dir { add_name create link remove_name rename reparent rmdir setattr unlink watch watch_reads write }; [ ftpd_anon_write ]:True # setsebool ftpd_anon_write=off ftpd_connect_all_unreserved=off ftpd_connect_db=off ftpd_full_access=off On fixed kernels, the sesearch output is the same after the setsebool command: # sesearch -s ftpd_t -t public_content_rw_t -c dir -p create -A allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True allow ftpd_t public_content_rw_t:dir { add_name create link remove_name rename reparent rmdir setattr unlink watch watch_reads write }; [ ftpd_anon_write ]:True While on the broken kernels, it will be different: # sesearch -s ftpd_t -t public_content_rw_t -c dir -p create -A allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True allow ftpd_t non_security_file_type:dir { add_name create getattr ioctl link lock open read remove_name rename reparent rmdir search setattr unlink watch watch_reads write }; [ ftpd_full_access ]:True While there, also simplify the computation of nslots. This changes the nslots values for nrules 2 or 3 to just two slots instead of 4, which makes the sequence more consistent. Cc: stable@vger.kernel.org Fixes: c7c556f1e81b ("selinux: refactor changing booleans") Signed-off-by: Ondrej Mosnacek Signed-off-by: Paul Moore --- security/selinux/ss/avtab.c | 86 +++++++++---------------------- security/selinux/ss/avtab.h | 2 +- security/selinux/ss/conditional.c | 12 ++--- 3 files changed, 32 insertions(+), 68 deletions(-) diff --git a/security/selinux/ss/avtab.c b/security/selinux/ss/avtab.c index 2aee4c965c25..75df32906055 100644 --- a/security/selinux/ss/avtab.c +++ b/security/selinux/ss/avtab.c @@ -308,24 +308,10 @@ void avtab_init(struct avtab *h) h->mask = 0; } -int avtab_alloc(struct avtab *h, u32 nrules) +static int avtab_alloc_common(struct avtab *h, u32 nslot) { - u32 shift = 0; - u32 work = nrules; - u32 nslot; - - if (nrules == 0) - goto avtab_alloc_out; - - while (work) { - work = work >> 1; - shift++; - } - if (shift > 2) - shift = shift - 2; - nslot = 1 << shift; - if (nslot > MAX_AVTAB_HASH_BUCKETS) - nslot = MAX_AVTAB_HASH_BUCKETS; + if (!nslot) + return 0; h->htable = kvcalloc(nslot, sizeof(void *), GFP_KERNEL); if (!h->htable) @@ -333,59 +319,37 @@ int avtab_alloc(struct avtab *h, u32 nrules) h->nslot = nslot; h->mask = nslot - 1; - -avtab_alloc_out: - pr_debug("SELinux: %d avtab hash slots, %d rules.\n", - h->nslot, nrules); return 0; } -int avtab_duplicate(struct avtab *new, struct avtab *orig) +int avtab_alloc(struct avtab *h, u32 nrules) { - int i; - struct avtab_node *node, *tmp, *tail; + int rc; + u32 nslot = 0; - memset(new, 0, sizeof(*new)); - - new->htable = kvcalloc(orig->nslot, sizeof(void *), GFP_KERNEL); - if (!new->htable) - return -ENOMEM; - new->nslot = orig->nslot; - new->mask = orig->mask; - - for (i = 0; i < orig->nslot; i++) { - tail = NULL; - for (node = orig->htable[i]; node; node = node->next) { - tmp = kmem_cache_zalloc(avtab_node_cachep, GFP_KERNEL); - if (!tmp) - goto error; - tmp->key = node->key; - if (tmp->key.specified & AVTAB_XPERMS) { - tmp->datum.u.xperms = - kmem_cache_zalloc(avtab_xperms_cachep, - GFP_KERNEL); - if (!tmp->datum.u.xperms) { - kmem_cache_free(avtab_node_cachep, tmp); - goto error; - } - tmp->datum.u.xperms = node->datum.u.xperms; - } else - tmp->datum.u.data = node->datum.u.data; - - if (tail) - tail->next = tmp; - else - new->htable[i] = tmp; - - tail = tmp; - new->nel++; + if (nrules != 0) { + u32 shift = 1; + u32 work = nrules >> 3; + while (work) { + work >>= 1; + shift++; } + nslot = 1 << shift; + if (nslot > MAX_AVTAB_HASH_BUCKETS) + nslot = MAX_AVTAB_HASH_BUCKETS; + + rc = avtab_alloc_common(h, nslot); + if (rc) + return rc; } + pr_debug("SELinux: %d avtab hash slots, %d rules.\n", nslot, nrules); return 0; -error: - avtab_destroy(new); - return -ENOMEM; +} + +int avtab_alloc_dup(struct avtab *new, const struct avtab *orig) +{ + return avtab_alloc_common(new, orig->nslot); } void avtab_hash_eval(struct avtab *h, char *tag) diff --git a/security/selinux/ss/avtab.h b/security/selinux/ss/avtab.h index 4c4445ca9118..f2eeb36265d1 100644 --- a/security/selinux/ss/avtab.h +++ b/security/selinux/ss/avtab.h @@ -89,7 +89,7 @@ struct avtab { void avtab_init(struct avtab *h); int avtab_alloc(struct avtab *, u32); -int avtab_duplicate(struct avtab *new, struct avtab *orig); +int avtab_alloc_dup(struct avtab *new, const struct avtab *orig); struct avtab_datum *avtab_search(struct avtab *h, struct avtab_key *k); void avtab_destroy(struct avtab *h); void avtab_hash_eval(struct avtab *h, char *tag); diff --git a/security/selinux/ss/conditional.c b/security/selinux/ss/conditional.c index 0b32f3ab025e..1ef74c085f2b 100644 --- a/security/selinux/ss/conditional.c +++ b/security/selinux/ss/conditional.c @@ -605,7 +605,6 @@ static int cond_dup_av_list(struct cond_av_list *new, struct cond_av_list *orig, struct avtab *avtab) { - struct avtab_node *avnode; u32 i; memset(new, 0, sizeof(*new)); @@ -615,10 +614,11 @@ static int cond_dup_av_list(struct cond_av_list *new, return -ENOMEM; for (i = 0; i < orig->len; i++) { - avnode = avtab_search_node(avtab, &orig->nodes[i]->key); - if (WARN_ON(!avnode)) - return -EINVAL; - new->nodes[i] = avnode; + new->nodes[i] = avtab_insert_nonunique(avtab, + &orig->nodes[i]->key, + &orig->nodes[i]->datum); + if (!new->nodes[i]) + return -ENOMEM; new->len++; } @@ -630,7 +630,7 @@ static int duplicate_policydb_cond_list(struct policydb *newp, { int rc, i, j; - rc = avtab_duplicate(&newp->te_cond_avtab, &origp->te_cond_avtab); + rc = avtab_alloc_dup(&newp->te_cond_avtab, &origp->te_cond_avtab); if (rc) return rc; From b9c6cdc37ee1fe5866d3b1c10efb9d03191a76af Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 2 Apr 2021 19:17:31 +0200 Subject: [PATCH 0668/1091] block: update a few comments in uapi/linux/blkpg.h The big top of the file comment talk about grand plans that never happened, so remove them to not confuse the readers. Also mark the devname and volname fields as ignored as they were never used by the kernel. Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- include/uapi/linux/blkpg.h | 28 ++-------------------------- 1 file changed, 2 insertions(+), 26 deletions(-) diff --git a/include/uapi/linux/blkpg.h b/include/uapi/linux/blkpg.h index ac6474e4f29d..d0a64ee97c6d 100644 --- a/include/uapi/linux/blkpg.h +++ b/include/uapi/linux/blkpg.h @@ -2,29 +2,6 @@ #ifndef _UAPI__LINUX_BLKPG_H #define _UAPI__LINUX_BLKPG_H -/* - * Partition table and disk geometry handling - * - * A single ioctl with lots of subfunctions: - * - * Device number stuff: - * get_whole_disk() (given the device number of a partition, - * find the device number of the encompassing disk) - * get_all_partitions() (given the device number of a disk, return the - * device numbers of all its known partitions) - * - * Partition stuff: - * add_partition() - * delete_partition() - * test_partition_in_use() (also for test_disk_in_use) - * - * Geometry stuff: - * get_geometry() - * set_geometry() - * get_bios_drivedata() - * - * For today, only the partition stuff - aeb, 990515 - */ #include #include @@ -52,9 +29,8 @@ struct blkpg_partition { long long start; /* starting offset in bytes */ long long length; /* length in bytes */ int pno; /* partition number */ - char devname[BLKPG_DEVNAMELTH]; /* partition name, like sda5 or c0d1p2, - to be used in kernel messages */ - char volname[BLKPG_VOLNAMELTH]; /* volume label */ + char devname[BLKPG_DEVNAMELTH]; /* unused / ignored */ + char volname[BLKPG_VOLNAMELTH]; /* unused / ignore */ }; #endif /* _UAPI__LINUX_BLKPG_H */ From f06c609645ecd043c79380fac94145926603fb33 Mon Sep 17 00:00:00 2001 From: Christoph Hellwig Date: Fri, 2 Apr 2021 19:17:46 +0200 Subject: [PATCH 0669/1091] block: remove the unused RQF_ALLOCED flag Signed-off-by: Christoph Hellwig Signed-off-by: Jens Axboe --- block/blk-mq-debugfs.c | 1 - include/linux/blkdev.h | 2 -- 2 files changed, 3 deletions(-) diff --git a/block/blk-mq-debugfs.c b/block/blk-mq-debugfs.c index 9ebb344e2585..271f6596435b 100644 --- a/block/blk-mq-debugfs.c +++ b/block/blk-mq-debugfs.c @@ -302,7 +302,6 @@ static const char *const rqf_name[] = { RQF_NAME(QUIET), RQF_NAME(ELVPRIV), RQF_NAME(IO_STAT), - RQF_NAME(ALLOCED), RQF_NAME(PM), RQF_NAME(HASHED), RQF_NAME(STATS), diff --git a/include/linux/blkdev.h b/include/linux/blkdev.h index bc6bc8383b43..158aefae1030 100644 --- a/include/linux/blkdev.h +++ b/include/linux/blkdev.h @@ -85,8 +85,6 @@ typedef __u32 __bitwise req_flags_t; #define RQF_ELVPRIV ((__force req_flags_t)(1 << 12)) /* account into disk and partition IO statistics */ #define RQF_IO_STAT ((__force req_flags_t)(1 << 13)) -/* request came from our alloc pool */ -#define RQF_ALLOCED ((__force req_flags_t)(1 << 14)) /* runtime pm request */ #define RQF_PM ((__force req_flags_t)(1 << 15)) /* on IO scheduler merge hash */ From 967ff33eb0efcd48e4df11ab9aee51c41e0f44d0 Mon Sep 17 00:00:00 2001 From: Gregory CLEMENT Date: Fri, 2 Apr 2021 21:58:26 +0200 Subject: [PATCH 0670/1091] Revert "arm64: dts: marvell: armada-cp110: Switch to per-port SATA interrupts" The driver part of this support was not merged which leads to break AHCI on all Marvell Armada 7k8k / CN913x platforms as it was reported by Marcin Wojtas. So for now let's remove it in order to fix the issue waiting for the driver part really be merged. This reverts commit 53e950d597e3578da84238b86424bfcc9e101d87. Fixes: 53e950d597e3 ("arm64: dts: marvell: armada-cp110: Switch to per-port SATA interrupts") Signed-off-by: Gregory CLEMENT --- arch/arm64/boot/dts/marvell/armada-cp11x.dtsi | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi index 64179a372ecf..c6f5df2deccf 100644 --- a/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi +++ b/arch/arm64/boot/dts/marvell/armada-cp11x.dtsi @@ -310,9 +310,11 @@ }; CP11X_LABEL(sata0): sata@540000 { - compatible = "marvell,armada-8k-ahci"; + compatible = "marvell,armada-8k-ahci", + "generic-ahci"; reg = <0x540000 0x30000>; dma-coherent; + interrupts = <107 IRQ_TYPE_LEVEL_HIGH>; clocks = <&CP11X_LABEL(clk) 1 15>, <&CP11X_LABEL(clk) 1 16>; #address-cells = <1>; @@ -320,12 +322,10 @@ status = "disabled"; sata-port@0 { - interrupts = <109 IRQ_TYPE_LEVEL_HIGH>; reg = <0>; }; sata-port@1 { - interrupts = <107 IRQ_TYPE_LEVEL_HIGH>; reg = <1>; }; }; From 5b2c7e0ae762fff2b172caf16b2766cc3e1ad859 Mon Sep 17 00:00:00 2001 From: Rui Salvaterra Date: Wed, 17 Feb 2021 15:30:38 +0000 Subject: [PATCH 0671/1091] ARM: dts: turris-omnia: fix hardware buffer management MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Hardware buffer management has never worked on the Turris Omnia, as the required MBus window hadn't been reserved. Fix thusly. Fixes: 018b88eee1a2 ("ARM: dts: turris-omnia: enable HW buffer management") Signed-off-by: Rui Salvaterra Reviewed-by: Marek Behún Tested-by: Klaus Kudielka Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/armada-385-turris-omnia.dts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts index 646a06420c77..dc80a909ea88 100644 --- a/arch/arm/boot/dts/armada-385-turris-omnia.dts +++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts @@ -32,7 +32,8 @@ ranges = ; + MBUS_ID(0x09, 0x15) 0 0xf1110000 0x10000 + MBUS_ID(0x0c, 0x04) 0 0xf1200000 0x100000>; internal-regs { From a26c56ae67fa9fbb45a8a232dcd7ebaa7af16086 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Sun, 21 Feb 2021 00:11:44 +0100 Subject: [PATCH 0672/1091] ARM: dts: turris-omnia: configure LED[2]/INTn pin as interrupt pin MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the `marvell,reg-init` DT property to configure the LED[2]/INTn pin of the Marvell 88E1514 ethernet PHY on Turris Omnia into interrupt mode. Without this the pin is by default in LED[2] mode, and the Marvell PHY driver configures LED[2] into "On - Link, Blink - Activity" mode. This fixes the issue where the pca9538 GPIO/interrupt controller (which can't mask interrupts in HW) received too many interrupts and after a time started ignoring the interrupt with error message: IRQ 71: nobody cared There is a work in progress to have the Marvell PHY driver support parsing PHY LED nodes from OF and registering the LEDs as Linux LED class devices. Once this is done the PHY driver can also automatically set the pin into INTn mode if it does not find LED[2] in OF. Until then, though, we fix this via `marvell,reg-init` DT property. Signed-off-by: Marek Behún Reported-by: Rui Salvaterra Fixes: 26ca8b52d6e1 ("ARM: dts: add support for Turris Omnia") Cc: Uwe Kleine-König Cc: linux-arm-kernel@lists.infradead.org Cc: Andrew Lunn Cc: Gregory CLEMENT Cc: Tested-by: Rui Salvaterra Reviewed-by: Andrew Lunn Signed-off-by: Gregory CLEMENT --- arch/arm/boot/dts/armada-385-turris-omnia.dts | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/arm/boot/dts/armada-385-turris-omnia.dts b/arch/arm/boot/dts/armada-385-turris-omnia.dts index dc80a909ea88..5bd6a66d2c2b 100644 --- a/arch/arm/boot/dts/armada-385-turris-omnia.dts +++ b/arch/arm/boot/dts/armada-385-turris-omnia.dts @@ -390,6 +390,7 @@ phy1: ethernet-phy@1 { compatible = "ethernet-phy-ieee802.3-c22"; reg = <1>; + marvell,reg-init = <3 18 0 0x4985>; /* irq is connected to &pcawan pin 7 */ }; From 990b03b05b2fba79de2a1ee9dc359fc552d95ba6 Mon Sep 17 00:00:00 2001 From: Yunjian Wang Date: Thu, 1 Apr 2021 12:52:48 +0800 Subject: [PATCH 0673/1091] net: cls_api: Fix uninitialised struct field bo->unlocked_driver_cb The 'unlocked_driver_cb' struct field in 'bo' is not being initialized in tcf_block_offload_init(). The uninitialized 'unlocked_driver_cb' will be used when calling unlocked_driver_cb(). So initialize 'bo' to zero to avoid the issue. Addresses-Coverity: ("Uninitialized scalar variable") Fixes: 0fdcf78d5973 ("net: use flow_indr_dev_setup_offload()") Signed-off-by: Yunjian Wang Signed-off-by: David S. Miller --- net/sched/cls_api.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 13341e7fb077..9332ec6863e8 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -646,7 +646,7 @@ static void tc_block_indr_cleanup(struct flow_block_cb *block_cb) struct net_device *dev = block_cb->indr.dev; struct Qdisc *sch = block_cb->indr.sch; struct netlink_ext_ack extack = {}; - struct flow_block_offload bo; + struct flow_block_offload bo = {}; tcf_block_offload_init(&bo, dev, sch, FLOW_BLOCK_UNBIND, block_cb->indr.binder_type, From a14d273ba15968495896a38b7b3399dba66d0270 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Fri, 2 Apr 2021 15:42:53 +0300 Subject: [PATCH 0674/1091] net: macb: restore cmp registers on resume path Restore CMP screener registers on resume path. Fixes: c1e85c6ce57ef ("net: macb: save/restore the remaining registers and features") Signed-off-by: Claudiu Beznea Acked-by: Nicolas Ferre Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 15362d016a87..6e5cf490c01d 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3239,6 +3239,9 @@ static void gem_prog_cmp_regs(struct macb *bp, struct ethtool_rx_flow_spec *fs) bool cmp_b = false; bool cmp_c = false; + if (!macb_is_gem(bp)) + return; + tp4sp_v = &(fs->h_u.tcp_ip4_spec); tp4sp_m = &(fs->m_u.tcp_ip4_spec); @@ -3607,6 +3610,7 @@ static void macb_restore_features(struct macb *bp) { struct net_device *netdev = bp->dev; netdev_features_t features = netdev->features; + struct ethtool_rx_fs_item *item; /* TX checksum offload */ macb_set_txcsum_feature(bp, features); @@ -3615,6 +3619,9 @@ static void macb_restore_features(struct macb *bp) macb_set_rxcsum_feature(bp, features); /* RX Flow Filters */ + list_for_each_entry(item, &bp->rx_fs_list.list, list) + gem_prog_cmp_regs(bp, &item->fs); + macb_set_rxflow_feature(bp, features); } From e82ad4853948382d37ac512b27a3e70b6f01c103 Mon Sep 17 00:00:00 2001 From: Jens Axboe Date: Fri, 2 Apr 2021 19:45:34 -0600 Subject: [PATCH 0675/1091] io_uring: fix !CONFIG_BLOCK compilation failure kernel test robot correctly pinpoints a compilation failure if CONFIG_BLOCK isn't set: fs/io_uring.c: In function '__io_complete_rw': >> fs/io_uring.c:2509:48: error: implicit declaration of function 'io_rw_should_reissue'; did you mean 'io_rw_reissue'? [-Werror=implicit-function-declaration] 2509 | if ((res == -EAGAIN || res == -EOPNOTSUPP) && io_rw_should_reissue(req)) { | ^~~~~~~~~~~~~~~~~~~~ | io_rw_reissue cc1: some warnings being treated as errors Ensure that we have a stub declaration of io_rw_should_reissue() for !CONFIG_BLOCK. Fixes: 230d50d448ac ("io_uring: move reissue into regular IO path") Reported-by: kernel test robot Signed-off-by: Jens Axboe --- fs/io_uring.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/fs/io_uring.c b/fs/io_uring.c index 8be542050648..65a17d560a73 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2479,6 +2479,11 @@ static bool io_rw_should_reissue(struct io_kiocb *req) return false; return true; } +#else +static bool io_rw_should_reissue(struct io_kiocb *req) +{ + return false; +} #endif static bool io_rw_reissue(struct io_kiocb *req) From 8d3c0c01cb2e36b2bf3c06a82b18b228d0c8f5d0 Mon Sep 17 00:00:00 2001 From: Lukasz Bartosik Date: Fri, 2 Apr 2021 00:51:48 +0200 Subject: [PATCH 0676/1091] clk: fix invalid usage of list cursor in register Fix invalid usage of a list_for_each_entry cursor in clk_notifier_register(). When list is empty or if the list is completely traversed (without breaking from the loop on one of the entries) then the list cursor does not point to a valid entry and therefore should not be used. The issue was dicovered when running 5.12-rc1 kernel on x86_64 with KASAN enabled: BUG: KASAN: global-out-of-bounds in clk_notifier_register+0xab/0x230 Read of size 8 at addr ffffffffa0d10588 by task swapper/0/1 CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.12.0-rc1 #1 Hardware name: Google Caroline/Caroline, BIOS Google_Caroline.7820.430.0 07/20/2018 Call Trace: dump_stack+0xee/0x15c print_address_description+0x1e/0x2dc kasan_report+0x188/0x1ce ? clk_notifier_register+0xab/0x230 ? clk_prepare_lock+0x15/0x7b ? clk_notifier_register+0xab/0x230 clk_notifier_register+0xab/0x230 dw8250_probe+0xc01/0x10d4 ... Memory state around the buggy address: ffffffffa0d10480: 00 00 00 00 00 03 f9 f9 f9 f9 f9 f9 00 00 00 00 ffffffffa0d10500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f9 f9 >ffffffffa0d10580: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00 ^ ffffffffa0d10600: 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 00 00 00 00 ffffffffa0d10680: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00 ================================================================== Fixes: b2476490ef11 ("clk: introduce the common clock framework") Reported-by: Lukasz Majczak Signed-off-by: Lukasz Bartosik Link: https://lore.kernel.org/r/20210401225149.18826-1-lb@semihalf.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 5052541a0986..16634d5912be 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4357,20 +4357,19 @@ int clk_notifier_register(struct clk *clk, struct notifier_block *nb) /* search the list of notifiers for this clk */ list_for_each_entry(cn, &clk_notifier_list, node) if (cn->clk == clk) - break; + goto found; /* if clk wasn't in the notifier list, allocate new clk_notifier */ - if (cn->clk != clk) { - cn = kzalloc(sizeof(*cn), GFP_KERNEL); - if (!cn) - goto out; + cn = kzalloc(sizeof(*cn), GFP_KERNEL); + if (!cn) + goto out; - cn->clk = clk; - srcu_init_notifier_head(&cn->notifier_head); + cn->clk = clk; + srcu_init_notifier_head(&cn->notifier_head); - list_add(&cn->node, &clk_notifier_list); - } + list_add(&cn->node, &clk_notifier_list); +found: ret = srcu_notifier_chain_register(&cn->notifier_head, nb); clk->core->notifier_count++; From 7045465500e465b09f09d6e5bdc260a9f1aab97b Mon Sep 17 00:00:00 2001 From: Lukasz Bartosik Date: Fri, 2 Apr 2021 00:51:49 +0200 Subject: [PATCH 0677/1091] clk: fix invalid usage of list cursor in unregister Fix invalid usage of a list_for_each_entry cursor in clk_notifier_unregister(). When list is empty or if the list is completely traversed (without breaking from the loop on one of the entries) then the list cursor does not point to a valid entry and therefore should not be used. The patch fixes a logical bug that hasn't been seen in pratice however it is analogus to the bug fixed in clk_notifier_register(). The issue was dicovered when running 5.12-rc1 kernel on x86_64 with KASAN enabled: BUG: KASAN: global-out-of-bounds in clk_notifier_register+0xab/0x230 Read of size 8 at addr ffffffffa0d10588 by task swapper/0/1 CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.12.0-rc1 #1 Hardware name: Google Caroline/Caroline, BIOS Google_Caroline.7820.430.0 07/20/2018 Call Trace: dump_stack+0xee/0x15c print_address_description+0x1e/0x2dc kasan_report+0x188/0x1ce ? clk_notifier_register+0xab/0x230 ? clk_prepare_lock+0x15/0x7b ? clk_notifier_register+0xab/0x230 clk_notifier_register+0xab/0x230 dw8250_probe+0xc01/0x10d4 ... Memory state around the buggy address: ffffffffa0d10480: 00 00 00 00 00 03 f9 f9 f9 f9 f9 f9 00 00 00 00 ffffffffa0d10500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 f9 f9 >ffffffffa0d10580: f9 f9 f9 f9 00 00 00 00 00 00 00 00 00 00 00 00 ^ ffffffffa0d10600: 00 00 00 00 00 00 f9 f9 f9 f9 f9 f9 00 00 00 00 ffffffffa0d10680: 00 00 00 00 00 00 00 00 f9 f9 f9 f9 00 00 00 00 ================================================================== Fixes: b2476490ef11 ("clk: introduce the common clock framework") Reported-by: Lukasz Majczak Signed-off-by: Lukasz Bartosik Link: https://lore.kernel.org/r/20210401225149.18826-2-lb@semihalf.com Signed-off-by: Stephen Boyd --- drivers/clk/clk.c | 32 ++++++++++++++------------------ 1 file changed, 14 insertions(+), 18 deletions(-) diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index 16634d5912be..39cfc6c6a8d2 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -4394,32 +4394,28 @@ EXPORT_SYMBOL_GPL(clk_notifier_register); */ int clk_notifier_unregister(struct clk *clk, struct notifier_block *nb) { - struct clk_notifier *cn = NULL; - int ret = -EINVAL; + struct clk_notifier *cn; + int ret = -ENOENT; if (!clk || !nb) return -EINVAL; clk_prepare_lock(); - list_for_each_entry(cn, &clk_notifier_list, node) - if (cn->clk == clk) + list_for_each_entry(cn, &clk_notifier_list, node) { + if (cn->clk == clk) { + ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb); + + clk->core->notifier_count--; + + /* XXX the notifier code should handle this better */ + if (!cn->notifier_head.head) { + srcu_cleanup_notifier_head(&cn->notifier_head); + list_del(&cn->node); + kfree(cn); + } break; - - if (cn->clk == clk) { - ret = srcu_notifier_chain_unregister(&cn->notifier_head, nb); - - clk->core->notifier_count--; - - /* XXX the notifier code should handle this better */ - if (!cn->notifier_head.head) { - srcu_cleanup_notifier_head(&cn->notifier_head); - list_del(&cn->node); - kfree(cn); } - - } else { - ret = -ENOENT; } clk_prepare_unlock(); From 1683f7de65dbf0a2c6a7d639173fe92430a28930 Mon Sep 17 00:00:00 2001 From: Zhen Lei Date: Wed, 31 Mar 2021 15:06:43 +0200 Subject: [PATCH 0678/1091] soc: litex: Remove duplicated header file inclusion The header file is already included above and can be removed here. Signed-off-by: Zhen Lei Signed-off-by: Mateusz Holenko Signed-off-by: Stafford Horne --- drivers/soc/litex/litex_soc_ctrl.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/soc/litex/litex_soc_ctrl.c b/drivers/soc/litex/litex_soc_ctrl.c index 6268bfa7f0d6..c3e379a990f2 100644 --- a/drivers/soc/litex/litex_soc_ctrl.c +++ b/drivers/soc/litex/litex_soc_ctrl.c @@ -13,7 +13,6 @@ #include #include #include -#include #include #include From 0687c66b5f666b5ad433f4e94251590d9bc9d10e Mon Sep 17 00:00:00 2001 From: Zqiang Date: Thu, 18 Feb 2021 11:16:49 +0800 Subject: [PATCH 0679/1091] workqueue: Move the position of debug_work_activate() in __queue_work() The debug_work_activate() is called on the premise that the work can be inserted, because if wq be in WQ_DRAINING status, insert work may be failed. Fixes: e41e704bc4f4 ("workqueue: improve destroy_workqueue() debuggability") Signed-off-by: Zqiang Reviewed-by: Lai Jiangshan Signed-off-by: Tejun Heo --- kernel/workqueue.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 0d150da252e8..21fb00b52def 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -1412,7 +1412,6 @@ static void __queue_work(int cpu, struct workqueue_struct *wq, */ lockdep_assert_irqs_disabled(); - debug_work_activate(work); /* if draining, only works from the same workqueue are allowed */ if (unlikely(wq->flags & __WQ_DRAINING) && @@ -1494,6 +1493,7 @@ retry: worklist = &pwq->delayed_works; } + debug_work_activate(work); insert_work(pwq, work, worklist, work_flags); out: From 89e28ce60cb65971c73359c66d076aa20a395cd5 Mon Sep 17 00:00:00 2001 From: Wang Qing Date: Wed, 24 Mar 2021 19:40:29 +0800 Subject: [PATCH 0680/1091] workqueue/watchdog: Make unbound workqueues aware of touch_softlockup_watchdog() 84;0;0c84;0;0c There are two workqueue-specific watchdog timestamps: + @wq_watchdog_touched_cpu (per-CPU) updated by touch_softlockup_watchdog() + @wq_watchdog_touched (global) updated by touch_all_softlockup_watchdogs() watchdog_timer_fn() checks only the global @wq_watchdog_touched for unbound workqueues. As a result, unbound workqueues are not aware of touch_softlockup_watchdog(). The watchdog might report a stall even when the unbound workqueues are blocked by a known slow code. Solution: touch_softlockup_watchdog() must touch also the global @wq_watchdog_touched timestamp. The global timestamp can no longer be used for bound workqueues because it is now updated from all CPUs. Instead, bound workqueues have to check only @wq_watchdog_touched_cpu and these timestamps have to be updated for all CPUs in touch_all_softlockup_watchdogs(). Beware: The change might cause the opposite problem. An unbound workqueue might get blocked on CPU A because of a real softlockup. The workqueue watchdog would miss it when the timestamp got touched on CPU B. It is acceptable because softlockups are detected by softlockup watchdog. The workqueue watchdog is there to detect stalls where a work never finishes, for example, because of dependencies of works queued into the same workqueue. V3: - Modify the commit message clearly according to Petr's suggestion. Signed-off-by: Wang Qing Signed-off-by: Tejun Heo --- kernel/watchdog.c | 5 +++-- kernel/workqueue.c | 17 ++++++----------- 2 files changed, 9 insertions(+), 13 deletions(-) diff --git a/kernel/watchdog.c b/kernel/watchdog.c index 71109065bd8e..107bc38b1945 100644 --- a/kernel/watchdog.c +++ b/kernel/watchdog.c @@ -278,9 +278,10 @@ void touch_all_softlockup_watchdogs(void) * update as well, the only side effect might be a cycle delay for * the softlockup check. */ - for_each_cpu(cpu, &watchdog_allowed_mask) + for_each_cpu(cpu, &watchdog_allowed_mask) { per_cpu(watchdog_touch_ts, cpu) = SOFTLOCKUP_RESET; - wq_watchdog_touch(-1); + wq_watchdog_touch(cpu); + } } void touch_softlockup_watchdog_sync(void) diff --git a/kernel/workqueue.c b/kernel/workqueue.c index 21fb00b52def..79f2319543ce 100644 --- a/kernel/workqueue.c +++ b/kernel/workqueue.c @@ -5787,22 +5787,17 @@ static void wq_watchdog_timer_fn(struct timer_list *unused) continue; /* get the latest of pool and touched timestamps */ + if (pool->cpu >= 0) + touched = READ_ONCE(per_cpu(wq_watchdog_touched_cpu, pool->cpu)); + else + touched = READ_ONCE(wq_watchdog_touched); pool_ts = READ_ONCE(pool->watchdog_ts); - touched = READ_ONCE(wq_watchdog_touched); if (time_after(pool_ts, touched)) ts = pool_ts; else ts = touched; - if (pool->cpu >= 0) { - unsigned long cpu_touched = - READ_ONCE(per_cpu(wq_watchdog_touched_cpu, - pool->cpu)); - if (time_after(cpu_touched, ts)) - ts = cpu_touched; - } - /* did we stall? */ if (time_after(jiffies, ts + thresh)) { lockup_detected = true; @@ -5826,8 +5821,8 @@ notrace void wq_watchdog_touch(int cpu) { if (cpu >= 0) per_cpu(wq_watchdog_touched_cpu, cpu) = jiffies; - else - wq_watchdog_touched = jiffies; + + wq_watchdog_touched = jiffies; } static void wq_watchdog_set_thresh(unsigned long thresh) From 829933ef05a951c8ff140e814656d73e74915faf Mon Sep 17 00:00:00 2001 From: Zheyu Ma Date: Sat, 3 Apr 2021 06:58:36 +0000 Subject: [PATCH 0681/1091] firewire: nosy: Fix a use-after-free bug in nosy_ioctl() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit For each device, the nosy driver allocates a pcilynx structure. A use-after-free might happen in the following scenario: 1. Open nosy device for the first time and call ioctl with command NOSY_IOC_START, then a new client A will be malloced and added to doubly linked list. 2. Open nosy device for the second time and call ioctl with command NOSY_IOC_START, then a new client B will be malloced and added to doubly linked list. 3. Call ioctl with command NOSY_IOC_START for client A, then client A will be readded to the doubly linked list. Now the doubly linked list is messed up. 4. Close the first nosy device and nosy_release will be called. In nosy_release, client A will be unlinked and freed. 5. Close the second nosy device, and client A will be referenced, resulting in UAF. The root cause of this bug is that the element in the doubly linked list is reentered into the list. Fix this bug by adding a check before inserting a client. If a client is already in the linked list, don't insert it. The following KASAN report reveals it: BUG: KASAN: use-after-free in nosy_release+0x1ea/0x210 Write of size 8 at addr ffff888102ad7360 by task poc CPU: 3 PID: 337 Comm: poc Not tainted 5.12.0-rc5+ #6 Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.12.0-59-gc9ba5276e321-prebuilt.qemu.org 04/01/2014 Call Trace: nosy_release+0x1ea/0x210 __fput+0x1e2/0x840 task_work_run+0xe8/0x180 exit_to_user_mode_prepare+0x114/0x120 syscall_exit_to_user_mode+0x1d/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae Allocated by task 337: nosy_open+0x154/0x4d0 misc_open+0x2ec/0x410 chrdev_open+0x20d/0x5a0 do_dentry_open+0x40f/0xe80 path_openat+0x1cf9/0x37b0 do_filp_open+0x16d/0x390 do_sys_openat2+0x11d/0x360 __x64_sys_open+0xfd/0x1a0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae Freed by task 337: kfree+0x8f/0x210 nosy_release+0x158/0x210 __fput+0x1e2/0x840 task_work_run+0xe8/0x180 exit_to_user_mode_prepare+0x114/0x120 syscall_exit_to_user_mode+0x1d/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae The buggy address belongs to the object at ffff888102ad7300 which belongs to the cache kmalloc-128 of size 128 The buggy address is located 96 bytes inside of 128-byte region [ffff888102ad7300, ffff888102ad7380) [ Modified to use 'list_empty()' inside proper lock - Linus ] Link: https://lore.kernel.org/lkml/1617433116-5930-1-git-send-email-zheyuma97@gmail.com/ Reported-and-tested-by: 马哲宇 (Zheyu Ma) Signed-off-by: Zheyu Ma Cc: Greg Kroah-Hartman Cc: Stefan Richter Signed-off-by: Linus Torvalds --- drivers/firewire/nosy.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/firewire/nosy.c b/drivers/firewire/nosy.c index 5fd6a60b6741..88ed971e32c0 100644 --- a/drivers/firewire/nosy.c +++ b/drivers/firewire/nosy.c @@ -346,6 +346,7 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) struct client *client = file->private_data; spinlock_t *client_list_lock = &client->lynx->client_list_lock; struct nosy_stats stats; + int ret; switch (cmd) { case NOSY_IOC_GET_STATS: @@ -360,11 +361,15 @@ nosy_ioctl(struct file *file, unsigned int cmd, unsigned long arg) return 0; case NOSY_IOC_START: + ret = -EBUSY; spin_lock_irq(client_list_lock); - list_add_tail(&client->link, &client->lynx->client_list); + if (list_empty(&client->link)) { + list_add_tail(&client->link, &client->lynx->client_list); + ret = 0; + } spin_unlock_irq(client_list_lock); - return 0; + return ret; case NOSY_IOC_STOP: spin_lock_irq(client_list_lock); From e49d033bddf5b565044e2abe4241353959bc9120 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 4 Apr 2021 14:15:36 -0700 Subject: [PATCH 0682/1091] Linux 5.12-rc6 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 73add16f9898..cc77fd45ca64 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 5 PATCHLEVEL = 12 SUBLEVEL = 0 -EXTRAVERSION = -rc5 +EXTRAVERSION = -rc6 NAME = Frozen Wasteland # *DOCUMENTATION* From 4e9c93af7279b059faf5bb1897ee90512b258a12 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 29 Mar 2021 19:36:48 -0600 Subject: [PATCH 0683/1091] usbip: add sysfs_lock to synchronize sysfs code paths Fuzzing uncovered race condition between sysfs code paths in usbip drivers. Device connect/disconnect code paths initiated through sysfs interface are prone to races if disconnect happens during connect and vice versa. This problem is common to all drivers while it can be reproduced easily in vhci_hcd. Add a sysfs_lock to usbip_device struct to protect the paths. Use this in vhci_hcd to protect sysfs paths. For a complete fix, usip_host and usip-vudc drivers and the event handler will have to use this lock to protect the paths. These changes will be done in subsequent patches. Cc: stable@vger.kernel.org Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com Signed-off-by: Shuah Khan Link: https://lore.kernel.org/r/b6568f7beae702bbc236a545d3c020106ca75eac.1616807117.git.skhan@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/usbip_common.h | 3 +++ drivers/usb/usbip/vhci_hcd.c | 1 + drivers/usb/usbip/vhci_sysfs.c | 30 +++++++++++++++++++++++++----- 3 files changed, 29 insertions(+), 5 deletions(-) diff --git a/drivers/usb/usbip/usbip_common.h b/drivers/usb/usbip/usbip_common.h index d60ce17d3dd2..ea2a20e6d27d 100644 --- a/drivers/usb/usbip/usbip_common.h +++ b/drivers/usb/usbip/usbip_common.h @@ -263,6 +263,9 @@ struct usbip_device { /* lock for status */ spinlock_t lock; + /* mutex for synchronizing sysfs store paths */ + struct mutex sysfs_lock; + int sockfd; struct socket *tcp_socket; diff --git a/drivers/usb/usbip/vhci_hcd.c b/drivers/usb/usbip/vhci_hcd.c index a20a8380ca0c..4ba6bcdaa8e9 100644 --- a/drivers/usb/usbip/vhci_hcd.c +++ b/drivers/usb/usbip/vhci_hcd.c @@ -1101,6 +1101,7 @@ static void vhci_device_init(struct vhci_device *vdev) vdev->ud.side = USBIP_VHCI; vdev->ud.status = VDEV_ST_NULL; spin_lock_init(&vdev->ud.lock); + mutex_init(&vdev->ud.sysfs_lock); INIT_LIST_HEAD(&vdev->priv_rx); INIT_LIST_HEAD(&vdev->priv_tx); diff --git a/drivers/usb/usbip/vhci_sysfs.c b/drivers/usb/usbip/vhci_sysfs.c index c4b4256e5dad..e2847cd3e6e3 100644 --- a/drivers/usb/usbip/vhci_sysfs.c +++ b/drivers/usb/usbip/vhci_sysfs.c @@ -185,6 +185,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) usbip_dbg_vhci_sysfs("enter\n"); + mutex_lock(&vdev->ud.sysfs_lock); + /* lock */ spin_lock_irqsave(&vhci->lock, flags); spin_lock(&vdev->ud.lock); @@ -195,6 +197,7 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) /* unlock */ spin_unlock(&vdev->ud.lock); spin_unlock_irqrestore(&vhci->lock, flags); + mutex_unlock(&vdev->ud.sysfs_lock); return -EINVAL; } @@ -205,6 +208,8 @@ static int vhci_port_disconnect(struct vhci_hcd *vhci_hcd, __u32 rhport) usbip_event_add(&vdev->ud, VDEV_EVENT_DOWN); + mutex_unlock(&vdev->ud.sysfs_lock); + return 0; } @@ -349,30 +354,36 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, else vdev = &vhci->vhci_hcd_hs->vdev[rhport]; + mutex_lock(&vdev->ud.sysfs_lock); + /* Extract socket from fd. */ socket = sockfd_lookup(sockfd, &err); if (!socket) { dev_err(dev, "failed to lookup sock"); - return -EINVAL; + err = -EINVAL; + goto unlock_mutex; } if (socket->type != SOCK_STREAM) { dev_err(dev, "Expecting SOCK_STREAM - found %d", socket->type); sockfd_put(socket); - return -EINVAL; + err = -EINVAL; + goto unlock_mutex; } /* create threads before locking */ tcp_rx = kthread_create(vhci_rx_loop, &vdev->ud, "vhci_rx"); if (IS_ERR(tcp_rx)) { sockfd_put(socket); - return -EINVAL; + err = -EINVAL; + goto unlock_mutex; } tcp_tx = kthread_create(vhci_tx_loop, &vdev->ud, "vhci_tx"); if (IS_ERR(tcp_tx)) { kthread_stop(tcp_rx); sockfd_put(socket); - return -EINVAL; + err = -EINVAL; + goto unlock_mutex; } /* get task structs now */ @@ -397,7 +408,8 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, * Will be retried from userspace * if there's another free port. */ - return -EBUSY; + err = -EBUSY; + goto unlock_mutex; } dev_info(dev, "pdev(%u) rhport(%u) sockfd(%d)\n", @@ -423,7 +435,15 @@ static ssize_t attach_store(struct device *dev, struct device_attribute *attr, rh_port_connect(vdev, speed); + dev_info(dev, "Device attached\n"); + + mutex_unlock(&vdev->ud.sysfs_lock); + return count; + +unlock_mutex: + mutex_unlock(&vdev->ud.sysfs_lock); + return err; } static DEVICE_ATTR_WO(attach); From 9dbf34a834563dada91366c2ac266f32ff34641a Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 29 Mar 2021 19:36:49 -0600 Subject: [PATCH 0684/1091] usbip: stub-dev synchronize sysfs code paths Fuzzing uncovered race condition between sysfs code paths in usbip drivers. Device connect/disconnect code paths initiated through sysfs interface are prone to races if disconnect happens during connect and vice versa. Use sysfs_lock to protect sysfs paths in stub-dev. Cc: stable@vger.kernel.org Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com Signed-off-by: Shuah Khan Link: https://lore.kernel.org/r/2b182f3561b4a065bf3bf6dce3b0e9944ba17b3f.1616807117.git.skhan@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/stub_dev.c | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/drivers/usb/usbip/stub_dev.c b/drivers/usb/usbip/stub_dev.c index 8f1de1fbbeed..d8d3892e5a69 100644 --- a/drivers/usb/usbip/stub_dev.c +++ b/drivers/usb/usbip/stub_dev.c @@ -63,6 +63,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a dev_info(dev, "stub up\n"); + mutex_lock(&sdev->ud.sysfs_lock); spin_lock_irq(&sdev->ud.lock); if (sdev->ud.status != SDEV_ST_AVAILABLE) { @@ -87,13 +88,13 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a tcp_rx = kthread_create(stub_rx_loop, &sdev->ud, "stub_rx"); if (IS_ERR(tcp_rx)) { sockfd_put(socket); - return -EINVAL; + goto unlock_mutex; } tcp_tx = kthread_create(stub_tx_loop, &sdev->ud, "stub_tx"); if (IS_ERR(tcp_tx)) { kthread_stop(tcp_rx); sockfd_put(socket); - return -EINVAL; + goto unlock_mutex; } /* get task structs now */ @@ -112,6 +113,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a wake_up_process(sdev->ud.tcp_rx); wake_up_process(sdev->ud.tcp_tx); + mutex_unlock(&sdev->ud.sysfs_lock); + } else { dev_info(dev, "stub down\n"); @@ -122,6 +125,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, struct device_attribute *a spin_unlock_irq(&sdev->ud.lock); usbip_event_add(&sdev->ud, SDEV_EVENT_DOWN); + mutex_unlock(&sdev->ud.sysfs_lock); } return count; @@ -130,6 +134,8 @@ sock_err: sockfd_put(socket); err: spin_unlock_irq(&sdev->ud.lock); +unlock_mutex: + mutex_unlock(&sdev->ud.sysfs_lock); return -EINVAL; } static DEVICE_ATTR_WO(usbip_sockfd); @@ -270,6 +276,7 @@ static struct stub_device *stub_device_alloc(struct usb_device *udev) sdev->ud.side = USBIP_STUB; sdev->ud.status = SDEV_ST_AVAILABLE; spin_lock_init(&sdev->ud.lock); + mutex_init(&sdev->ud.sysfs_lock); sdev->ud.tcp_socket = NULL; sdev->ud.sockfd = -1; From bd8b82042269a95db48074b8bb400678dbac1815 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 29 Mar 2021 19:36:50 -0600 Subject: [PATCH 0685/1091] usbip: vudc synchronize sysfs code paths Fuzzing uncovered race condition between sysfs code paths in usbip drivers. Device connect/disconnect code paths initiated through sysfs interface are prone to races if disconnect happens during connect and vice versa. Use sysfs_lock to protect sysfs paths in vudc. Cc: stable@vger.kernel.org Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com Signed-off-by: Shuah Khan Link: https://lore.kernel.org/r/caabcf3fc87bdae970509b5ff32d05bb7ce2fb15.1616807117.git.skhan@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/vudc_dev.c | 1 + drivers/usb/usbip/vudc_sysfs.c | 5 +++++ 2 files changed, 6 insertions(+) diff --git a/drivers/usb/usbip/vudc_dev.c b/drivers/usb/usbip/vudc_dev.c index c8eeabdd9b56..2bc428f2e261 100644 --- a/drivers/usb/usbip/vudc_dev.c +++ b/drivers/usb/usbip/vudc_dev.c @@ -572,6 +572,7 @@ static int init_vudc_hw(struct vudc *udc) init_waitqueue_head(&udc->tx_waitq); spin_lock_init(&ud->lock); + mutex_init(&ud->sysfs_lock); ud->status = SDEV_ST_AVAILABLE; ud->side = USBIP_VUDC; diff --git a/drivers/usb/usbip/vudc_sysfs.c b/drivers/usb/usbip/vudc_sysfs.c index 7383a543c6d1..f7633ee655a1 100644 --- a/drivers/usb/usbip/vudc_sysfs.c +++ b/drivers/usb/usbip/vudc_sysfs.c @@ -112,6 +112,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, dev_err(dev, "no device"); return -ENODEV; } + mutex_lock(&udc->ud.sysfs_lock); spin_lock_irqsave(&udc->lock, flags); /* Don't export what we don't have */ if (!udc->driver || !udc->pullup) { @@ -187,6 +188,8 @@ static ssize_t usbip_sockfd_store(struct device *dev, wake_up_process(udc->ud.tcp_rx); wake_up_process(udc->ud.tcp_tx); + + mutex_unlock(&udc->ud.sysfs_lock); return count; } else { @@ -207,6 +210,7 @@ static ssize_t usbip_sockfd_store(struct device *dev, } spin_unlock_irqrestore(&udc->lock, flags); + mutex_unlock(&udc->ud.sysfs_lock); return count; @@ -216,6 +220,7 @@ unlock_ud: spin_unlock_irq(&udc->ud.lock); unlock: spin_unlock_irqrestore(&udc->lock, flags); + mutex_unlock(&udc->ud.sysfs_lock); return ret; } From 363eaa3a450abb4e63bd6e3ad79d1f7a0f717814 Mon Sep 17 00:00:00 2001 From: Shuah Khan Date: Mon, 29 Mar 2021 19:36:51 -0600 Subject: [PATCH 0686/1091] usbip: synchronize event handler with sysfs code paths Fuzzing uncovered race condition between sysfs code paths in usbip drivers. Device connect/disconnect code paths initiated through sysfs interface are prone to races if disconnect happens during connect and vice versa. Use sysfs_lock to synchronize event handler with sysfs paths in usbip drivers. Cc: stable@vger.kernel.org Reported-and-tested-by: syzbot+a93fba6d384346a761e3@syzkaller.appspotmail.com Signed-off-by: Shuah Khan Link: https://lore.kernel.org/r/c5c8723d3f29dfe3d759cfaafa7dd16b0dfe2918.1616807117.git.skhan@linuxfoundation.org Signed-off-by: Greg Kroah-Hartman --- drivers/usb/usbip/usbip_event.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/usb/usbip/usbip_event.c b/drivers/usb/usbip/usbip_event.c index 5d88917c9631..086ca76dd053 100644 --- a/drivers/usb/usbip/usbip_event.c +++ b/drivers/usb/usbip/usbip_event.c @@ -70,6 +70,7 @@ static void event_handler(struct work_struct *work) while ((ud = get_event()) != NULL) { usbip_dbg_eh("pending event %lx\n", ud->event); + mutex_lock(&ud->sysfs_lock); /* * NOTE: shutdown must come first. * Shutdown the device. @@ -90,6 +91,7 @@ static void event_handler(struct work_struct *work) ud->eh_ops.unusable(ud); unset_event(ud, USBIP_EH_UNUSABLE); } + mutex_unlock(&ud->sysfs_lock); wake_up(&ud->eh_waitq); } From eed6e41813deb9ee622cd9242341f21430d7789f Mon Sep 17 00:00:00 2001 From: Saravana Kannan Date: Thu, 1 Apr 2021 21:03:40 -0700 Subject: [PATCH 0687/1091] driver core: Fix locking bug in deferred_probe_timeout_work_func() list_for_each_entry_safe() is only useful if we are deleting nodes in a linked list within the loop. It doesn't protect against other threads adding/deleting nodes to the list in parallel. We need to grab deferred_probe_mutex when traversing the deferred_probe_pending_list. Cc: stable@vger.kernel.org Fixes: 25b4e70dcce9 ("driver core: allow stopping deferred probe after init") Signed-off-by: Saravana Kannan Link: https://lore.kernel.org/r/20210402040342.2944858-2-saravanak@google.com Signed-off-by: Greg Kroah-Hartman --- drivers/base/dd.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/base/dd.c b/drivers/base/dd.c index e2cf3b29123e..37a5e5f8b221 100644 --- a/drivers/base/dd.c +++ b/drivers/base/dd.c @@ -292,14 +292,16 @@ int driver_deferred_probe_check_state(struct device *dev) static void deferred_probe_timeout_work_func(struct work_struct *work) { - struct device_private *private, *p; + struct device_private *p; driver_deferred_probe_timeout = 0; driver_deferred_probe_trigger(); flush_work(&deferred_probe_work); - list_for_each_entry_safe(private, p, &deferred_probe_pending_list, deferred_probe) - dev_info(private->device, "deferred probe pending\n"); + mutex_lock(&deferred_probe_mutex); + list_for_each_entry(p, &deferred_probe_pending_list, deferred_probe) + dev_info(p->device, "deferred probe pending\n"); + mutex_unlock(&deferred_probe_mutex); wake_up_all(&probe_timeout_waitqueue); } static DECLARE_DELAYED_WORK(deferred_probe_timeout_work, deferred_probe_timeout_work_func); From 7a2f91441b2c1d81b77c1cd816a4659f4abc9cbe Mon Sep 17 00:00:00 2001 From: Alexander Gordeev Date: Mon, 29 Mar 2021 18:35:07 +0200 Subject: [PATCH 0688/1091] s390/cpcmd: fix inline assembly register clobbering Register variables initialized using arithmetic. That leads to kasan instrumentaton code corrupting the registers contents. Follow GCC guidlines and use temporary variables for assigning init values to register variables. Fixes: 94c12cc7d196 ("[S390] Inline assembly cleanup.") Signed-off-by: Alexander Gordeev Acked-by: Ilya Leoshkevich Link: https://gcc.gnu.org/onlinedocs/gcc-10.2.0/gcc/Local-Register-Variables.html Signed-off-by: Heiko Carstens --- arch/s390/kernel/cpcmd.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/s390/kernel/cpcmd.c b/arch/s390/kernel/cpcmd.c index af013b4244d3..2da027359798 100644 --- a/arch/s390/kernel/cpcmd.c +++ b/arch/s390/kernel/cpcmd.c @@ -37,10 +37,12 @@ static int diag8_noresponse(int cmdlen) static int diag8_response(int cmdlen, char *response, int *rlen) { + unsigned long _cmdlen = cmdlen | 0x40000000L; + unsigned long _rlen = *rlen; register unsigned long reg2 asm ("2") = (addr_t) cpcmd_buf; register unsigned long reg3 asm ("3") = (addr_t) response; - register unsigned long reg4 asm ("4") = cmdlen | 0x40000000L; - register unsigned long reg5 asm ("5") = *rlen; + register unsigned long reg4 asm ("4") = _cmdlen; + register unsigned long reg5 asm ("5") = _rlen; asm volatile( " diag %2,%0,0x8\n" From 08edb9683e47f5183aed9aa3f926292b54c278c1 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Wed, 31 Mar 2021 11:44:50 +0200 Subject: [PATCH 0689/1091] s390/unwind: add machine check handler stack Fixes: b61b1595124a ("s390: add stack for machine check handler") Signed-off-by: Vasily Gorbik Signed-off-by: Heiko Carstens --- arch/s390/include/asm/stacktrace.h | 1 + arch/s390/kernel/dumpstack.c | 12 +++++++++++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/arch/s390/include/asm/stacktrace.h b/arch/s390/include/asm/stacktrace.h index ee056f4a4fa3..2b543163d90a 100644 --- a/arch/s390/include/asm/stacktrace.h +++ b/arch/s390/include/asm/stacktrace.h @@ -12,6 +12,7 @@ enum stack_type { STACK_TYPE_IRQ, STACK_TYPE_NODAT, STACK_TYPE_RESTART, + STACK_TYPE_MCCK, }; struct stack_info { diff --git a/arch/s390/kernel/dumpstack.c b/arch/s390/kernel/dumpstack.c index 0dc4b258b98d..db1bc00229ca 100644 --- a/arch/s390/kernel/dumpstack.c +++ b/arch/s390/kernel/dumpstack.c @@ -79,6 +79,15 @@ static bool in_nodat_stack(unsigned long sp, struct stack_info *info) return in_stack(sp, info, STACK_TYPE_NODAT, top - THREAD_SIZE, top); } +static bool in_mcck_stack(unsigned long sp, struct stack_info *info) +{ + unsigned long frame_size, top; + + frame_size = STACK_FRAME_OVERHEAD + sizeof(struct pt_regs); + top = S390_lowcore.mcck_stack + frame_size; + return in_stack(sp, info, STACK_TYPE_MCCK, top - THREAD_SIZE, top); +} + static bool in_restart_stack(unsigned long sp, struct stack_info *info) { unsigned long frame_size, top; @@ -108,7 +117,8 @@ int get_stack_info(unsigned long sp, struct task_struct *task, /* Check per-cpu stacks */ if (!in_irq_stack(sp, info) && !in_nodat_stack(sp, info) && - !in_restart_stack(sp, info)) + !in_restart_stack(sp, info) && + !in_mcck_stack(sp, info)) goto unknown; recursion_check: From 85012e764d3a1be02297b23c1aa3467f0df212aa Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Sat, 3 Apr 2021 12:15:13 +0200 Subject: [PATCH 0690/1091] s390/irq: fix reading of ext_params2 field from lowcore The contents of the ext_params2 field of the lowcore should just be copied to the pt_regs structure, not dereferenced. Fixes crashes / program check loops like this: Krnl PSW : 0404c00180000000 00000000d6d02b3c (do_ext_irq+0x74/0x170) R:0 T:1 IO:0 EX:0 Key:0 M:1 W:0 P:0 AS:3 CC:0 PM:0 RI:0 EA:3 Krnl GPRS: 0000000000000000 80000000000b974e 00000000d71abee0 00000000d71abee0 0000000080030000 000000000000000f 0000000000000000 0000000000000000 0000000000000001 00000380000bf918 00000000d73ef780 00000380000bf518 0000000080348000 00000000d6d13350 00000000d6d02b1e 00000380000bf428 Krnl Code: 00000000d6d02b2e: 58100080 l %r1,128 00000000d6d02b32: 5010b0a4 st %r1,164(%r11) #00000000d6d02b36: e31001b80104 lg %r1,4536 >00000000d6d02b3c: e31010000004 lg %r1,0(%r1) 00000000d6d02b42: e310b0a80024 stg %r1,168(%r11) 00000000d6d02b48: c01000242270 larl %r1,00000000d7187028 00000000d6d02b4e: d5071000b010 clc 0(8,%r1),16(%r11) 00000000d6d02b54: a784001b brc 8,00000000d6d02b8a Call Trace: [<00000000d6d02b3c>] do_ext_irq+0x74/0x170 [<00000000d6d0ea5c>] ext_int_handler+0xc4/0xf4 [<00000000d621d266>] die+0x106/0x188 [<00000000d62305b8>] do_no_context+0xc8/0x100 [<00000000d6d02790>] __do_pgm_check+0xe0/0x1f0 [<00000000d6d0e950>] pgm_check_handler+0x118/0x160 [<00000000d6d02b3c>] do_ext_irq+0x74/0x170 [<00000000d6d0ea5c>] ext_int_handler+0xc4/0xf4 [<00000000d621d266>] die+0x106/0x188 [<00000000d62305b8>] do_no_context+0xc8/0x100 [<00000000d6d02790>] __do_pgm_check+0xe0/0x1f0 [<00000000d6d0e950>] pgm_check_handler+0x118/0x160 [<00000000d6d02b3c>] do_ext_irq+0x74/0x170 [<00000000d6d0ea5c>] ext_int_handler+0xc4/0xf4 [<0000000000000000>] 0x0 [<00000000d6d0e57a>] default_idle_call+0x42/0x110 [<00000000d629856e>] do_idle+0xce/0x160 [<00000000d62987be>] cpu_startup_entry+0x36/0x40 [<00000000d621f2f2>] smp_start_secondary+0x82/0x88 Cc: Sven Schnelle Cc: Vasily Gorbik Fixes: 56e62a737028 ("s390: convert to generic entry") Signed-off-by: Heiko Carstens --- arch/s390/kernel/irq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/irq.c b/arch/s390/kernel/irq.c index 601c21791338..714269e10eec 100644 --- a/arch/s390/kernel/irq.c +++ b/arch/s390/kernel/irq.c @@ -174,7 +174,7 @@ void noinstr do_ext_irq(struct pt_regs *regs) memcpy(®s->int_code, &S390_lowcore.ext_cpu_addr, 4); regs->int_parm = S390_lowcore.ext_params; - regs->int_parm_long = *(unsigned long *)S390_lowcore.ext_params2; + regs->int_parm_long = S390_lowcore.ext_params2; from_idle = !user_mode(regs) && regs->psw.addr == (unsigned long)psw_idle_exit; if (from_idle) From 026334a3bb6a3919b42aba9fc11843db2b77fd41 Mon Sep 17 00:00:00 2001 From: Adrian Hunter Date: Thu, 1 Apr 2021 13:36:05 +0300 Subject: [PATCH 0691/1091] perf inject: Fix repipe usage Since commit 14d3d54052539a1e ("perf session: Try to read pipe data from file") 'perf inject' has started printing "PERFILE2h" when not processing pipes. The commit exposed perf to the possiblity that the input is not a pipe but the 'repipe' parameter gets used. That causes the printing because perf inject sets 'repipe' to true always. The 'repipe' parameter of perf_session__new() is used by 2 functions: - perf_file_header__read_pipe() - trace_report() In both cases, the functions copy data to STDOUT_FILENO when 'repipe' is true. Fix by setting 'repipe' to true only if the output is a pipe. Fixes: e558a5bd8b74aff4 ("perf inject: Work with files") Signed-off-by: Adrian Hunter Acked-by: Jiri Olsa Cc: Andrew Vagin Link: http://lore.kernel.org/lkml/20210401103605.9000-1-adrian.hunter@intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/builtin-inject.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/builtin-inject.c b/tools/perf/builtin-inject.c index 6fe44d97fde5..ddccc0eb7390 100644 --- a/tools/perf/builtin-inject.c +++ b/tools/perf/builtin-inject.c @@ -906,7 +906,7 @@ int cmd_inject(int argc, const char **argv) } data.path = inject.input_name; - inject.session = perf_session__new(&data, true, &inject.tool); + inject.session = perf_session__new(&data, inject.output.is_pipe, &inject.tool); if (IS_ERR(inject.session)) return PTR_ERR(inject.session); From 4d51419d49930be2701c2633ae271b350397c3ca Mon Sep 17 00:00:00 2001 From: Ilya Maximets Date: Sun, 4 Apr 2021 19:50:31 +0200 Subject: [PATCH 0692/1091] openvswitch: fix send of uninitialized stack memory in ct limit reply 'struct ovs_zone_limit' has more members than initialized in ovs_ct_limit_get_default_limit(). The rest of the memory is a random kernel stack content that ends up being sent to userspace. Fix that by using designated initializer that will clear all non-specified fields. Fixes: 11efd5cb04a1 ("openvswitch: Support conntrack zone limit") Signed-off-by: Ilya Maximets Acked-by: Tonghao Zhang Signed-off-by: David S. Miller --- net/openvswitch/conntrack.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/openvswitch/conntrack.c b/net/openvswitch/conntrack.c index 71cec03e8612..d217bd91176b 100644 --- a/net/openvswitch/conntrack.c +++ b/net/openvswitch/conntrack.c @@ -2034,10 +2034,10 @@ static int ovs_ct_limit_del_zone_limit(struct nlattr *nla_zone_limit, static int ovs_ct_limit_get_default_limit(struct ovs_ct_limit_info *info, struct sk_buff *reply) { - struct ovs_zone_limit zone_limit; - - zone_limit.zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE; - zone_limit.limit = info->default_limit; + struct ovs_zone_limit zone_limit = { + .zone_id = OVS_ZONE_LIMIT_DEFAULT_ZONE, + .limit = info->default_limit, + }; return nla_put_nohdr(reply, sizeof(zone_limit), &zone_limit); } From 630e4576f83accf90366686f39808d665d8dbecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Maciej=20=C5=BBenczykowski?= Date: Mon, 5 Apr 2021 00:06:52 -0700 Subject: [PATCH 0693/1091] net-ipv6: bugfix - raw & sctp - switch to ipv6_can_nonlocal_bind() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Found by virtue of ipv6 raw sockets not honouring the per-socket IP{,V6}_FREEBIND setting. Based on hits found via: git grep '[.]ip_nonlocal_bind' We fix both raw ipv6 sockets to honour IP{,V6}_FREEBIND and IP{,V6}_TRANSPARENT, and we fix sctp sockets to honour IP{,V6}_TRANSPARENT (they already honoured FREEBIND), and not just the ipv6 'ip_nonlocal_bind' sysctl. The helper is defined as: static inline bool ipv6_can_nonlocal_bind(struct net *net, struct inet_sock *inet) { return net->ipv6.sysctl.ip_nonlocal_bind || inet->freebind || inet->transparent; } so this change only widens the accepted opt-outs and is thus a clean bugfix. I'm not entirely sure what 'fixes' tag to add, since this is AFAICT an ancient bug, but IMHO this should be applied to stable kernels as far back as possible. As such I'm adding a 'fixes' tag with the commit that originally added the helper, which happened in 4.19. Backporting to older LTS kernels (at least 4.9 and 4.14) would presumably require open-coding it or backporting the helper as well. Other possibly relevant commits: v4.18-rc6-1502-g83ba4645152d net: add helpers checking if socket can be bound to nonlocal address v4.18-rc6-1431-gd0c1f01138c4 net/ipv6: allow any source address for sendmsg pktinfo with ip_nonlocal_bind v4.14-rc5-271-gb71d21c274ef sctp: full support for ipv6 ip_nonlocal_bind & IP_FREEBIND v4.7-rc7-1883-g9b9742022888 sctp: support ipv6 nonlocal bind v4.1-12247-g35a256fee52c ipv6: Nonlocal bind Cc: Lorenzo Colitti Fixes: 83ba4645152d ("net: add helpers checking if socket can be bound to nonlocal address") Signed-off-by: Maciej Żenczykowski Reviewed-By: Lorenzo Colitti Signed-off-by: David S. Miller --- net/ipv6/raw.c | 2 +- net/sctp/ipv6.c | 7 +++---- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/net/ipv6/raw.c b/net/ipv6/raw.c index 1f56d9aae589..bf3646b57c68 100644 --- a/net/ipv6/raw.c +++ b/net/ipv6/raw.c @@ -298,7 +298,7 @@ static int rawv6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len) */ v4addr = LOOPBACK4_IPV6; if (!(addr_type & IPV6_ADDR_MULTICAST) && - !sock_net(sk)->ipv6.sysctl.ip_nonlocal_bind) { + !ipv6_can_nonlocal_bind(sock_net(sk), inet)) { err = -EADDRNOTAVAIL; if (!ipv6_chk_addr(sock_net(sk), &addr->sin6_addr, dev, 0)) { diff --git a/net/sctp/ipv6.c b/net/sctp/ipv6.c index c3e89c776e66..bd08807c9e44 100644 --- a/net/sctp/ipv6.c +++ b/net/sctp/ipv6.c @@ -664,8 +664,8 @@ static int sctp_v6_available(union sctp_addr *addr, struct sctp_sock *sp) if (!(type & IPV6_ADDR_UNICAST)) return 0; - return sp->inet.freebind || net->ipv6.sysctl.ip_nonlocal_bind || - ipv6_chk_addr(net, in6, NULL, 0); + return ipv6_can_nonlocal_bind(net, &sp->inet) || + ipv6_chk_addr(net, in6, NULL, 0); } /* This function checks if the address is a valid address to be used for @@ -954,8 +954,7 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr) net = sock_net(&opt->inet.sk); rcu_read_lock(); dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id); - if (!dev || !(opt->inet.freebind || - net->ipv6.sysctl.ip_nonlocal_bind || + if (!dev || !(ipv6_can_nonlocal_bind(net, &opt->inet) || ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0))) { rcu_read_unlock(); From 5e729bc54bda705f64941008b018b4e41a4322bf Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 31 Mar 2021 14:05:10 +0300 Subject: [PATCH 0694/1091] i2c: designware: Adjust bus_freq_hz when refuse high speed mode set When hardware doesn't support High Speed Mode, we forget bus_freq_hz timing adjustment. This makes the timings and real registers being unsynchronized. Adjust bus_freq_hz when refuse high speed mode set. Fixes: b6e67145f149 ("i2c: designware: Enable high speed mode") Reported-by: "Song Bao Hua (Barry Song)" Signed-off-by: Andy Shevchenko Reviewed-by: Barry Song Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-designware-master.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/i2c/busses/i2c-designware-master.c b/drivers/i2c/busses/i2c-designware-master.c index dd27b9dbe931..873ef38eb1c8 100644 --- a/drivers/i2c/busses/i2c-designware-master.c +++ b/drivers/i2c/busses/i2c-designware-master.c @@ -129,6 +129,7 @@ static int i2c_dw_set_timings_master(struct dw_i2c_dev *dev) if ((comp_param1 & DW_IC_COMP_PARAM_1_SPEED_MODE_MASK) != DW_IC_COMP_PARAM_1_SPEED_MODE_HIGH) { dev_err(dev->dev, "High Speed not supported!\n"); + t->bus_freq_hz = I2C_MAX_FAST_MODE_FREQ; dev->master_cfg &= ~DW_IC_CON_SPEED_MASK; dev->master_cfg |= DW_IC_CON_SPEED_FAST; dev->hs_hcnt = 0; From 9a6aaf61487e6d96ce0bf9b84a784c528dbf6e5e Mon Sep 17 00:00:00 2001 From: Salil Mehta Date: Mon, 5 Apr 2021 18:06:44 +0100 Subject: [PATCH 0695/1091] net: hns3: Remove the left over redundant check & assignment This removes the left over check and assignment which is no longer used anywhere in the function and should have been removed as part of the below mentioned patch. Fixes: 012fcb52f67c ("net: hns3: activate reset timer when calling reset_event") Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index e3f81c7e0ce7..58d210bbb311 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3966,7 +3966,6 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) * normalcy is to reset. * 2. A new reset request from the stack due to timeout * - * For the first case,error event might not have ae handle available. * check if this is a new reset request and we are not here just because * last reset attempt did not succeed and watchdog hit us again. We will * know this if last reset request did not occur very recently (watchdog @@ -3976,8 +3975,6 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) * want to make sure we throttle the reset request. Therefore, we will * not allow it again before 3*HZ times. */ - if (!handle) - handle = &hdev->vport[0].nic; if (time_before(jiffies, (hdev->last_reset_time + HCLGE_RESET_INTERVAL))) { From 0600771fa6b231e801ba1ff5d7adfcf7659dbbf3 Mon Sep 17 00:00:00 2001 From: Salil Mehta Date: Mon, 5 Apr 2021 18:06:45 +0100 Subject: [PATCH 0696/1091] net: hns3: Remove un-necessary 'else-if' in the hclge_reset_event() Code to defer the reset(which caps the frequency of the reset) schedules the timer and returns. Hence, following 'else-if' looks un-necessary. Fixes: 9de0b86f6444 ("net: hns3: Prevent to request reset frequently") Signed-off-by: Salil Mehta Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 58d210bbb311..2dd2af269b46 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -3980,7 +3980,9 @@ static void hclge_reset_event(struct pci_dev *pdev, struct hnae3_handle *handle) HCLGE_RESET_INTERVAL))) { mod_timer(&hdev->reset_timer, jiffies + HCLGE_RESET_INTERVAL); return; - } else if (hdev->default_reset_request) { + } + + if (hdev->default_reset_request) { hdev->reset_level = hclge_get_reset_level(ae_dev, &hdev->default_reset_request); From 08c27f3322fec11950b8f1384aa0f3b11d028528 Mon Sep 17 00:00:00 2001 From: Tetsuo Handa Date: Mon, 5 Apr 2021 19:16:50 +0900 Subject: [PATCH 0697/1091] batman-adv: initialize "struct batadv_tvlv_tt_vlan_data"->reserved field KMSAN found uninitialized value at batadv_tt_prepare_tvlv_local_data() [1], for commit ced72933a5e8ab52 ("batman-adv: use CRC32C instead of CRC16 in TT code") inserted 'reserved' field into "struct batadv_tvlv_tt_data" and commit 7ea7b4a142758dea ("batman-adv: make the TT CRC logic VLAN specific") moved that field to "struct batadv_tvlv_tt_vlan_data" but left that field uninitialized. [1] https://syzkaller.appspot.com/bug?id=07f3e6dba96f0eb3cabab986adcd8a58b9bdbe9d Reported-by: syzbot Tested-by: syzbot Signed-off-by: Tetsuo Handa Fixes: ced72933a5e8ab52 ("batman-adv: use CRC32C instead of CRC16 in TT code") Fixes: 7ea7b4a142758dea ("batman-adv: make the TT CRC logic VLAN specific") Acked-by: Sven Eckelmann Signed-off-by: David S. Miller --- net/batman-adv/translation-table.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/net/batman-adv/translation-table.c b/net/batman-adv/translation-table.c index f8761281aab0..434b4f042909 100644 --- a/net/batman-adv/translation-table.c +++ b/net/batman-adv/translation-table.c @@ -890,6 +890,7 @@ batadv_tt_prepare_tvlv_global_data(struct batadv_orig_node *orig_node, hlist_for_each_entry(vlan, &orig_node->vlan_list, list) { tt_vlan->vid = htons(vlan->vid); tt_vlan->crc = htonl(vlan->tt.crc); + tt_vlan->reserved = 0; tt_vlan++; } @@ -973,6 +974,7 @@ batadv_tt_prepare_tvlv_local_data(struct batadv_priv *bat_priv, tt_vlan->vid = htons(vlan->vid); tt_vlan->crc = htonl(vlan->tt.crc); + tt_vlan->reserved = 0; tt_vlan++; } From 65df7d1986a1909a0869419919e7d9c78d70407e Mon Sep 17 00:00:00 2001 From: Viswas G Date: Fri, 2 Apr 2021 11:12:12 +0530 Subject: [PATCH 0698/1091] scsi: pm80xx: Fix chip initialization failure Inbound and outbound queues were not properly configured and that lead to MPI configuration failure. Fixes: 05c6c029a44d ("scsi: pm80xx: Increase number of supported queues") Cc: stable@vger.kernel.org # 5.10+ Link: https://lore.kernel.org/r/20210402054212.17834-1-Viswas.G@microchip.com.com Reported-and-tested-by: Ash Izat Signed-off-by: Viswas G Signed-off-by: Martin K. Petersen --- drivers/scsi/pm8001/pm8001_hwi.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/scsi/pm8001/pm8001_hwi.c b/drivers/scsi/pm8001/pm8001_hwi.c index 49bf2f70a470..31e5455d280c 100644 --- a/drivers/scsi/pm8001/pm8001_hwi.c +++ b/drivers/scsi/pm8001/pm8001_hwi.c @@ -223,7 +223,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) PM8001_EVENT_LOG_SIZE; pm8001_ha->main_cfg_tbl.pm8001_tbl.iop_event_log_option = 0x01; pm8001_ha->main_cfg_tbl.pm8001_tbl.fatal_err_interrupt = 0x01; - for (i = 0; i < PM8001_MAX_INB_NUM; i++) { + for (i = 0; i < pm8001_ha->max_q_num; i++) { pm8001_ha->inbnd_q_tbl[i].element_pri_size_cnt = PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x00<<30); pm8001_ha->inbnd_q_tbl[i].upper_base_addr = @@ -249,7 +249,7 @@ static void init_default_table_values(struct pm8001_hba_info *pm8001_ha) pm8001_ha->inbnd_q_tbl[i].producer_idx = 0; pm8001_ha->inbnd_q_tbl[i].consumer_index = 0; } - for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) { + for (i = 0; i < pm8001_ha->max_q_num; i++) { pm8001_ha->outbnd_q_tbl[i].element_size_cnt = PM8001_MPI_QUEUE | (pm8001_ha->iomb_size << 16) | (0x01<<30); pm8001_ha->outbnd_q_tbl[i].upper_base_addr = @@ -671,9 +671,9 @@ static int pm8001_chip_init(struct pm8001_hba_info *pm8001_ha) read_outbnd_queue_table(pm8001_ha); /* update main config table ,inbound table and outbound table */ update_main_config_table(pm8001_ha); - for (i = 0; i < PM8001_MAX_INB_NUM; i++) + for (i = 0; i < pm8001_ha->max_q_num; i++) update_inbnd_queue_table(pm8001_ha, i); - for (i = 0; i < PM8001_MAX_OUTB_NUM; i++) + for (i = 0; i < pm8001_ha->max_q_num; i++) update_outbnd_queue_table(pm8001_ha, i); /* 8081 controller donot require these operations */ if (deviceid != 0x8081 && deviceid != 0x0042) { From 0352c3d3959a6cf543075b88c7e662fd3546f12e Mon Sep 17 00:00:00 2001 From: Roman Bolshakov Date: Sun, 4 Apr 2021 00:54:15 +0300 Subject: [PATCH 0699/1091] scsi: target: iscsi: Fix zero tag inside a trace event target_sequencer_start event is triggered inside target_cmd_init_cdb(). se_cmd.tag is not initialized with ITT at the moment so the event always prints zero tag. Link: https://lore.kernel.org/r/20210403215415.95077-1-r.bolshakov@yadro.com Cc: stable@vger.kernel.org # 5.10+ Reviewed-by: Mike Christie Signed-off-by: Roman Bolshakov Signed-off-by: Martin K. Petersen --- drivers/target/iscsi/iscsi_target.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/target/iscsi/iscsi_target.c b/drivers/target/iscsi/iscsi_target.c index d0e7ed8f28cc..e5c443bfbdf9 100644 --- a/drivers/target/iscsi/iscsi_target.c +++ b/drivers/target/iscsi/iscsi_target.c @@ -1166,6 +1166,7 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, target_get_sess_cmd(&cmd->se_cmd, true); + cmd->se_cmd.tag = (__force u32)cmd->init_task_tag; cmd->sense_reason = target_cmd_init_cdb(&cmd->se_cmd, hdr->cdb); if (cmd->sense_reason) { if (cmd->sense_reason == TCM_OUT_OF_RESOURCES) { @@ -1180,8 +1181,6 @@ int iscsit_setup_scsi_cmd(struct iscsi_conn *conn, struct iscsi_cmd *cmd, if (cmd->sense_reason) goto attach_cmd; - /* only used for printks or comparing with ->ref_task_tag */ - cmd->se_cmd.tag = (__force u32)cmd->init_task_tag; cmd->sense_reason = target_cmd_parse_cdb(&cmd->se_cmd); if (cmd->sense_reason) goto attach_cmd; From 5cd0f6f57639c5afbb36100c69281fee82c95ee7 Mon Sep 17 00:00:00 2001 From: Martin Wilck Date: Thu, 1 Apr 2021 11:11:05 +0200 Subject: [PATCH 0700/1091] scsi: scsi_transport_srp: Don't block target in SRP_PORT_LOST state rport_dev_loss_timedout() sets the rport state to SRP_PORT_LOST and the SCSI target state to SDEV_TRANSPORT_OFFLINE. If this races with srp_reconnect_work(), a warning is printed: Mar 27 18:48:07 ictm1604s01h4 kernel: dev_loss_tmo expired for SRP port-18:1 / host18. Mar 27 18:48:07 ictm1604s01h4 kernel: ------------[ cut here ]------------ Mar 27 18:48:07 ictm1604s01h4 kernel: scsi_internal_device_block(18:0:0:100) failed: ret = -22 Mar 27 18:48:07 ictm1604s01h4 kernel: Call Trace: Mar 27 18:48:07 ictm1604s01h4 kernel: ? scsi_target_unblock+0x50/0x50 [scsi_mod] Mar 27 18:48:07 ictm1604s01h4 kernel: starget_for_each_device+0x80/0xb0 [scsi_mod] Mar 27 18:48:07 ictm1604s01h4 kernel: target_block+0x24/0x30 [scsi_mod] Mar 27 18:48:07 ictm1604s01h4 kernel: device_for_each_child+0x57/0x90 Mar 27 18:48:07 ictm1604s01h4 kernel: srp_reconnect_rport+0xe4/0x230 [scsi_transport_srp] Mar 27 18:48:07 ictm1604s01h4 kernel: srp_reconnect_work+0x40/0xc0 [scsi_transport_srp] Avoid this by not trying to block targets for rports in SRP_PORT_LOST state. Link: https://lore.kernel.org/r/20210401091105.8046-1-mwilck@suse.com Reviewed-by: Bart Van Assche Signed-off-by: Martin Wilck Signed-off-by: Martin K. Petersen --- drivers/scsi/scsi_transport_srp.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/scsi/scsi_transport_srp.c b/drivers/scsi/scsi_transport_srp.c index 1e939a2a387f..98a34ed10f1a 100644 --- a/drivers/scsi/scsi_transport_srp.c +++ b/drivers/scsi/scsi_transport_srp.c @@ -541,7 +541,7 @@ int srp_reconnect_rport(struct srp_rport *rport) res = mutex_lock_interruptible(&rport->mutex); if (res) goto out; - if (rport->state != SRP_RPORT_FAIL_FAST) + if (rport->state != SRP_RPORT_FAIL_FAST && rport->state != SRP_RPORT_LOST) /* * sdev state must be SDEV_TRANSPORT_OFFLINE, transition * to SDEV_BLOCK is illegal. Calling scsi_target_unblock() From 4033e76a7abd102eaa84d7adc232f53b9da8709a Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Wed, 31 Mar 2021 09:28:50 +0800 Subject: [PATCH 0701/1091] parisc: Remove duplicate struct task_struct declaration struct task_struct is declared twice. One has been declared at 154th line. Remove the duplicate. Signed-off-by: Wan Jiabing Signed-off-by: Helge Deller --- arch/parisc/include/asm/processor.h | 1 - 1 file changed, 1 deletion(-) diff --git a/arch/parisc/include/asm/processor.h b/arch/parisc/include/asm/processor.h index 11ece0d07374..b5fbcd2c1780 100644 --- a/arch/parisc/include/asm/processor.h +++ b/arch/parisc/include/asm/processor.h @@ -272,7 +272,6 @@ on downward growing arches, it looks like this: regs->gr[23] = 0; \ } while(0) -struct task_struct; struct mm_struct; /* Free all resources held by a thread. */ From 9054284e8846b0105aad43a4e7174ca29fffbc44 Mon Sep 17 00:00:00 2001 From: Helge Deller Date: Tue, 6 Apr 2021 11:32:52 +0200 Subject: [PATCH 0702/1091] parisc: parisc-agp requires SBA IOMMU driver Add a dependency to the SBA IOMMU driver to avoid: ERROR: modpost: "sba_list" [drivers/char/agp/parisc-agp.ko] undefined! Reported-by: kernel test robot Cc: stable@vger.kernel.org Signed-off-by: Helge Deller --- drivers/char/agp/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/char/agp/Kconfig b/drivers/char/agp/Kconfig index a086dd34f932..4f501e4842ab 100644 --- a/drivers/char/agp/Kconfig +++ b/drivers/char/agp/Kconfig @@ -125,7 +125,7 @@ config AGP_HP_ZX1 config AGP_PARISC tristate "HP Quicksilver AGP support" - depends on AGP && PARISC && 64BIT + depends on AGP && PARISC && 64BIT && IOMMU_SBA help This option gives you AGP GART support for the HP Quicksilver AGP bus adapter on HP PA-RISC machines (Ok, just on the C8000 From 07cc40fec9a85e669ea12e161a438d2cbd76f1ed Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 26 Mar 2021 12:57:17 +0200 Subject: [PATCH 0703/1091] iwlwifi: fix 11ax disabled bit in the regulatory capability flags When version 2 of the regulatory capability flags API was implemented, the flag to disable 11ax was defined as bit 13, but this was later changed and the bit remained as bit 10, like in version 1. This was never changed in the driver, so we were checking for the wrong bit in newer devices. Fix it. Signed-off-by: Luca Coelho Fixes: e27c506a985c ("iwlwifi: regulatory: regulatory capabilities api change") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210326125611.6d28516b59cd.Id0248d5e4662695254f49ce37b0268834ed52918@changeid --- drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c index af684f80b0cc..c5a1e84dc1ab 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-nvm-parse.c @@ -232,7 +232,7 @@ enum iwl_reg_capa_flags_v2 { REG_CAPA_V2_MCS_9_ALLOWED = BIT(6), REG_CAPA_V2_WEATHER_DISABLED = BIT(7), REG_CAPA_V2_40MHZ_ALLOWED = BIT(8), - REG_CAPA_V2_11AX_DISABLED = BIT(13), + REG_CAPA_V2_11AX_DISABLED = BIT(10), }; /* From 25628bc08d4526d3673ca7d039eb636aa9006076 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Mar 2021 12:57:18 +0200 Subject: [PATCH 0704/1091] iwlwifi: pcie: properly set LTR workarounds on 22000 devices As the context info gen3 code is only called for >=AX210 devices (from iwl_trans_pcie_gen2_start_fw()) the code there to set LTR on 22000 devices cannot actually do anything (22000 < AX210). Fix this by moving the LTR code to iwl_trans_pcie_gen2_start_fw() where it can handle both devices. This then requires that we kick the firmware only after that rather than doing it from the context info code. Note that this again had a dead branch in gen3 code, which I've removed here. Signed-off-by: Johannes Berg Fixes: ed0022da8bd9 ("iwlwifi: pcie: set LTR on more devices") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210326125611.675486178ed1.Ib61463aba6920645059e366dcdca4c4c77f0ff58@changeid --- .../intel/iwlwifi/pcie/ctxt-info-gen3.c | 31 +--------------- .../wireless/intel/iwlwifi/pcie/ctxt-info.c | 3 +- .../wireless/intel/iwlwifi/pcie/trans-gen2.c | 35 +++++++++++++++++++ 3 files changed, 37 insertions(+), 32 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c index 8fba190e84cf..cecc32e7dbe8 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info-gen3.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -75,15 +75,6 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, const struct fw_img *fw) { struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans); - u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ | - u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, - CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) | - u32_encode_bits(250, - CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) | - CSR_LTR_LONG_VAL_AD_SNOOP_REQ | - u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, - CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) | - u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL); struct iwl_context_info_gen3 *ctxt_info_gen3; struct iwl_prph_scratch *prph_scratch; struct iwl_prph_scratch_ctrl_cfg *prph_sc_ctrl; @@ -217,26 +208,6 @@ int iwl_pcie_ctxt_info_gen3_init(struct iwl_trans *trans, iwl_set_bit(trans, CSR_CTXT_INFO_BOOT_CTRL, CSR_AUTO_FUNC_BOOT_ENA); - /* - * To workaround hardware latency issues during the boot process, - * initialize the LTR to ~250 usec (see ltr_val above). - * The firmware initializes this again later (to a smaller value). - */ - if ((trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210 || - trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) && - !trans->trans_cfg->integrated) { - iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val); - } else if (trans->trans_cfg->integrated && - trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) { - iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL); - iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val); - } - - if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) - iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); - else - iwl_set_bit(trans, CSR_GP_CNTRL, CSR_AUTO_FUNC_INIT); - return 0; err_free_ctxt_info: diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c index d1bb273d6b6d..74ce31fdf45e 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/ctxt-info.c @@ -1,7 +1,7 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* * Copyright (C) 2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #include "iwl-trans.h" #include "iwl-fh.h" @@ -240,7 +240,6 @@ int iwl_pcie_ctxt_info_init(struct iwl_trans *trans, /* kick FW self load */ iwl_write64(trans, CSR_CTXT_INFO_BA, trans_pcie->ctxt_info_dma_addr); - iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); /* Context info will be released upon alive or failure to get one */ diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c index 497ef3405da3..94ffc1ae484d 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/trans-gen2.c @@ -266,6 +266,34 @@ void iwl_trans_pcie_gen2_fw_alive(struct iwl_trans *trans, u32 scd_addr) mutex_unlock(&trans_pcie->mutex); } +static void iwl_pcie_set_ltr(struct iwl_trans *trans) +{ + u32 ltr_val = CSR_LTR_LONG_VAL_AD_NO_SNOOP_REQ | + u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, + CSR_LTR_LONG_VAL_AD_NO_SNOOP_SCALE) | + u32_encode_bits(250, + CSR_LTR_LONG_VAL_AD_NO_SNOOP_VAL) | + CSR_LTR_LONG_VAL_AD_SNOOP_REQ | + u32_encode_bits(CSR_LTR_LONG_VAL_AD_SCALE_USEC, + CSR_LTR_LONG_VAL_AD_SNOOP_SCALE) | + u32_encode_bits(250, CSR_LTR_LONG_VAL_AD_SNOOP_VAL); + + /* + * To workaround hardware latency issues during the boot process, + * initialize the LTR to ~250 usec (see ltr_val above). + * The firmware initializes this again later (to a smaller value). + */ + if ((trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_AX210 || + trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) && + !trans->trans_cfg->integrated) { + iwl_write32(trans, CSR_LTR_LONG_VAL_AD, ltr_val); + } else if (trans->trans_cfg->integrated && + trans->trans_cfg->device_family == IWL_DEVICE_FAMILY_22000) { + iwl_write_prph(trans, HPM_MAC_LTR_CSR, HPM_MAC_LRT_ENABLE_ALL); + iwl_write_prph(trans, HPM_UMAC_LTR, ltr_val); + } +} + int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, const struct fw_img *fw, bool run_in_rfkill) { @@ -332,6 +360,13 @@ int iwl_trans_pcie_gen2_start_fw(struct iwl_trans *trans, if (ret) goto out; + iwl_pcie_set_ltr(trans); + + if (trans->trans_cfg->device_family >= IWL_DEVICE_FAMILY_AX210) + iwl_write_umac_prph(trans, UREG_CPU_INIT_RUN, 1); + else + iwl_write_prph(trans, UREG_CPU_INIT_RUN, 1); + /* re-check RF-Kill state since we may have missed the interrupt */ hw_rfkill = iwl_pcie_check_hw_rf_kill(trans); if (hw_rfkill && !run_in_rfkill) From 97195d3cad852063208a1cd4f4d073459547a415 Mon Sep 17 00:00:00 2001 From: Matt Chen Date: Fri, 26 Mar 2021 12:57:19 +0200 Subject: [PATCH 0705/1091] iwlwifi: add support for Qu with AX201 device Add this specific Samsung AX201 sku to driver so it can be detected and initialized successfully. Signed-off-by: Matt Chen Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210326125611.30b622037714.Id9fd709cf1c8261c097bbfd7453f6476077dcafc@changeid --- drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index ffaf973dae94..4e2219b46db2 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -592,6 +592,7 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x4DF0, 0x1652, killer1650i_2ax_cfg_qu_b0_hr_b0, NULL), IWL_DEV_INFO(0x4DF0, 0x2074, iwl_ax201_cfg_qu_hr, NULL), IWL_DEV_INFO(0x4DF0, 0x4070, iwl_ax201_cfg_qu_hr, NULL), + IWL_DEV_INFO(0x4DF0, 0x6074, iwl_ax201_cfg_qu_hr, NULL), /* So with HR */ IWL_DEV_INFO(0x2725, 0x0090, iwlax211_2ax_cfg_so_gf_a0, NULL), From 9c04fd95fa830d60e5bdb08bcd7ff68d7e120e5b Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Mar 2021 12:57:20 +0200 Subject: [PATCH 0706/1091] iwlwifi: fw: fix notification wait locking Since we now call iwl_notification_wait_notify() from the NAPI poll in soft-IRQ, we get a (valid) lockdep complaint that we could get a deadlock by taking the spinlock from sleeping context and then getting the soft-IRQ that also tries to take it (in NAPI polling). Fix this by disabling soft-IRQs for this lock. Signed-off-by: Johannes Berg Fixes: 25edc8f259c7 ("iwlwifi: pcie: properly implement NAPI") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210326125611.c3b2e3d6b58b.Ic56f351d04674df70567bab0269cba91bdbc853c@changeid --- drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c b/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c index 3dbc6f3f92cc..231d2517f398 100644 --- a/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c +++ b/drivers/net/wireless/intel/iwlwifi/fw/notif-wait.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2005-2014 Intel Corporation + * Copyright (C) 2005-2014, 2021 Intel Corporation * Copyright (C) 2015-2017 Intel Deutschland GmbH */ #include @@ -26,7 +26,7 @@ bool iwl_notification_wait(struct iwl_notif_wait_data *notif_wait, if (!list_empty(¬if_wait->notif_waits)) { struct iwl_notification_wait *w; - spin_lock(¬if_wait->notif_wait_lock); + spin_lock_bh(¬if_wait->notif_wait_lock); list_for_each_entry(w, ¬if_wait->notif_waits, list) { int i; bool found = false; @@ -59,7 +59,7 @@ bool iwl_notification_wait(struct iwl_notif_wait_data *notif_wait, triggered = true; } } - spin_unlock(¬if_wait->notif_wait_lock); + spin_unlock_bh(¬if_wait->notif_wait_lock); } return triggered; @@ -70,10 +70,10 @@ void iwl_abort_notification_waits(struct iwl_notif_wait_data *notif_wait) { struct iwl_notification_wait *wait_entry; - spin_lock(¬if_wait->notif_wait_lock); + spin_lock_bh(¬if_wait->notif_wait_lock); list_for_each_entry(wait_entry, ¬if_wait->notif_waits, list) wait_entry->aborted = true; - spin_unlock(¬if_wait->notif_wait_lock); + spin_unlock_bh(¬if_wait->notif_wait_lock); wake_up_all(¬if_wait->notif_waitq); } From 08f4b0b1c07bcb70247931d81233fb9c59f50c35 Mon Sep 17 00:00:00 2001 From: Luca Coelho Date: Fri, 26 Mar 2021 12:57:21 +0200 Subject: [PATCH 0707/1091] iwlwifi: pcie: add support for So-F devices We have a new type of device that has a different MAC ID, but is otherwise identical to So devices. Add rules to match this new ID accordingly. Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210326125611.4feea3560def.I2b6ef794c2073a18779dd40fb53f8c942d1ab42d@changeid --- .../net/wireless/intel/iwlwifi/iwl-config.h | 1 + drivers/net/wireless/intel/iwlwifi/pcie/drv.c | 26 ++++++++++++++++++- 2 files changed, 26 insertions(+), 1 deletion(-) diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-config.h b/drivers/net/wireless/intel/iwlwifi/iwl-config.h index 75f99ff7f908..c4f5da76f1c0 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/intel/iwlwifi/iwl-config.h @@ -414,6 +414,7 @@ struct iwl_cfg { #define IWL_CFG_MAC_TYPE_QNJ 0x36 #define IWL_CFG_MAC_TYPE_SO 0x37 #define IWL_CFG_MAC_TYPE_SNJ 0x42 +#define IWL_CFG_MAC_TYPE_SOF 0x43 #define IWL_CFG_MAC_TYPE_MA 0x44 #define IWL_CFG_RF_TYPE_TH 0x105 diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 4e2219b46db2..558a0b2ef0fc 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -1041,7 +1041,31 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_CFG_MAC_TYPE_SO, IWL_CFG_ANY, IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, - iwl_cfg_so_a0_hr_a0, iwl_ax201_name) + iwl_cfg_so_a0_hr_a0, iwl_ax201_name), + +/* So-F with Hr */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, + IWL_CFG_NO_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_so_a0_hr_a0, iwl_ax203_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_HR1, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_so_a0_hr_a0, iwl_ax101_name), + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_HR2, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwl_cfg_so_a0_hr_a0, iwl_ax201_name), + +/* So-F with Gf */ + _IWL_DEV_INFO(IWL_CFG_ANY, IWL_CFG_ANY, + IWL_CFG_MAC_TYPE_SOF, IWL_CFG_ANY, + IWL_CFG_RF_TYPE_GF, IWL_CFG_ANY, + IWL_CFG_160, IWL_CFG_ANY, IWL_CFG_NO_CDB, + iwlax211_2ax_cfg_so_gf_a0, iwl_ax211_name), #endif /* CONFIG_IWLMVM */ }; From 39fb06f791429eaee8374ef12634c0fbf68a5a9f Mon Sep 17 00:00:00 2001 From: Gregory Greenman Date: Fri, 26 Mar 2021 12:57:22 +0200 Subject: [PATCH 0708/1091] iwlwifi: mvm: rfi: don't lock mvm->mutex when sending config command The mutex is already locked in iwl_mvm_mac_start. Signed-off-by: Gregory Greenman Fixes: 21254908cbe9 ("iwlwifi: mvm: add RFI-M support") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210326125611.703288ea058d.I82a0312389032d07c3b478bef3e938e06bfa7df6@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c | 7 +++++-- drivers/net/wireless/intel/iwlwifi/mvm/rfi.c | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c index 130760572262..34ddef97b099 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/debugfs.c @@ -1786,10 +1786,13 @@ static ssize_t iwl_dbgfs_rfi_freq_table_write(struct iwl_mvm *mvm, char *buf, return -EINVAL; /* value zero triggers re-sending the default table to the device */ - if (!op_id) + if (!op_id) { + mutex_lock(&mvm->mutex); ret = iwl_rfi_send_config_cmd(mvm, NULL); - else + mutex_unlock(&mvm->mutex); + } else { ret = -EOPNOTSUPP; /* in the future a new table will be added */ + } return ret ?: count; } diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c b/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c index 873919048143..0b818067067c 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rfi.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause /* - * Copyright (C) 2020 Intel Corporation + * Copyright (C) 2020 - 2021 Intel Corporation */ #include "mvm.h" @@ -66,6 +66,8 @@ int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_t if (!fw_has_capa(&mvm->fw->ucode_capa, IWL_UCODE_TLV_CAPA_RFIM_SUPPORT)) return -EOPNOTSUPP; + lockdep_assert_held(&mvm->mutex); + /* in case no table is passed, use the default one */ if (!rfi_table) { memcpy(cmd.table, iwl_rfi_table, sizeof(cmd.table)); @@ -75,9 +77,7 @@ int iwl_rfi_send_config_cmd(struct iwl_mvm *mvm, struct iwl_rfi_lut_entry *rfi_t cmd.oem = 1; } - mutex_lock(&mvm->mutex); ret = iwl_mvm_send_cmd(mvm, &hcmd); - mutex_unlock(&mvm->mutex); if (ret) IWL_ERR(mvm, "Failed to send RFI config cmd %d\n", ret); From 65db391dd874db42279713405f29f4ac93682d13 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 26 Mar 2021 12:57:23 +0200 Subject: [PATCH 0709/1091] iwlwifi: mvm: fix beacon protection checks Unfortunately, since beacon protection isn't fully available yet, we didn't notice that there are problems with it and that the replay detection isn't working correctly. We were relying only on mac80211, since iwl_mvm_rx_crypto() exits when !ieee80211_has_protected(), which is of course true for protected (but not encrypted) management frames. Fix this to properly detect protected (but not encrypted) management frames and handle them - we continue to only care about beacons since for others everything can and will be checked in mac80211. Signed-off-by: Johannes Berg Fixes: b1fdc2505abc ("iwlwifi: mvm: advertise BIGTK client support if available") Signed-off-by: Luca Coelho Signed-off-by: Kalle Valo Link: https://lore.kernel.org/r/iwlwifi.20210326125611.23c990843369.I09c262a8f6f9852cc8f513cdcb31a7f8f87dd8af@changeid --- drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c index c21736f80c29..af5a6dd81c41 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/rxmq.c @@ -272,10 +272,10 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, rx_status->chain_signal[2] = S8_MIN; } -static int iwl_mvm_rx_mgmt_crypto(struct ieee80211_sta *sta, - struct ieee80211_hdr *hdr, - struct iwl_rx_mpdu_desc *desc, - u32 status) +static int iwl_mvm_rx_mgmt_prot(struct ieee80211_sta *sta, + struct ieee80211_hdr *hdr, + struct iwl_rx_mpdu_desc *desc, + u32 status) { struct iwl_mvm_sta *mvmsta; struct iwl_mvm_vif *mvmvif; @@ -285,6 +285,9 @@ static int iwl_mvm_rx_mgmt_crypto(struct ieee80211_sta *sta, u32 len = le16_to_cpu(desc->mpdu_len); const u8 *frame = (void *)hdr; + if ((status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE) + return 0; + /* * For non-beacon, we don't really care. But beacons may * be filtered out, and we thus need the firmware's replay @@ -356,6 +359,10 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta, IWL_RX_MPDU_STATUS_SEC_UNKNOWN && !mvm->monitor_on) return -1; + if (unlikely(ieee80211_is_mgmt(hdr->frame_control) && + !ieee80211_has_protected(hdr->frame_control))) + return iwl_mvm_rx_mgmt_prot(sta, hdr, desc, status); + if (!ieee80211_has_protected(hdr->frame_control) || (status & IWL_RX_MPDU_STATUS_SEC_MASK) == IWL_RX_MPDU_STATUS_SEC_NONE) @@ -411,7 +418,7 @@ static int iwl_mvm_rx_crypto(struct iwl_mvm *mvm, struct ieee80211_sta *sta, stats->flag |= RX_FLAG_DECRYPTED; return 0; case RX_MPDU_RES_STATUS_SEC_CMAC_GMAC_ENC: - return iwl_mvm_rx_mgmt_crypto(sta, hdr, desc, status); + break; default: /* * Sometimes we can get frames that were not decrypted From 617085fca6375e2c1667d1fbfc6adc4034c85f04 Mon Sep 17 00:00:00 2001 From: Marc Kleine-Budde Date: Tue, 30 Mar 2021 11:46:07 +0200 Subject: [PATCH 0710/1091] can: mcp251x: fix support for half duplex SPI host controllers Some SPI host controllers do not support full-duplex SPI transfers. The function mcp251x_spi_trans() does a full duplex transfer. It is used in several places in the driver, where a TX half duplex transfer is sufficient. To fix support for half duplex SPI host controllers, this patch introduces a new function mcp251x_spi_write() and changes all callers that do a TX half duplex transfer to use mcp251x_spi_write(). Fixes: e0e25001d088 ("can: mcp251x: add support for half duplex controllers") Link: https://lore.kernel.org/r/20210330100246.1074375-1-mkl@pengutronix.de Cc: Tim Harvey Tested-By: Tim Harvey Reported-by: Gerhard Bertelsmann Signed-off-by: Marc Kleine-Budde --- drivers/net/can/spi/mcp251x.c | 24 ++++++++++++++++++------ 1 file changed, 18 insertions(+), 6 deletions(-) diff --git a/drivers/net/can/spi/mcp251x.c b/drivers/net/can/spi/mcp251x.c index f69fb4238a65..a57da43680d8 100644 --- a/drivers/net/can/spi/mcp251x.c +++ b/drivers/net/can/spi/mcp251x.c @@ -314,6 +314,18 @@ static int mcp251x_spi_trans(struct spi_device *spi, int len) return ret; } +static int mcp251x_spi_write(struct spi_device *spi, int len) +{ + struct mcp251x_priv *priv = spi_get_drvdata(spi); + int ret; + + ret = spi_write(spi, priv->spi_tx_buf, len); + if (ret) + dev_err(&spi->dev, "spi write failed: ret = %d\n", ret); + + return ret; +} + static u8 mcp251x_read_reg(struct spi_device *spi, u8 reg) { struct mcp251x_priv *priv = spi_get_drvdata(spi); @@ -361,7 +373,7 @@ static void mcp251x_write_reg(struct spi_device *spi, u8 reg, u8 val) priv->spi_tx_buf[1] = reg; priv->spi_tx_buf[2] = val; - mcp251x_spi_trans(spi, 3); + mcp251x_spi_write(spi, 3); } static void mcp251x_write_2regs(struct spi_device *spi, u8 reg, u8 v1, u8 v2) @@ -373,7 +385,7 @@ static void mcp251x_write_2regs(struct spi_device *spi, u8 reg, u8 v1, u8 v2) priv->spi_tx_buf[2] = v1; priv->spi_tx_buf[3] = v2; - mcp251x_spi_trans(spi, 4); + mcp251x_spi_write(spi, 4); } static void mcp251x_write_bits(struct spi_device *spi, u8 reg, @@ -386,7 +398,7 @@ static void mcp251x_write_bits(struct spi_device *spi, u8 reg, priv->spi_tx_buf[2] = mask; priv->spi_tx_buf[3] = val; - mcp251x_spi_trans(spi, 4); + mcp251x_spi_write(spi, 4); } static u8 mcp251x_read_stat(struct spi_device *spi) @@ -618,7 +630,7 @@ static void mcp251x_hw_tx_frame(struct spi_device *spi, u8 *buf, buf[i]); } else { memcpy(priv->spi_tx_buf, buf, TXBDAT_OFF + len); - mcp251x_spi_trans(spi, TXBDAT_OFF + len); + mcp251x_spi_write(spi, TXBDAT_OFF + len); } } @@ -650,7 +662,7 @@ static void mcp251x_hw_tx(struct spi_device *spi, struct can_frame *frame, /* use INSTRUCTION_RTS, to avoid "repeated frame problem" */ priv->spi_tx_buf[0] = INSTRUCTION_RTS(1 << tx_buf_idx); - mcp251x_spi_trans(priv->spi, 1); + mcp251x_spi_write(priv->spi, 1); } static void mcp251x_hw_rx_frame(struct spi_device *spi, u8 *buf, @@ -888,7 +900,7 @@ static int mcp251x_hw_reset(struct spi_device *spi) mdelay(MCP251X_OST_DELAY_MS); priv->spi_tx_buf[0] = INSTRUCTION_RESET; - ret = mcp251x_spi_trans(spi, 1); + ret = mcp251x_spi_write(spi, 1); if (ret) return ret; From 4d752e5af63753ab5140fc282929b98eaa4bd12e Mon Sep 17 00:00:00 2001 From: Gao Xiang Date: Tue, 6 Apr 2021 12:59:29 +0800 Subject: [PATCH 0711/1091] parisc: avoid a warning on u8 cast for cmpxchg on u8 pointers commit b344d6a83d01 ("parisc: add support for cmpxchg on u8 pointers") can generate a sparse warning ("cast truncates bits from constant value"), which has been reported several times [1] [2] [3]. The original code worked as expected, but anyway, let silence such sparse warning as what others did [4]. [1] https://lore.kernel.org/r/202104061220.nRMBwCXw-lkp@intel.com [2] https://lore.kernel.org/r/202012291914.T5Agcn99-lkp@intel.com [3] https://lore.kernel.org/r/202008210829.KVwn7Xeh%25lkp@intel.com [4] https://lore.kernel.org/r/20210315131512.133720-2-jacopo+renesas@jmondi.org Cc: Liam Beguin Cc: Helge Deller Cc: stable@vger.kernel.org # v5.8+ Signed-off-by: Gao Xiang Signed-off-by: Helge Deller --- arch/parisc/include/asm/cmpxchg.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/parisc/include/asm/cmpxchg.h b/arch/parisc/include/asm/cmpxchg.h index cf5ee9b0b393..84ee232278a6 100644 --- a/arch/parisc/include/asm/cmpxchg.h +++ b/arch/parisc/include/asm/cmpxchg.h @@ -72,7 +72,7 @@ __cmpxchg(volatile void *ptr, unsigned long old, unsigned long new_, int size) #endif case 4: return __cmpxchg_u32((unsigned int *)ptr, (unsigned int)old, (unsigned int)new_); - case 1: return __cmpxchg_u8((u8 *)ptr, (u8)old, (u8)new_); + case 1: return __cmpxchg_u8((u8 *)ptr, old & 0xff, new_ & 0xff); } __cmpxchg_called_with_bad_pointer(); return old; From 0aa2ddc9af44bf9032098a587aeabada4da181a7 Mon Sep 17 00:00:00 2001 From: Bhaskar Chowdhury Date: Thu, 18 Mar 2021 00:54:27 +0530 Subject: [PATCH 0712/1091] parisc: math-emu: Few spelling fixes in the file fpu.h with some additional cleanups by Helge. Signed-off-by: Bhaskar Chowdhury Acked-by: Randy Dunlap Signed-off-by: Helge Deller --- arch/parisc/math-emu/fpu.h | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/arch/parisc/math-emu/fpu.h b/arch/parisc/math-emu/fpu.h index 853c19c03828..dec951d40286 100644 --- a/arch/parisc/math-emu/fpu.h +++ b/arch/parisc/math-emu/fpu.h @@ -5,34 +5,10 @@ * Floating-point emulation code * Copyright (C) 2001 Hewlett-Packard (Paul Bame) */ -/* - * BEGIN_DESC - * - * File: - * @(#) pa/fp/fpu.h $Revision: 1.1 $ - * - * Purpose: - * <> - * - * - * END_DESC -*/ - -#ifdef __NO_PA_HDRS - PA header file -- do not include this header file for non-PA builds. -#endif - #ifndef _MACHINE_FPU_INCLUDED /* allows multiple inclusion */ #define _MACHINE_FPU_INCLUDED -#if 0 -#ifndef _SYS_STDSYMS_INCLUDED -# include -#endif /* _SYS_STDSYMS_INCLUDED */ -#include -#endif - #define PA83_FPU_FLAG 0x00000001 #define PA89_FPU_FLAG 0x00000002 #define PA2_0_FPU_FLAG 0x00000010 @@ -43,21 +19,19 @@ #define COPR_FP 0x00000080 /* Floating point -- Coprocessor 0 */ #define SFU_MPY_DIVIDE 0x00008000 /* Multiply/Divide __ SFU 0 */ - #define EM_FPU_TYPE_OFFSET 272 /* version of EMULATION software for COPR,0,0 instruction */ #define EMULATION_VERSION 4 /* - * The only was to differeniate between TIMEX and ROLEX (or PCX-S and PCX-T) - * is thorough the potential type field from the PDC_MODEL call. The - * following flags are used at assist this differeniation. + * The only way to differentiate between TIMEX and ROLEX (or PCX-S and PCX-T) + * is through the potential type field from the PDC_MODEL call. + * The following flags are used to assist this differentiation. */ #define ROLEX_POTENTIAL_KEY_FLAGS PDC_MODEL_CPU_KEY_WORD_TO_IO #define TIMEX_POTENTIAL_KEY_FLAGS (PDC_MODEL_CPU_KEY_QUAD_STORE | \ PDC_MODEL_CPU_KEY_RECIP_SQRT) - #endif /* ! _MACHINE_FPU_INCLUDED */ From 3b943360a20f3e4b2e0133c7cd7138b51fd93de6 Mon Sep 17 00:00:00 2001 From: Sebastian Reichel Date: Sat, 27 Feb 2021 22:45:42 +0100 Subject: [PATCH 0713/1091] drm/panel: panel-dsi-cm: disable TE for now Disable TE for Droid 4 panel, since implementation is currently broken. Also disable it for N950 panel, which is untested. Reported-by: Tony Lindgren Reported-by: Tomi Valkeinen Fixes: 4c1b935fea54 ("drm/omap: dsi: move TE GPIO handling into core") Signed-off-by: Sebastian Reichel Tested-by: Tony Lindgren Acked-by: Thierry Reding Signed-off-by: Tomi Valkeinen Link: https://patchwork.freedesktop.org/patch/msgid/20210227214542.99961-1-sebastian.reichel@collabora.com --- drivers/gpu/drm/panel/panel-dsi-cm.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/gpu/drm/panel/panel-dsi-cm.c b/drivers/gpu/drm/panel/panel-dsi-cm.c index af381d756ac1..5fbfb71ca3d9 100644 --- a/drivers/gpu/drm/panel/panel-dsi-cm.c +++ b/drivers/gpu/drm/panel/panel-dsi-cm.c @@ -37,6 +37,7 @@ struct dsic_panel_data { u32 height_mm; u32 max_hs_rate; u32 max_lp_rate; + bool te_support; }; struct panel_drv_data { @@ -334,9 +335,11 @@ static int dsicm_power_on(struct panel_drv_data *ddata) if (r) goto err; - r = mipi_dsi_dcs_set_tear_on(ddata->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); - if (r) - goto err; + if (ddata->panel_data->te_support) { + r = mipi_dsi_dcs_set_tear_on(ddata->dsi, MIPI_DSI_DCS_TEAR_MODE_VBLANK); + if (r) + goto err; + } /* possible panel bug */ msleep(100); @@ -619,6 +622,7 @@ static const struct dsic_panel_data taal_data = { .height_mm = 0, .max_hs_rate = 300000000, .max_lp_rate = 10000000, + .te_support = true, }; static const struct dsic_panel_data himalaya_data = { @@ -629,6 +633,7 @@ static const struct dsic_panel_data himalaya_data = { .height_mm = 88, .max_hs_rate = 300000000, .max_lp_rate = 10000000, + .te_support = false, }; static const struct dsic_panel_data droid4_data = { @@ -639,6 +644,7 @@ static const struct dsic_panel_data droid4_data = { .height_mm = 89, .max_hs_rate = 300000000, .max_lp_rate = 10000000, + .te_support = false, }; static const struct of_device_id dsicm_of_match[] = { From 29654ed8384e9dbaf4cfba689dbcb664a6ab4bb7 Mon Sep 17 00:00:00 2001 From: Annaliese McDermond Date: Wed, 31 Mar 2021 18:21:45 +0000 Subject: [PATCH 0714/1091] ASoC: tlv320aic32x4: Increase maximum register in regmap AIC32X4_REFPOWERUP was added as a register, but the maximum register value in the regmap and regmap range was not correspondingly increased. This caused an error when this register was attempted to be written. Fixes: ec96690de82c ("ASoC: tlv320aic32x4: Enable fast charge") Cc: stable@vger.kernel.org Signed-off-by: Annaliese McDermond Link: https://lore.kernel.org/r/0101017889851cab-ce60cfdb-d88c-43d8-bbd2-7fbf34a0c912-000000@us-west-2.amazonses.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index f04f88c8d425..1ac3b3b12dc6 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -577,12 +577,12 @@ static const struct regmap_range_cfg aic32x4_regmap_pages[] = { .window_start = 0, .window_len = 128, .range_min = 0, - .range_max = AIC32X4_RMICPGAVOL, + .range_max = AIC32X4_REFPOWERUP, }, }; const struct regmap_config aic32x4_regmap_config = { - .max_register = AIC32X4_RMICPGAVOL, + .max_register = AIC32X4_REFPOWERUP, .ranges = aic32x4_regmap_pages, .num_ranges = ARRAY_SIZE(aic32x4_regmap_pages), }; From 1ca1156cfd69530e6b7cb99943baf90c8bd871a5 Mon Sep 17 00:00:00 2001 From: Annaliese McDermond Date: Wed, 31 Mar 2021 18:21:38 +0000 Subject: [PATCH 0715/1091] ASoC: tlv320aic32x4: Register clocks before registering component Clock registration must be performed before the component is registered. aic32x4_component_probe attempts to get all the clocks right off the bat. If the component is registered before the clocks there is a race condition where the clocks may not be registered by the time aic32x4_componet_probe actually runs. Fixes: d1c859d314d8 ("ASoC: codec: tlv3204: Increased maximum supported channels") Cc: stable@vger.kernel.org Signed-off-by: Annaliese McDermond Link: https://lore.kernel.org/r/0101017889850206-dcac4cce-8cc8-4a21-80e9-4e4bef44b981-000000@us-west-2.amazonses.com Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic32x4.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/tlv320aic32x4.c b/sound/soc/codecs/tlv320aic32x4.c index 1ac3b3b12dc6..b689f26fc4be 100644 --- a/sound/soc/codecs/tlv320aic32x4.c +++ b/sound/soc/codecs/tlv320aic32x4.c @@ -1243,6 +1243,10 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) if (ret) goto err_disable_regulators; + ret = aic32x4_register_clocks(dev, aic32x4->mclk_name); + if (ret) + goto err_disable_regulators; + ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic32x4, &aic32x4_dai, 1); if (ret) { @@ -1250,10 +1254,6 @@ int aic32x4_probe(struct device *dev, struct regmap *regmap) goto err_disable_regulators; } - ret = aic32x4_register_clocks(dev, aic32x4->mclk_name); - if (ret) - goto err_disable_regulators; - return 0; err_disable_regulators: From c7c19ec098b862a688291f5a1101f7de6e4b0a6c Mon Sep 17 00:00:00 2001 From: Vamshi Krishna Gopal Date: Mon, 5 Apr 2021 18:18:34 +0530 Subject: [PATCH 0716/1091] ASoC: Intel: kbl: Add MST route change to kbl machine drivers To support MST hdmi audio, modify the current routes to be based on port in kbl_da7219_max98357a, kbl_da7219_max98927 & kbl_rt5663_max98927. Signed-off-by: Vamshi Krishna Gopal Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210405124835.71247-2-vamshi.krishna.gopal@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_da7219_max98357a.c | 10 ++++++---- sound/soc/intel/boards/kbl_da7219_max98927.c | 10 ++++++---- sound/soc/intel/boards/kbl_rt5663_max98927.c | 14 ++++++++++---- 3 files changed, 22 insertions(+), 12 deletions(-) diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index dc3d897ad280..0e689ec7e11b 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -90,8 +90,9 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = { SND_SOC_DAPM_MIC("Headset Mic", NULL), SND_SOC_DAPM_SPK("Spk", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("DP", NULL), - SND_SOC_DAPM_SPK("HDMI", NULL), + SND_SOC_DAPM_SPK("HDMI1", NULL), + SND_SOC_DAPM_SPK("HDMI2", NULL), + SND_SOC_DAPM_SPK("HDMI3", NULL), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -108,8 +109,9 @@ static const struct snd_soc_dapm_route kabylake_map[] = { { "MIC", NULL, "Headset Mic" }, { "DMic", NULL, "SoC DMIC" }, - { "HDMI", NULL, "hif5 Output" }, - { "DP", NULL, "hif6 Output" }, + {"HDMI1", NULL, "hif5-0 Output"}, + {"HDMI2", NULL, "hif6-0 Output"}, + {"HDMI3", NULL, "hif7-0 Output"}, /* CODEC BE connections */ { "HiFi Playback", NULL, "ssp0 Tx" }, diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index cc9a2509ace2..9dfe5bd9180d 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -111,8 +111,9 @@ static const struct snd_soc_dapm_widget kabylake_widgets[] = { SND_SOC_DAPM_SPK("Left Spk", NULL), SND_SOC_DAPM_SPK("Right Spk", NULL), SND_SOC_DAPM_MIC("SoC DMIC", NULL), - SND_SOC_DAPM_SPK("DP", NULL), - SND_SOC_DAPM_SPK("HDMI", NULL), + SND_SOC_DAPM_SPK("HDMI1", NULL), + SND_SOC_DAPM_SPK("HDMI2", NULL), + SND_SOC_DAPM_SPK("HDMI3", NULL), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -126,8 +127,9 @@ static const struct snd_soc_dapm_route kabylake_map[] = { /* other jacks */ { "DMic", NULL, "SoC DMIC" }, - { "HDMI", NULL, "hif5 Output" }, - { "DP", NULL, "hif6 Output" }, + {"HDMI1", NULL, "hif5-0 Output"}, + {"HDMI2", NULL, "hif6-0 Output"}, + {"HDMI3", NULL, "hif7-0 Output"}, /* CODEC BE connections */ { "Left HiFi Playback", NULL, "ssp0 Tx" }, diff --git a/sound/soc/intel/boards/kbl_rt5663_max98927.c b/sound/soc/intel/boards/kbl_rt5663_max98927.c index 9a4b3d0973f6..a3de55a3b58d 100644 --- a/sound/soc/intel/boards/kbl_rt5663_max98927.c +++ b/sound/soc/intel/boards/kbl_rt5663_max98927.c @@ -151,6 +151,10 @@ static const struct snd_soc_dapm_route kabylake_map[] = { { "IN1N", NULL, "Headset Mic" }, { "DMic", NULL, "SoC DMIC" }, + {"HDMI1", NULL, "hif5-0 Output"}, + {"HDMI2", NULL, "hif6-0 Output"}, + {"HDMI3", NULL, "hif7-0 Output"}, + /* CODEC BE connections */ { "Left HiFi Playback", NULL, "ssp0 Tx" }, { "Right HiFi Playback", NULL, "ssp0 Tx" }, @@ -194,8 +198,9 @@ static const struct snd_kcontrol_new kabylake_5663_controls[] = { static const struct snd_soc_dapm_widget kabylake_5663_widgets[] = { SND_SOC_DAPM_HP("Headphone Jack", NULL), SND_SOC_DAPM_MIC("Headset Mic", NULL), - SND_SOC_DAPM_SPK("DP", NULL), - SND_SOC_DAPM_SPK("HDMI", NULL), + SND_SOC_DAPM_SPK("HDMI1", NULL), + SND_SOC_DAPM_SPK("HDMI2", NULL), + SND_SOC_DAPM_SPK("HDMI3", NULL), SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0, platform_clock_control, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMD), @@ -211,8 +216,9 @@ static const struct snd_soc_dapm_route kabylake_5663_map[] = { { "IN1P", NULL, "Headset Mic" }, { "IN1N", NULL, "Headset Mic" }, - { "HDMI", NULL, "hif5 Output" }, - { "DP", NULL, "hif6 Output" }, + {"HDMI1", NULL, "hif5-0 Output"}, + {"HDMI2", NULL, "hif6-0 Output"}, + {"HDMI3", NULL, "hif7-0 Output"}, /* CODEC BE connections */ { "AIF Playback", NULL, "ssp1 Tx" }, From 74ed9e9bfb7343b0a6710b651df66f3d68551110 Mon Sep 17 00:00:00 2001 From: Mac Chiang Date: Mon, 5 Apr 2021 18:18:35 +0530 Subject: [PATCH 0717/1091] ASoc: Intel: board: add BE DAI link for WoV create dai link in kbl_da7219_max98357a driver for wake on voice functionality. changes picked from broonie's tree commit 0c7941a63a0f ("ASoC: Intel: Skylake: Use refcap device for mono recording") commit 2154be362c90 ("ASoc: Intel: boards: Add WOV as sink for nau88l25_ssm4567 machine") Signed-off-by: Mac Chiang Signed-off-by: Vamshi Krishna Gopal Tested-by: Kaiyen Chang Tested-by: luke yang Tested-by: Grace Kao Tested-by: Kaiyen Chang Reviewed-by: Cheng-Yi Chiang Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210405124835.71247-3-vamshi.krishna.gopal@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_da7219_max98357a.c | 48 +++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/sound/soc/intel/boards/kbl_da7219_max98357a.c b/sound/soc/intel/boards/kbl_da7219_max98357a.c index 0e689ec7e11b..c0d8a73c6d21 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98357a.c +++ b/sound/soc/intel/boards/kbl_da7219_max98357a.c @@ -44,6 +44,7 @@ struct kbl_codec_private { enum { KBL_DPCM_AUDIO_PB = 0, KBL_DPCM_AUDIO_CP, + KBL_DPCM_AUDIO_REF_CP, KBL_DPCM_AUDIO_DMIC_CP, KBL_DPCM_AUDIO_HDMI1_PB, KBL_DPCM_AUDIO_HDMI2_PB, @@ -338,12 +339,49 @@ static struct snd_soc_ops kabylake_dmic_ops = { .startup = kabylake_dmic_startup, }; +static unsigned int rates_16000[] = { + 16000, +}; + +static const struct snd_pcm_hw_constraint_list constraints_16000 = { + .count = ARRAY_SIZE(rates_16000), + .list = rates_16000, +}; + +static const unsigned int ch_mono[] = { + 1, +}; + +static const struct snd_pcm_hw_constraint_list constraints_refcap = { + .count = ARRAY_SIZE(ch_mono), + .list = ch_mono, +}; + +static int kabylake_refcap_startup(struct snd_pcm_substream *substream) +{ + substream->runtime->hw.channels_max = 1; + snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_CHANNELS, + &constraints_refcap); + + return snd_pcm_hw_constraint_list(substream->runtime, 0, + SNDRV_PCM_HW_PARAM_RATE, + &constraints_16000); +} + +static struct snd_soc_ops skylake_refcap_ops = { + .startup = kabylake_refcap_startup, +}; + SND_SOC_DAILINK_DEF(dummy, DAILINK_COMP_ARRAY(COMP_DUMMY())); SND_SOC_DAILINK_DEF(system, DAILINK_COMP_ARRAY(COMP_CPU("System Pin"))); +SND_SOC_DAILINK_DEF(reference, + DAILINK_COMP_ARRAY(COMP_CPU("Reference Pin"))); + SND_SOC_DAILINK_DEF(dmic, DAILINK_COMP_ARRAY(COMP_CPU("DMIC Pin"))); @@ -418,6 +456,16 @@ static struct snd_soc_dai_link kabylake_dais[] = { .ops = &kabylake_da7219_fe_ops, SND_SOC_DAILINK_REG(system, dummy, platform), }, + [KBL_DPCM_AUDIO_REF_CP] = { + .name = "Kbl Audio Reference cap", + .stream_name = "Wake on Voice", + .init = NULL, + .dpcm_capture = 1, + .nonatomic = 1, + .dynamic = 1, + .ops = &skylake_refcap_ops, + SND_SOC_DAILINK_REG(reference, dummy, platform), + }, [KBL_DPCM_AUDIO_DMIC_CP] = { .name = "Kbl Audio DMIC cap", .stream_name = "dmiccap", From a43508995a913893c5f303e56415d06432b15619 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Sat, 3 Apr 2021 21:59:25 +0800 Subject: [PATCH 0718/1091] ASoC: ak5558: Fix s/show/slow/ typo s/show/slow/ Fixes: 920884777480 ("ASoC: ak5558: Add support for AK5558 ADC driver") Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1617458365-23393-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 3ac62a281807..8e4dca753f0b 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -75,8 +75,8 @@ static const struct soc_enum ak5552_mono_enum[] = { }; static const char * const digfil_texts[] = { - "Sharp Roll-Off", "Show Roll-Off", - "Short Delay Sharp Roll-Off", "Short Delay Show Roll-Off", + "Sharp Roll-Off", "Slow Roll-Off", + "Short Delay Sharp Roll-Off", "Short Delay Slow Roll-Off", }; static const struct soc_enum ak5558_adcset_enum[] = { From e5870bd0e40c749fd96a4e565497c789bee456bf Mon Sep 17 00:00:00 2001 From: Steve Lee Date: Mon, 5 Apr 2021 23:38:01 +0900 Subject: [PATCH 0719/1091] ASoC: max98390: Add support for tx slot configuration. Update voltage/current tx slot configuration support. Signed-off-by: Steve Lee Link: https://lore.kernel.org/r/20210405143801.29770-1-steves.lee@maximintegrated.com Signed-off-by: Mark Brown --- sound/soc/codecs/max98390.c | 62 +++++++++++++++++++++++++++++++++++++ sound/soc/codecs/max98390.h | 2 ++ 2 files changed, 64 insertions(+) diff --git a/sound/soc/codecs/max98390.c b/sound/soc/codecs/max98390.c index bb736c44e68a..94773ccee9d5 100644 --- a/sound/soc/codecs/max98390.c +++ b/sound/soc/codecs/max98390.c @@ -856,6 +856,48 @@ static void max98390_init_regs(struct snd_soc_component *component) regmap_write(max98390->regmap, MAX98390_ENV_TRACK_VOUT_HEADROOM, 0x0e); regmap_write(max98390->regmap, MAX98390_BOOST_BYPASS1, 0x46); regmap_write(max98390->regmap, MAX98390_FET_SCALING3, 0x03); + + /* voltage, current slot configuration */ + regmap_write(max98390->regmap, + MAX98390_PCM_CH_SRC_2, + (max98390->i_l_slot << 4 | + max98390->v_l_slot)&0xFF); + + if (max98390->v_l_slot < 8) { + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_HIZ_CTRL_A, + 1 << max98390->v_l_slot, 0); + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_EN_A, + 1 << max98390->v_l_slot, + 1 << max98390->v_l_slot); + } else { + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_HIZ_CTRL_B, + 1 << (max98390->v_l_slot - 8), 0); + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_EN_B, + 1 << (max98390->v_l_slot - 8), + 1 << (max98390->v_l_slot - 8)); + } + + if (max98390->i_l_slot < 8) { + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_HIZ_CTRL_A, + 1 << max98390->i_l_slot, 0); + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_EN_A, + 1 << max98390->i_l_slot, + 1 << max98390->i_l_slot); + } else { + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_HIZ_CTRL_B, + 1 << (max98390->i_l_slot - 8), 0); + regmap_update_bits(max98390->regmap, + MAX98390_PCM_TX_EN_B, + 1 << (max98390->i_l_slot - 8), + 1 << (max98390->i_l_slot - 8)); + } } static int max98390_probe(struct snd_soc_component *component) @@ -946,6 +988,23 @@ static const struct regmap_config max98390_regmap = { .cache_type = REGCACHE_RBTREE, }; +static void max98390_slot_config(struct i2c_client *i2c, + struct max98390_priv *max98390) +{ + int value; + struct device *dev = &i2c->dev; + + if (!device_property_read_u32(dev, "maxim,vmon-slot-no", &value)) + max98390->v_l_slot = value & 0xF; + else + max98390->v_l_slot = 0; + + if (!device_property_read_u32(dev, "maxim,imon-slot-no", &value)) + max98390->i_l_slot = value & 0xF; + else + max98390->i_l_slot = 1; +} + static int max98390_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) { @@ -988,6 +1047,9 @@ static int max98390_i2c_probe(struct i2c_client *i2c, __func__, max98390->ref_rdc_value, max98390->ambient_temp_value); + /* voltage/current slot configuration */ + max98390_slot_config(i2c, max98390); + /* regmap initialization */ max98390->regmap = devm_regmap_init_i2c(i2c, &max98390_regmap); if (IS_ERR(max98390->regmap)) { diff --git a/sound/soc/codecs/max98390.h b/sound/soc/codecs/max98390.h index dff884f68e3e..e31516717d3b 100644 --- a/sound/soc/codecs/max98390.h +++ b/sound/soc/codecs/max98390.h @@ -658,6 +658,8 @@ struct max98390_priv { unsigned int sysclk; unsigned int master; unsigned int tdm_mode; + unsigned int v_l_slot; + unsigned int i_l_slot; unsigned int ref_rdc_value; unsigned int ambient_temp_value; }; From 7d01ef7585c07afaf487759a48486228cd065726 Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Apr 2021 12:33:07 -0400 Subject: [PATCH 0720/1091] Make sure nd->path.mnt and nd->path.dentry are always valid pointers Initialize them in set_nameidata() and make sure that terminate_walk() clears them once the pointers become potentially invalid (i.e. we leave RCU mode or drop them in non-RCU one). Currently we have "path_init() always initializes them and nobody accesses them outside of path_init()/terminate_walk() segments", which is asking for trouble. With that change we would have nd->path.{mnt,dentry} 1) always valid - NULL or pointing to currently allocated objects. 2) non-NULL while we are successfully walking 3) NULL when we are not walking at all 4) contributing to refcounts whenever non-NULL outside of RCU mode. Fixes: 6c6ec2b0a3e0 ("fs: add support for LOOKUP_CACHED") Reported-by: syzbot+c88a7030da47945a3cc3@syzkaller.appspotmail.com Tested-by: Christian Brauner Signed-off-by: Al Viro --- fs/namei.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index 216f16e74351..fc8760d4314e 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -579,6 +579,8 @@ static void set_nameidata(struct nameidata *p, int dfd, struct filename *name) p->stack = p->internal; p->dfd = dfd; p->name = name; + p->path.mnt = NULL; + p->path.dentry = NULL; p->total_link_count = old ? old->total_link_count : 0; p->saved = old; current->nameidata = p; @@ -652,6 +654,8 @@ static void terminate_walk(struct nameidata *nd) rcu_read_unlock(); } nd->depth = 0; + nd->path.mnt = NULL; + nd->path.dentry = NULL; } /* path_put is needed afterwards regardless of success or failure */ @@ -2322,8 +2326,6 @@ static const char *path_init(struct nameidata *nd, unsigned flags) } nd->root.mnt = NULL; - nd->path.mnt = NULL; - nd->path.dentry = NULL; /* Absolute pathname -- fetch the root (LOOKUP_IN_ROOT uses nd->dfd). */ if (*s == '/' && !(flags & LOOKUP_IN_ROOT)) { From 6eff5721933c08c3b76d6126aee24d8f134518ef Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 1 Apr 2021 07:33:14 -0700 Subject: [PATCH 0721/1091] cxl/mem: Use sysfs_emit() for attribute show routines While none the CXL sysfs attributes are threatening to overrun a PAGE_SIZE of output, it is good form to use the recommended helpers. Fixes: b39cb1052a5c ("cxl/mem: Register CXL memX devices") Reported-by: Jason Gunthorpe Reviewed-by: Ben Widawsky Reviewed-by: Jason Gunthorpe Link: https://lore.kernel.org/r/161728759424.2474381.11231441014951343463.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams --- drivers/cxl/mem.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 244cb7d89678..832582033683 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -1066,7 +1066,7 @@ static ssize_t firmware_version_show(struct device *dev, struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_mem *cxlm = cxlmd->cxlm; - return sprintf(buf, "%.16s\n", cxlm->firmware_version); + return sysfs_emit(buf, "%.16s\n", cxlm->firmware_version); } static DEVICE_ATTR_RO(firmware_version); @@ -1076,7 +1076,7 @@ static ssize_t payload_max_show(struct device *dev, struct cxl_memdev *cxlmd = to_cxl_memdev(dev); struct cxl_mem *cxlm = cxlmd->cxlm; - return sprintf(buf, "%zu\n", cxlm->payload_size); + return sysfs_emit(buf, "%zu\n", cxlm->payload_size); } static DEVICE_ATTR_RO(payload_max); @@ -1087,7 +1087,7 @@ static ssize_t ram_size_show(struct device *dev, struct device_attribute *attr, struct cxl_mem *cxlm = cxlmd->cxlm; unsigned long long len = range_len(&cxlm->ram_range); - return sprintf(buf, "%#llx\n", len); + return sysfs_emit(buf, "%#llx\n", len); } static struct device_attribute dev_attr_ram_size = @@ -1100,7 +1100,7 @@ static ssize_t pmem_size_show(struct device *dev, struct device_attribute *attr, struct cxl_mem *cxlm = cxlmd->cxlm; unsigned long long len = range_len(&cxlm->pmem_range); - return sprintf(buf, "%#llx\n", len); + return sysfs_emit(buf, "%#llx\n", len); } static struct device_attribute dev_attr_pmem_size = From 5877515912cc4f0d67071b7cee15076ebef24708 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 1 Apr 2021 07:33:19 -0700 Subject: [PATCH 0722/1091] cxl/mem: Fix synchronization mechanism for device removal vs ioctl operations The percpu_ref to gate whether cxl_memdev_ioctl() is free to use the driver context (@cxlm) to issue I/O is overkill, implemented incorrectly (missing a device reference before accessing the percpu_ref), and the complexities of shutting down a percpu_ref contributed to a bug in the error unwind in cxl_mem_add_memdev() (missing put_device() to be fixed separately). Use an rwsem to explicitly synchronize the usage of cxlmd->cxlm, and add the missing reference counting for cxlmd in cxl_memdev_open() and cxl_memdev_release_file(). Fixes: b39cb1052a5c ("cxl/mem: Register CXL memX devices") Reported-by: Jason Gunthorpe Reviewed-by: Jason Gunthorpe Link: https://lore.kernel.org/r/161728759948.2474381.17481500816783671817.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams --- drivers/cxl/mem.c | 101 ++++++++++++++++++++++++---------------------- 1 file changed, 52 insertions(+), 49 deletions(-) diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 832582033683..438f0861c46c 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -96,21 +96,18 @@ struct mbox_cmd { * @dev: driver core device object * @cdev: char dev core object for ioctl operations * @cxlm: pointer to the parent device driver data - * @ops_active: active user of @cxlm in ops handlers - * @ops_dead: completion when all @cxlm ops users have exited * @id: id number of this memdev instance. */ struct cxl_memdev { struct device dev; struct cdev cdev; struct cxl_mem *cxlm; - struct percpu_ref ops_active; - struct completion ops_dead; int id; }; static int cxl_mem_major; static DEFINE_IDA(cxl_memdev_ida); +static DECLARE_RWSEM(cxl_memdev_rwsem); static struct dentry *cxl_debugfs; static bool cxl_raw_allow_all; @@ -776,26 +773,43 @@ static long __cxl_memdev_ioctl(struct cxl_memdev *cxlmd, unsigned int cmd, static long cxl_memdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg) { - struct cxl_memdev *cxlmd; - struct inode *inode; - int rc = -ENOTTY; + struct cxl_memdev *cxlmd = file->private_data; + int rc = -ENXIO; - inode = file_inode(file); - cxlmd = container_of(inode->i_cdev, typeof(*cxlmd), cdev); - - if (!percpu_ref_tryget_live(&cxlmd->ops_active)) - return -ENXIO; - - rc = __cxl_memdev_ioctl(cxlmd, cmd, arg); - - percpu_ref_put(&cxlmd->ops_active); + down_read(&cxl_memdev_rwsem); + if (cxlmd->cxlm) + rc = __cxl_memdev_ioctl(cxlmd, cmd, arg); + up_read(&cxl_memdev_rwsem); return rc; } +static int cxl_memdev_open(struct inode *inode, struct file *file) +{ + struct cxl_memdev *cxlmd = + container_of(inode->i_cdev, typeof(*cxlmd), cdev); + + get_device(&cxlmd->dev); + file->private_data = cxlmd; + + return 0; +} + +static int cxl_memdev_release_file(struct inode *inode, struct file *file) +{ + struct cxl_memdev *cxlmd = + container_of(inode->i_cdev, typeof(*cxlmd), cdev); + + put_device(&cxlmd->dev); + + return 0; +} + static const struct file_operations cxl_memdev_fops = { .owner = THIS_MODULE, .unlocked_ioctl = cxl_memdev_ioctl, + .open = cxl_memdev_open, + .release = cxl_memdev_release_file, .compat_ioctl = compat_ptr_ioctl, .llseek = noop_llseek, }; @@ -1049,7 +1063,6 @@ static void cxl_memdev_release(struct device *dev) { struct cxl_memdev *cxlmd = to_cxl_memdev(dev); - percpu_ref_exit(&cxlmd->ops_active); ida_free(&cxl_memdev_ida, cxlmd->id); kfree(cxlmd); } @@ -1150,26 +1163,23 @@ static const struct device_type cxl_memdev_type = { .groups = cxl_memdev_attribute_groups, }; -static void cxlmdev_unregister(void *_cxlmd) +static void cxl_memdev_shutdown(struct cxl_memdev *cxlmd) +{ + down_write(&cxl_memdev_rwsem); + cxlmd->cxlm = NULL; + up_write(&cxl_memdev_rwsem); +} + +static void cxl_memdev_unregister(void *_cxlmd) { struct cxl_memdev *cxlmd = _cxlmd; struct device *dev = &cxlmd->dev; - percpu_ref_kill(&cxlmd->ops_active); cdev_device_del(&cxlmd->cdev, dev); - wait_for_completion(&cxlmd->ops_dead); - cxlmd->cxlm = NULL; + cxl_memdev_shutdown(cxlmd); put_device(dev); } -static void cxlmdev_ops_active_release(struct percpu_ref *ref) -{ - struct cxl_memdev *cxlmd = - container_of(ref, typeof(*cxlmd), ops_active); - - complete(&cxlmd->ops_dead); -} - static int cxl_mem_add_memdev(struct cxl_mem *cxlm) { struct pci_dev *pdev = cxlm->pdev; @@ -1181,17 +1191,6 @@ static int cxl_mem_add_memdev(struct cxl_mem *cxlm) cxlmd = kzalloc(sizeof(*cxlmd), GFP_KERNEL); if (!cxlmd) return -ENOMEM; - init_completion(&cxlmd->ops_dead); - - /* - * @cxlm is deallocated when the driver unbinds so operations - * that are using it need to hold a live reference. - */ - cxlmd->cxlm = cxlm; - rc = percpu_ref_init(&cxlmd->ops_active, cxlmdev_ops_active_release, 0, - GFP_KERNEL); - if (rc) - goto err_ref; rc = ida_alloc_range(&cxl_memdev_ida, 0, CXL_MEM_MAX_DEVS, GFP_KERNEL); if (rc < 0) @@ -1209,23 +1208,27 @@ static int cxl_mem_add_memdev(struct cxl_mem *cxlm) cdev = &cxlmd->cdev; cdev_init(cdev, &cxl_memdev_fops); + /* + * Activate ioctl operations, no cxl_memdev_rwsem manipulation + * needed as this is ordered with cdev_add() publishing the device. + */ + cxlmd->cxlm = cxlm; + rc = cdev_device_add(cdev, dev); if (rc) goto err_add; - return devm_add_action_or_reset(dev->parent, cxlmdev_unregister, cxlmd); + return devm_add_action_or_reset(dev->parent, cxl_memdev_unregister, + cxlmd); err_add: + /* + * The cdev was briefly live, shutdown any ioctl operations that + * saw that state. + */ + cxl_memdev_shutdown(cxlmd); ida_free(&cxl_memdev_ida, cxlmd->id); err_id: - /* - * Theoretically userspace could have already entered the fops, - * so flush ops_active. - */ - percpu_ref_kill(&cxlmd->ops_active); - wait_for_completion(&cxlmd->ops_dead); - percpu_ref_exit(&cxlmd->ops_active); -err_ref: kfree(cxlmd); return rc; From 1c3333a28d4532cfc37d4d25bfc76654a0c76643 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 1 Apr 2021 07:33:25 -0700 Subject: [PATCH 0723/1091] cxl/mem: Do not rely on device_add() side effects for dev_set_name() failures While device_add() will happen to catch dev_set_name() failures it is a broken pattern to follow given that the core may try to fall back to a different name. Add explicit checking for dev_set_name() failures to be cleaned up by put_device(). Skip cdev_device_add() and proceed directly to put_device() if the name set fails. This type of bug is easier to see if 'alloc' is split from 'add' operations that require put_device() on failure. So cxl_memdev_alloc() is split out as a result. Fixes: b39cb1052a5c ("cxl/mem: Register CXL memX devices") Reported-by: Jason Gunthorpe Reviewed-by: Jason Gunthorpe Link: https://lore.kernel.org/r/161728760514.2474381.1163928273337158134.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams --- drivers/cxl/mem.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 438f0861c46c..da93b633531f 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -1180,7 +1180,7 @@ static void cxl_memdev_unregister(void *_cxlmd) put_device(dev); } -static int cxl_mem_add_memdev(struct cxl_mem *cxlm) +static struct cxl_memdev *cxl_memdev_alloc(struct cxl_mem *cxlm) { struct pci_dev *pdev = cxlm->pdev; struct cxl_memdev *cxlmd; @@ -1190,11 +1190,11 @@ static int cxl_mem_add_memdev(struct cxl_mem *cxlm) cxlmd = kzalloc(sizeof(*cxlmd), GFP_KERNEL); if (!cxlmd) - return -ENOMEM; + return ERR_PTR(-ENOMEM); rc = ida_alloc_range(&cxl_memdev_ida, 0, CXL_MEM_MAX_DEVS, GFP_KERNEL); if (rc < 0) - goto err_id; + goto err; cxlmd->id = rc; dev = &cxlmd->dev; @@ -1203,10 +1203,31 @@ static int cxl_mem_add_memdev(struct cxl_mem *cxlm) dev->bus = &cxl_bus_type; dev->devt = MKDEV(cxl_mem_major, cxlmd->id); dev->type = &cxl_memdev_type; - dev_set_name(dev, "mem%d", cxlmd->id); cdev = &cxlmd->cdev; cdev_init(cdev, &cxl_memdev_fops); + return cxlmd; + +err: + kfree(cxlmd); + return ERR_PTR(rc); +} + +static int cxl_mem_add_memdev(struct cxl_mem *cxlm) +{ + struct cxl_memdev *cxlmd; + struct device *dev; + struct cdev *cdev; + int rc; + + cxlmd = cxl_memdev_alloc(cxlm); + if (IS_ERR(cxlmd)) + return PTR_ERR(cxlmd); + + dev = &cxlmd->dev; + rc = dev_set_name(dev, "mem%d", cxlmd->id); + if (rc) + goto err; /* * Activate ioctl operations, no cxl_memdev_rwsem manipulation @@ -1214,23 +1235,21 @@ static int cxl_mem_add_memdev(struct cxl_mem *cxlm) */ cxlmd->cxlm = cxlm; + cdev = &cxlmd->cdev; rc = cdev_device_add(cdev, dev); if (rc) - goto err_add; + goto err; return devm_add_action_or_reset(dev->parent, cxl_memdev_unregister, cxlmd); -err_add: +err: /* * The cdev was briefly live, shutdown any ioctl operations that * saw that state. */ cxl_memdev_shutdown(cxlmd); - ida_free(&cxl_memdev_ida, cxlmd->id); -err_id: - kfree(cxlmd); - + put_device(dev); return rc; } From 7eda6457a9ca4dc9754e1158c3794e4487ea4392 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Thu, 1 Apr 2021 07:33:30 -0700 Subject: [PATCH 0724/1091] cxl/mem: Disable cxl device power management There is no power management of cxl virtual devices, disable device-power-management and runtime-power-management to prevent userspace from growing expectations of those attributes appearing. They can be added back in the future if needed. Reviewed-by: Ben Widawsky Link: https://lore.kernel.org/r/161728761025.2474381.808344500111924819.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams --- drivers/cxl/mem.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index da93b633531f..52f7da49c560 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -1203,6 +1203,7 @@ static struct cxl_memdev *cxl_memdev_alloc(struct cxl_mem *cxlm) dev->bus = &cxl_bus_type; dev->devt = MKDEV(cxl_mem_major, cxlmd->id); dev->type = &cxl_memdev_type; + device_set_pm_not_required(dev); cdev = &cxlmd->cdev; cdev_init(cdev, &cxl_memdev_fops); From 392be0bda730df3c71241b2a16bbecac78ee627d Mon Sep 17 00:00:00 2001 From: Robert Richter Date: Wed, 24 Mar 2021 15:16:35 +0100 Subject: [PATCH 0725/1091] cxl/mem: Force array size of mem_commands[] to CXL_MEM_COMMAND_ID_MAX Typically the mem_commands[] array is in sync with 'enum { CXL_CMDS }'. Current code works well. However, the array size of mem_commands[] may not strictly be the same as CXL_MEM_COMMAND_ID_MAX. E.g. if a new CXL_CMD() is added that is guarded by #ifdefs, the array could be shorter. This could lead then further to an out-of-bounds array access in cxl_validate_cmd_from_user(). Fix this by forcing the array size to CXL_MEM_COMMAND_ID_MAX. This also adds range checks for array items in mem_commands[] at compile time. Signed-off-by: Robert Richter Link: https://lore.kernel.org/r/20210324141635.22335-1-rrichter@amd.com Signed-off-by: Dan Williams --- drivers/cxl/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 52f7da49c560..e3003f49b329 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -166,7 +166,7 @@ struct cxl_mem_command { * table will be validated against the user's input. For example, if size_in is * 0, and the user passed in 1, it is an error. */ -static struct cxl_mem_command mem_commands[] = { +static struct cxl_mem_command mem_commands[CXL_MEM_COMMAND_ID_MAX] = { CXL_CMD(IDENTIFY, 0, 0x43, CXL_CMD_FLAG_FORCE_ENABLE), #ifdef CONFIG_CXL_MEM_RAW_COMMANDS CXL_CMD(RAW, ~0, ~0, 0), From 88c17855ac4291fb462e13a86b7516773b6c932e Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:41 -0400 Subject: [PATCH 0726/1091] net: ieee802154: forbid monitor for set llsec params This patch forbids to set llsec params for monitor interfaces which we don't support yet. Reported-by: syzbot+8b6719da8a04beeafcc3@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-3-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 1600edb98107..ce8956f31ef9 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1384,6 +1384,9 @@ static int nl802154_set_llsec_params(struct sk_buff *skb, u32 changed = 0; int ret; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (info->attrs[NL802154_ATTR_SEC_ENABLED]) { u8 enabled; From fb3c5cdf88cd504ef11d59e8d656f4bc896c6922 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:42 -0400 Subject: [PATCH 0727/1091] net: ieee802154: stop dump llsec keys for monitors This patch stops dumping llsec keys for monitors which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-4-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index ce8956f31ef9..7815f253c8a3 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1493,6 +1493,11 @@ nl802154_dump_llsec_key(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; From 08470c5453339369bd3d590c4cbb0b5961cdcbb6 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:43 -0400 Subject: [PATCH 0728/1091] net: ieee802154: forbid monitor for add llsec key This patch forbids to add llsec key for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-5-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 7815f253c8a3..42a246b6f9cb 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1552,6 +1552,9 @@ static int nl802154_add_llsec_key(struct sk_buff *skb, struct genl_info *info) struct ieee802154_llsec_key_id id = { }; u32 commands[NL802154_CMD_FRAME_NR_IDS / 32] = { }; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_KEY] || nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) return -EINVAL; From b6e2949544a183f590ae6f3ef2d1aaaa2c44e38a Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:44 -0400 Subject: [PATCH 0729/1091] net: ieee802154: forbid monitor for del llsec key This patch forbids to del llsec key for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-6-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 42a246b6f9cb..bfc0eca774e3 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1604,6 +1604,9 @@ static int nl802154_del_llsec_key(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_KEY_ATTR_MAX + 1]; struct ieee802154_llsec_key_id id; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_KEY] || nla_parse_nested_deprecated(attrs, NL802154_KEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_KEY], nl802154_key_policy, info->extack)) return -EINVAL; From 5582d641e6740839c9b83efd1fbf9bcd00b6f5fc Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:45 -0400 Subject: [PATCH 0730/1091] net: ieee802154: stop dump llsec devs for monitors This patch stops dumping llsec devs for monitors which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-7-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index bfc0eca774e3..ef0becc9faa7 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1672,6 +1672,11 @@ nl802154_dump_llsec_dev(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; From a3790a8a94fc0234c5d38013b48e74ef221ec84c Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Sun, 4 Apr 2021 16:38:31 +0200 Subject: [PATCH 0731/1091] platform/x86: intel-hid: Fix spurious wakeups caused by tablet-mode events during suspend Some devices send (duplicate) tablet-mode events when moved around even though the mode has not changed; and they do this even when suspended. Change the tablet-mode event handling when priv->wakeup_mode is set to update the switch state in case it changed and then return immediately (without calling pm_wakeup_hard_event()) to avoid spurious wakeups. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=212537 Fixes: 537b0dd4729e ("platform/x86: intel-hid: Add support for SW_TABLET_MODE") Signed-off-by: Hans de Goede Reviewed-by: Elia Devito Link: https://lore.kernel.org/r/20210404143831.25173-1-hdegoede@redhat.com --- drivers/platform/x86/intel-hid.c | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/drivers/platform/x86/intel-hid.c b/drivers/platform/x86/intel-hid.c index 57cc92891a57..078648a9201b 100644 --- a/drivers/platform/x86/intel-hid.c +++ b/drivers/platform/x86/intel-hid.c @@ -483,11 +483,16 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) goto wakeup; /* - * Switch events will wake the device and report the new switch - * position to the input subsystem. + * Some devices send (duplicate) tablet-mode events when moved + * around even though the mode has not changed; and they do this + * even when suspended. + * Update the switch state in case it changed and then return + * without waking up to avoid spurious wakeups. */ - if (priv->switches && (event == 0xcc || event == 0xcd)) - goto wakeup; + if (event == 0xcc || event == 0xcd) { + report_tablet_mode_event(priv->switches, event); + return; + } /* Wake up on 5-button array events only. */ if (event == 0xc0 || !priv->array) @@ -501,9 +506,6 @@ static void notify_handler(acpi_handle handle, u32 event, void *context) wakeup: pm_wakeup_hard_event(&device->dev); - if (report_tablet_mode_event(priv->switches, event)) - return; - return; } From 5303f956b05a2886ff42890908156afaec0f95ac Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:46 -0400 Subject: [PATCH 0732/1091] net: ieee802154: forbid monitor for add llsec dev This patch forbids to add llsec dev for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-8-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index ef0becc9faa7..0d7dc9478b56 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1763,6 +1763,9 @@ static int nl802154_add_llsec_dev(struct sk_buff *skb, struct genl_info *info) struct wpan_dev *wpan_dev = dev->ieee802154_ptr; struct ieee802154_llsec_device dev_desc; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (ieee802154_llsec_parse_device(info->attrs[NL802154_ATTR_SEC_DEVICE], &dev_desc) < 0) return -EINVAL; From ad8f9de1f3566686af35b1c6b43240726541da61 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:47 -0400 Subject: [PATCH 0733/1091] net: ieee802154: forbid monitor for del llsec dev This patch forbids to del llsec dev for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-9-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 0d7dc9478b56..17c782d4cdae 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1781,6 +1781,9 @@ static int nl802154_del_llsec_dev(struct sk_buff *skb, struct genl_info *info) struct nlattr *attrs[NL802154_DEV_ATTR_MAX + 1]; __le64 extended_addr; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_DEVICE] || nla_parse_nested_deprecated(attrs, NL802154_DEV_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVICE], nl802154_dev_policy, info->extack)) return -EINVAL; From 080d1a57a94d93e70f84b7a360baa351388c574f Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:48 -0400 Subject: [PATCH 0734/1091] net: ieee802154: stop dump llsec devkeys for monitors This patch stops dumping llsec devkeys for monitors which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-10-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 17c782d4cdae..6f9cb6c0cafc 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1853,6 +1853,11 @@ nl802154_dump_llsec_devkey(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; From a347b3b394868fef15b16f143719df56184be81d Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:49 -0400 Subject: [PATCH 0735/1091] net: ieee802154: forbid monitor for add llsec devkey This patch forbids to add llsec devkey for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-11-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 6f9cb6c0cafc..c3f9bff7a557 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1915,6 +1915,9 @@ static int nl802154_add_llsec_devkey(struct sk_buff *skb, struct genl_info *info struct ieee802154_llsec_device_key key; __le64 extended_addr; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack) < 0) return -EINVAL; From 6fb8045319ef172dc88a8142e7f8b58c7608137e Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:50 -0400 Subject: [PATCH 0736/1091] net: ieee802154: forbid monitor for del llsec devkey This patch forbids to del llsec devkey for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-12-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index c3f9bff7a557..88735f03b73e 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -1949,6 +1949,9 @@ static int nl802154_del_llsec_devkey(struct sk_buff *skb, struct genl_info *info struct ieee802154_llsec_device_key key; __le64 extended_addr; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_DEVKEY] || nla_parse_nested_deprecated(attrs, NL802154_DEVKEY_ATTR_MAX, info->attrs[NL802154_ATTR_SEC_DEVKEY], nl802154_devkey_policy, info->extack)) return -EINVAL; From 4c9b4f55ad1f5a4b6206ac4ea58f273126d21925 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:51 -0400 Subject: [PATCH 0737/1091] net: ieee802154: stop dump llsec seclevels for monitors This patch stops dumping llsec seclevels for monitors which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-13-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 88735f03b73e..9158b095ccf9 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -2026,6 +2026,11 @@ nl802154_dump_llsec_seclevel(struct sk_buff *skb, struct netlink_callback *cb) if (err) return err; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) { + err = skb->len; + goto out_err; + } + if (!wpan_dev->netdev) { err = -EINVAL; goto out_err; From 9ec87e322428d4734ac647d1a8e507434086993d Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:52 -0400 Subject: [PATCH 0738/1091] net: ieee802154: forbid monitor for add llsec seclevel This patch forbids to add llsec seclevel for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-14-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 9158b095ccf9..28427ce52a9b 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -2115,6 +2115,9 @@ static int nl802154_add_llsec_seclevel(struct sk_buff *skb, struct wpan_dev *wpan_dev = dev->ieee802154_ptr; struct ieee802154_llsec_seclevel sl; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], &sl) < 0) return -EINVAL; From 56b4c6515a367718ced8595debf1567c052ea0b2 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Mon, 5 Apr 2021 20:14:05 +0200 Subject: [PATCH 0739/1091] i2c: exynos5: correct top kerneldoc The top comment is not a kerneldoc, as W=1 build reports: drivers/i2c/busses/i2c-exynos5.c:39: warning: expecting prototype for i2c(). Prototype was for HSI2C_CTL() instead Signed-off-by: Krzysztof Kozlowski Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-exynos5.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/i2c/busses/i2c-exynos5.c b/drivers/i2c/busses/i2c-exynos5.c index 5ac30d95650c..97d4f3ac0abd 100644 --- a/drivers/i2c/busses/i2c-exynos5.c +++ b/drivers/i2c/busses/i2c-exynos5.c @@ -1,5 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/** +/* * i2c-exynos5.c - Samsung Exynos5 I2C Controller Driver * * Copyright (C) 2013 Samsung Electronics Co., Ltd. From 9dde130937e95b72adfae64ab21d6e7e707e2dac Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:53 -0400 Subject: [PATCH 0740/1091] net: ieee802154: forbid monitor for del llsec seclevel This patch forbids to del llsec seclevel for monitor interfaces which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Reported-by: syzbot+fbf4fc11a819824e027b@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-15-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index 28427ce52a9b..effc4c1a4780 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -2133,6 +2133,9 @@ static int nl802154_del_llsec_seclevel(struct sk_buff *skb, struct wpan_dev *wpan_dev = dev->ieee802154_ptr; struct ieee802154_llsec_seclevel sl; + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + return -EOPNOTSUPP; + if (!info->attrs[NL802154_ATTR_SEC_LEVEL] || llsec_parse_seclevel(info->attrs[NL802154_ATTR_SEC_LEVEL], &sl) < 0) From 1534efc7bbc1121e92c86c2dabebaf2c9dcece19 Mon Sep 17 00:00:00 2001 From: Alexander Aring Date: Sun, 4 Apr 2021 20:30:54 -0400 Subject: [PATCH 0741/1091] net: ieee802154: stop dump llsec params for monitors This patch stops dumping llsec params for monitors which we don't support yet. Otherwise we will access llsec mib which isn't initialized for monitors. Reported-by: syzbot+cde43a581a8e5f317bc2@syzkaller.appspotmail.com Signed-off-by: Alexander Aring Link: https://lore.kernel.org/r/20210405003054.256017-16-aahringo@redhat.com Signed-off-by: Stefan Schmidt --- net/ieee802154/nl802154.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/net/ieee802154/nl802154.c b/net/ieee802154/nl802154.c index effc4c1a4780..05f6bd89a7dd 100644 --- a/net/ieee802154/nl802154.c +++ b/net/ieee802154/nl802154.c @@ -820,8 +820,13 @@ nl802154_send_iface(struct sk_buff *msg, u32 portid, u32 seq, int flags, goto nla_put_failure; #ifdef CONFIG_IEEE802154_NL802154_EXPERIMENTAL + if (wpan_dev->iftype == NL802154_IFTYPE_MONITOR) + goto out; + if (nl802154_get_llsec_params(msg, rdev, wpan_dev) < 0) goto nla_put_failure; + +out: #endif /* CONFIG_IEEE802154_NL802154_EXPERIMENTAL */ genlmsg_end(msg, hdr); From 1165affd484889d4986cf3b724318935a0b120d8 Mon Sep 17 00:00:00 2001 From: Pavel Skripkin Date: Thu, 4 Mar 2021 18:21:25 +0300 Subject: [PATCH 0742/1091] net: mac802154: Fix general protection fault syzbot found general protection fault in crypto_destroy_tfm()[1]. It was caused by wrong clean up loop in llsec_key_alloc(). If one of the tfm array members is in IS_ERR() range it will cause general protection fault in clean up function [1]. Call Trace: crypto_free_aead include/crypto/aead.h:191 [inline] [1] llsec_key_alloc net/mac802154/llsec.c:156 [inline] mac802154_llsec_key_add+0x9e0/0xcc0 net/mac802154/llsec.c:249 ieee802154_add_llsec_key+0x56/0x80 net/mac802154/cfg.c:338 rdev_add_llsec_key net/ieee802154/rdev-ops.h:260 [inline] nl802154_add_llsec_key+0x3d3/0x560 net/ieee802154/nl802154.c:1584 genl_family_rcv_msg_doit+0x228/0x320 net/netlink/genetlink.c:739 genl_family_rcv_msg net/netlink/genetlink.c:783 [inline] genl_rcv_msg+0x328/0x580 net/netlink/genetlink.c:800 netlink_rcv_skb+0x153/0x420 net/netlink/af_netlink.c:2502 genl_rcv+0x24/0x40 net/netlink/genetlink.c:811 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2350 ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2433 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xae Signed-off-by: Pavel Skripkin Reported-by: syzbot+9ec037722d2603a9f52e@syzkaller.appspotmail.com Acked-by: Alexander Aring Link: https://lore.kernel.org/r/20210304152125.1052825-1-paskripkin@gmail.com Signed-off-by: Stefan Schmidt --- net/mac802154/llsec.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac802154/llsec.c b/net/mac802154/llsec.c index 585d33144c33..55550ead2ced 100644 --- a/net/mac802154/llsec.c +++ b/net/mac802154/llsec.c @@ -152,7 +152,7 @@ err_tfm0: crypto_free_sync_skcipher(key->tfm0); err_tfm: for (i = 0; i < ARRAY_SIZE(key->tfm); i++) - if (key->tfm[i]) + if (!IS_ERR_OR_NULL(key->tfm[i])) crypto_free_aead(key->tfm[i]); kfree_sensitive(key); From b25b343db0526669947a427e9a31bac91d29bb06 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Fri, 2 Apr 2021 10:40:19 -0700 Subject: [PATCH 0743/1091] net: broadcom: bcm4908enet: Fix a double free in bcm4908_enet_dma_alloc In bcm4908_enet_dma_alloc, if callee bcm4908_dma_alloc_buf_descs() failed, it will free the ring->cpu_addr by dma_free_coherent() and return error. Then bcm4908_enet_dma_free() will be called, and free the same cpu_addr by dma_free_coherent() again. My patch set ring->cpu_addr to NULL after it is freed in bcm4908_dma_alloc_buf_descs() to avoid the double free. Fixes: 4feffeadbcb2e ("net: broadcom: bcm4908enet: add BCM4908 controller driver") Signed-off-by: Lv Yunlong Signed-off-by: David S. Miller --- drivers/net/ethernet/broadcom/bcm4908_enet.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/broadcom/bcm4908_enet.c b/drivers/net/ethernet/broadcom/bcm4908_enet.c index 98cf82dea3e4..65981931a798 100644 --- a/drivers/net/ethernet/broadcom/bcm4908_enet.c +++ b/drivers/net/ethernet/broadcom/bcm4908_enet.c @@ -172,6 +172,7 @@ static int bcm4908_dma_alloc_buf_descs(struct bcm4908_enet *enet, err_free_buf_descs: dma_free_coherent(dev, size, ring->cpu_addr, ring->dma_addr); + ring->cpu_addr = NULL; return -ENOMEM; } From 0f6925b3e8da0dbbb52447ca8a8b42b371aac7db Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 2 Apr 2021 06:26:02 -0700 Subject: [PATCH 0744/1091] virtio_net: Do not pull payload in skb->head Xuan Zhuo reported that commit 3226b158e67c ("net: avoid 32 x truesize under-estimation for tiny skbs") brought a ~10% performance drop. The reason for the performance drop was that GRO was forced to chain sk_buff (using skb_shinfo(skb)->frag_list), which uses more memory but also cause packet consumers to go over a lot of overhead handling all the tiny skbs. It turns out that virtio_net page_to_skb() has a wrong strategy : It allocates skbs with GOOD_COPY_LEN (128) bytes in skb->head, then copies 128 bytes from the page, before feeding the packet to GRO stack. This was suboptimal before commit 3226b158e67c ("net: avoid 32 x truesize under-estimation for tiny skbs") because GRO was using 2 frags per MSS, meaning we were not packing MSS with 100% efficiency. Fix is to pull only the ethernet header in page_to_skb() Then, we change virtio_net_hdr_to_skb() to pull the missing headers, instead of assuming they were already pulled by callers. This fixes the performance regression, but could also allow virtio_net to accept packets with more than 128bytes of headers. Many thanks to Xuan Zhuo for his report, and his tests/help. Fixes: 3226b158e67c ("net: avoid 32 x truesize under-estimation for tiny skbs") Reported-by: Xuan Zhuo Link: https://www.spinics.net/lists/netdev/msg731397.html Co-Developed-by: Xuan Zhuo Signed-off-by: Xuan Zhuo Signed-off-by: Eric Dumazet Cc: "Michael S. Tsirkin" Cc: Jason Wang Cc: virtualization@lists.linux-foundation.org Acked-by: Jason Wang Signed-off-by: David S. Miller --- drivers/net/virtio_net.c | 10 +++++++--- include/linux/virtio_net.h | 14 +++++++++----- 2 files changed, 16 insertions(+), 8 deletions(-) diff --git a/drivers/net/virtio_net.c b/drivers/net/virtio_net.c index 82e520d2cb12..0824e6999e49 100644 --- a/drivers/net/virtio_net.c +++ b/drivers/net/virtio_net.c @@ -406,9 +406,13 @@ static struct sk_buff *page_to_skb(struct virtnet_info *vi, offset += hdr_padded_len; p += hdr_padded_len; - copy = len; - if (copy > skb_tailroom(skb)) - copy = skb_tailroom(skb); + /* Copy all frame if it fits skb->head, otherwise + * we let virtio_net_hdr_to_skb() and GRO pull headers as needed. + */ + if (len <= skb_tailroom(skb)) + copy = len; + else + copy = ETH_HLEN + metasize; skb_put_data(skb, p, copy); if (metasize) { diff --git a/include/linux/virtio_net.h b/include/linux/virtio_net.h index 98775d7fa696..b465f8f3e554 100644 --- a/include/linux/virtio_net.h +++ b/include/linux/virtio_net.h @@ -65,14 +65,18 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb, skb_reset_mac_header(skb); if (hdr->flags & VIRTIO_NET_HDR_F_NEEDS_CSUM) { - u16 start = __virtio16_to_cpu(little_endian, hdr->csum_start); - u16 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); + u32 start = __virtio16_to_cpu(little_endian, hdr->csum_start); + u32 off = __virtio16_to_cpu(little_endian, hdr->csum_offset); + u32 needed = start + max_t(u32, thlen, off + sizeof(__sum16)); + + if (!pskb_may_pull(skb, needed)) + return -EINVAL; if (!skb_partial_csum_set(skb, start, off)) return -EINVAL; p_off = skb_transport_offset(skb) + thlen; - if (p_off > skb_headlen(skb)) + if (!pskb_may_pull(skb, p_off)) return -EINVAL; } else { /* gso packets without NEEDS_CSUM do not set transport_offset. @@ -102,14 +106,14 @@ retry: } p_off = keys.control.thoff + thlen; - if (p_off > skb_headlen(skb) || + if (!pskb_may_pull(skb, p_off) || keys.basic.ip_proto != ip_proto) return -EINVAL; skb_set_transport_header(skb, keys.control.thoff); } else if (gso_type) { p_off = thlen; - if (p_off > skb_headlen(skb)) + if (!pskb_may_pull(skb, p_off)) return -EINVAL; } } From 2a2403ca3add03f542f6b34bef9f74649969b06d Mon Sep 17 00:00:00 2001 From: Xin Long Date: Tue, 6 Apr 2021 10:45:23 +0800 Subject: [PATCH 0745/1091] tipc: increment the tmp aead refcnt before attaching it Li Shuang found a NULL pointer dereference crash in her testing: [] BUG: unable to handle kernel NULL pointer dereference at 0000000000000020 [] RIP: 0010:tipc_crypto_rcv_complete+0xc8/0x7e0 [tipc] [] Call Trace: [] [] tipc_crypto_rcv+0x2d9/0x8f0 [tipc] [] tipc_rcv+0x2fc/0x1120 [tipc] [] tipc_udp_recv+0xc6/0x1e0 [tipc] [] udpv6_queue_rcv_one_skb+0x16a/0x460 [] udp6_unicast_rcv_skb.isra.35+0x41/0xa0 [] ip6_protocol_deliver_rcu+0x23b/0x4c0 [] ip6_input+0x3d/0xb0 [] ipv6_rcv+0x395/0x510 [] __netif_receive_skb_core+0x5fc/0xc40 This is caused by NULL returned by tipc_aead_get(), and then crashed when dereferencing it later in tipc_crypto_rcv_complete(). This might happen when tipc_crypto_rcv_complete() is called by two threads at the same time: the tmp attached by tipc_crypto_key_attach() in one thread may be released by the one attached by that in the other thread. This patch is to fix it by incrementing the tmp's refcnt before attaching it instead of calling tipc_aead_get() after attaching it. Fixes: fc1b6d6de220 ("tipc: introduce TIPC encryption & authentication") Reported-by: Li Shuang Signed-off-by: Xin Long Signed-off-by: David S. Miller --- net/tipc/crypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/tipc/crypto.c b/net/tipc/crypto.c index f4fca8f7f63f..97710ce36047 100644 --- a/net/tipc/crypto.c +++ b/net/tipc/crypto.c @@ -1941,12 +1941,13 @@ static void tipc_crypto_rcv_complete(struct net *net, struct tipc_aead *aead, goto rcv; if (tipc_aead_clone(&tmp, aead) < 0) goto rcv; + WARN_ON(!refcount_inc_not_zero(&tmp->refcnt)); if (tipc_crypto_key_attach(rx, tmp, ehdr->tx_key, false) < 0) { tipc_aead_free(&tmp->rcu); goto rcv; } tipc_aead_put(aead); - aead = tipc_aead_get(tmp); + aead = tmp; } if (unlikely(err)) { From 1c84b33101c82683dee8b06761ca1f69e78c8ee7 Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 1 Apr 2021 15:00:19 -0700 Subject: [PATCH 0746/1091] bpf, sockmap: Fix sk->prot unhash op reset In '4da6a196f93b1' we fixed a potential unhash loop caused when a TLS socket in a sockmap was removed from the sockmap. This happened because the unhash operation on the TLS ctx continued to point at the sockmap implementation of unhash even though the psock has already been removed. The sockmap unhash handler when a psock is removed does the following, void sock_map_unhash(struct sock *sk) { void (*saved_unhash)(struct sock *sk); struct sk_psock *psock; rcu_read_lock(); psock = sk_psock(sk); if (unlikely(!psock)) { rcu_read_unlock(); if (sk->sk_prot->unhash) sk->sk_prot->unhash(sk); return; } [...] } The unlikely() case is there to handle the case where psock is detached but the proto ops have not been updated yet. But, in the above case with TLS and removed psock we never fixed sk_prot->unhash() and unhash() points back to sock_map_unhash resulting in a loop. To fix this we added this bit of code, static inline void sk_psock_restore_proto(struct sock *sk, struct sk_psock *psock) { sk->sk_prot->unhash = psock->saved_unhash; This will set the sk_prot->unhash back to its saved value. This is the correct callback for a TLS socket that has been removed from the sock_map. Unfortunately, this also overwrites the unhash pointer for all psocks. We effectively break sockmap unhash handling for any future socks. Omitting the unhash operation will leave stale entries in the map if a socket transition through unhash, but does not do close() op. To fix set unhash correctly before calling into tls_update. This way the TLS enabled socket will point to the saved unhash() handler. Fixes: 4da6a196f93b1 ("bpf: Sockmap/tls, during free we may call tcp_bpf_unhash() in loop") Reported-by: Cong Wang Reported-by: Lorenz Bauer Suggested-by: Cong Wang Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/161731441904.68884.15593917809745631972.stgit@john-XPS-13-9370 --- include/linux/skmsg.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/include/linux/skmsg.h b/include/linux/skmsg.h index 8edbbf5f2f93..822c048934e3 100644 --- a/include/linux/skmsg.h +++ b/include/linux/skmsg.h @@ -349,8 +349,13 @@ static inline void sk_psock_update_proto(struct sock *sk, static inline void sk_psock_restore_proto(struct sock *sk, struct sk_psock *psock) { - sk->sk_prot->unhash = psock->saved_unhash; if (inet_csk_has_ulp(sk)) { + /* TLS does not have an unhash proto in SW cases, but we need + * to ensure we stop using the sock_map unhash routine because + * the associated psock is being removed. So use the original + * unhash handler. + */ + WRITE_ONCE(sk->sk_prot->unhash, psock->saved_unhash); tcp_update_ulp(sk, psock->sk_proto, psock->saved_write_space); } else { sk->sk_write_space = psock->saved_write_space; From 144748eb0c445091466c9b741ebd0bfcc5914f3d Mon Sep 17 00:00:00 2001 From: John Fastabend Date: Thu, 1 Apr 2021 15:00:40 -0700 Subject: [PATCH 0747/1091] bpf, sockmap: Fix incorrect fwd_alloc accounting Incorrect accounting fwd_alloc can result in a warning when the socket is torn down, [18455.319240] WARNING: CPU: 0 PID: 24075 at net/core/stream.c:208 sk_stream_kill_queues+0x21f/0x230 [...] [18455.319543] Call Trace: [18455.319556] inet_csk_destroy_sock+0xba/0x1f0 [18455.319577] tcp_rcv_state_process+0x1b4e/0x2380 [18455.319593] ? lock_downgrade+0x3a0/0x3a0 [18455.319617] ? tcp_finish_connect+0x1e0/0x1e0 [18455.319631] ? sk_reset_timer+0x15/0x70 [18455.319646] ? tcp_schedule_loss_probe+0x1b2/0x240 [18455.319663] ? lock_release+0xb2/0x3f0 [18455.319676] ? __release_sock+0x8a/0x1b0 [18455.319690] ? lock_downgrade+0x3a0/0x3a0 [18455.319704] ? lock_release+0x3f0/0x3f0 [18455.319717] ? __tcp_close+0x2c6/0x790 [18455.319736] ? tcp_v4_do_rcv+0x168/0x370 [18455.319750] tcp_v4_do_rcv+0x168/0x370 [18455.319767] __release_sock+0xbc/0x1b0 [18455.319785] __tcp_close+0x2ee/0x790 [18455.319805] tcp_close+0x20/0x80 This currently happens because on redirect case we do skb_set_owner_r() with the original sock. This increments the fwd_alloc memory accounting on the original sock. Then on redirect we may push this into the queue of the psock we are redirecting to. When the skb is flushed from the queue we give the memory back to the original sock. The problem is if the original sock is destroyed/closed with skbs on another psocks queue then the original sock will not have a way to reclaim the memory before being destroyed. Then above warning will be thrown sockA sockB sk_psock_strp_read() sk_psock_verdict_apply() -- SK_REDIRECT -- sk_psock_skb_redirect() skb_queue_tail(psock_other->ingress_skb..) sk_close() sock_map_unref() sk_psock_put() sk_psock_drop() sk_psock_zap_ingress() At this point we have torn down our own psock, but have the outstanding skb in psock_other. Note that SK_PASS doesn't have this problem because the sk_psock_drop() logic releases the skb, its still associated with our psock. To resolve lets only account for sockets on the ingress queue that are still associated with the current socket. On the redirect case we will check memory limits per 6fa9201a89898, but will omit fwd_alloc accounting until skb is actually enqueued. When the skb is sent via skb_send_sock_locked or received with sk_psock_skb_ingress memory will be claimed on psock_other. Fixes: 6fa9201a89898 ("bpf, sockmap: Avoid returning unneeded EAGAIN when redirecting to self") Reported-by: Andrii Nakryiko Signed-off-by: John Fastabend Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/161731444013.68884.4021114312848535993.stgit@john-XPS-13-9370 --- net/core/skmsg.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/net/core/skmsg.c b/net/core/skmsg.c index 1261512d6807..5def3a2e85be 100644 --- a/net/core/skmsg.c +++ b/net/core/skmsg.c @@ -488,6 +488,7 @@ static int sk_psock_skb_ingress_self(struct sk_psock *psock, struct sk_buff *skb if (unlikely(!msg)) return -EAGAIN; sk_msg_init(msg); + skb_set_owner_r(skb, sk); return sk_psock_skb_ingress_enqueue(skb, psock, sk, msg); } @@ -790,7 +791,6 @@ static void sk_psock_tls_verdict_apply(struct sk_buff *skb, struct sock *sk, int { switch (verdict) { case __SK_REDIRECT: - skb_set_owner_r(skb, sk); sk_psock_skb_redirect(skb); break; case __SK_PASS: @@ -808,10 +808,6 @@ int sk_psock_tls_strp_read(struct sk_psock *psock, struct sk_buff *skb) rcu_read_lock(); prog = READ_ONCE(psock->progs.skb_verdict); if (likely(prog)) { - /* We skip full set_owner_r here because if we do a SK_PASS - * or SK_DROP we can skip skb memory accounting and use the - * TLS context. - */ skb->sk = psock->sk; tcp_skb_bpf_redirect_clear(skb); ret = sk_psock_bpf_run(psock, prog, skb); @@ -880,12 +876,13 @@ static void sk_psock_strp_read(struct strparser *strp, struct sk_buff *skb) kfree_skb(skb); goto out; } - skb_set_owner_r(skb, sk); prog = READ_ONCE(psock->progs.skb_verdict); if (likely(prog)) { + skb->sk = sk; tcp_skb_bpf_redirect_clear(skb); ret = sk_psock_bpf_run(psock, prog, skb); ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb)); + skb->sk = NULL; } sk_psock_verdict_apply(psock, skb, ret); out: @@ -956,12 +953,13 @@ static int sk_psock_verdict_recv(read_descriptor_t *desc, struct sk_buff *skb, kfree_skb(skb); goto out; } - skb_set_owner_r(skb, sk); prog = READ_ONCE(psock->progs.skb_verdict); if (likely(prog)) { + skb->sk = sk; tcp_skb_bpf_redirect_clear(skb); ret = sk_psock_bpf_run(psock, prog, skb); ret = sk_psock_map_verd(ret, tcp_skb_bpf_redirect_fetch(skb)); + skb->sk = NULL; } sk_psock_verdict_apply(psock, skb, ret); out: From 66c3f05ddc538ee796321210c906b6ae6fc0792a Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Mon, 5 Apr 2021 21:29:22 -0700 Subject: [PATCH 0748/1091] pcnet32: Use pci_resource_len to validate PCI resource pci_resource_start() is not a good indicator to determine if a PCI resource exists or not, since the resource may start at address 0. This is seen when trying to instantiate the driver in qemu for riscv32 or riscv64. pci 0000:00:01.0: reg 0x10: [io 0x0000-0x001f] pci 0000:00:01.0: reg 0x14: [mem 0x00000000-0x0000001f] ... pcnet32: card has no PCI IO resources, aborting Use pci_resouce_len() instead. Signed-off-by: Guenter Roeck Signed-off-by: David S. Miller --- drivers/net/ethernet/amd/pcnet32.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/amd/pcnet32.c b/drivers/net/ethernet/amd/pcnet32.c index 187b0b9a6e1d..f78daba60b35 100644 --- a/drivers/net/ethernet/amd/pcnet32.c +++ b/drivers/net/ethernet/amd/pcnet32.c @@ -1534,8 +1534,7 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) } pci_set_master(pdev); - ioaddr = pci_resource_start(pdev, 0); - if (!ioaddr) { + if (!pci_resource_len(pdev, 0)) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("card has no PCI IO resources, aborting\n"); err = -ENODEV; @@ -1548,6 +1547,8 @@ pcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent) pr_err("architecture does not support 32bit PCI busmaster DMA\n"); goto err_disable_dev; } + + ioaddr = pci_resource_start(pdev, 0); if (!request_region(ioaddr, PCNET32_TOTAL_SIZE, "pcnet32_probe_pci")) { if (pcnet32_debug & NETIF_MSG_PROBE) pr_err("io address range already allocated\n"); From ed7bedd2c3ca040f1e8ea02c6590a93116b1ec78 Mon Sep 17 00:00:00 2001 From: Guangbin Huang Date: Tue, 6 Apr 2021 21:10:43 +0800 Subject: [PATCH 0749/1091] net: hns3: clear VF down state bit before request link status Currently, the VF down state bit is cleared after VF sending link status request command. There is problem that when VF gets link status replied from PF, the down state bit may still set as 1. In this case, the link status replied from PF will be ignored and always set VF link status to down. To fix this problem, clear VF down state bit before VF requests link status. Fixes: e2cb1dec9779 ("net: hns3: Add HNS3 VF HCL(Hardware Compatibility Layer) Support") Signed-off-by: Guangbin Huang Signed-off-by: Huazhong Tan Signed-off-by: David S. Miller --- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 700e068764c8..14b83eca0a5e 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2624,14 +2624,14 @@ static int hclgevf_ae_start(struct hnae3_handle *handle) { struct hclgevf_dev *hdev = hclgevf_ae_get_hdev(handle); + clear_bit(HCLGEVF_STATE_DOWN, &hdev->state); + hclgevf_reset_tqp_stats(handle); hclgevf_request_link_info(hdev); hclgevf_update_link_mode(hdev); - clear_bit(HCLGEVF_STATE_DOWN, &hdev->state); - return 0; } From 63cf32389925e234d166fb1a336b46de7f846003 Mon Sep 17 00:00:00 2001 From: Wong Vee Khee Date: Tue, 6 Apr 2021 21:17:30 +0800 Subject: [PATCH 0750/1091] ethtool: fix incorrect datatype in set_eee ops The member 'tx_lpi_timer' is defined with __u32 datatype in the ethtool header file. Hence, we should use ethnl_update_u32() in set_eee ops. Fixes: fd77be7bd43c ("ethtool: set EEE settings with EEE_SET request") Cc: # 5.10.x Cc: Michal Kubecek Signed-off-by: Wong Vee Khee Reviewed-by: Jakub Kicinski Reviewed-by: Michal Kubecek Signed-off-by: David S. Miller --- net/ethtool/eee.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ethtool/eee.c b/net/ethtool/eee.c index 901b7de941ab..e10bfcc07853 100644 --- a/net/ethtool/eee.c +++ b/net/ethtool/eee.c @@ -169,8 +169,8 @@ int ethnl_set_eee(struct sk_buff *skb, struct genl_info *info) ethnl_update_bool32(&eee.eee_enabled, tb[ETHTOOL_A_EEE_ENABLED], &mod); ethnl_update_bool32(&eee.tx_lpi_enabled, tb[ETHTOOL_A_EEE_TX_LPI_ENABLED], &mod); - ethnl_update_bool32(&eee.tx_lpi_timer, tb[ETHTOOL_A_EEE_TX_LPI_TIMER], - &mod); + ethnl_update_u32(&eee.tx_lpi_timer, tb[ETHTOOL_A_EEE_TX_LPI_TIMER], + &mod); ret = 0; if (!mod) goto out_ops; From cca8ea3b05c972ffb5295367e6c544369b45fbdd Mon Sep 17 00:00:00 2001 From: Phillip Potter Date: Tue, 6 Apr 2021 18:45:54 +0100 Subject: [PATCH 0751/1091] net: tun: set tun->dev->addr_len during TUNSETLINK processing When changing type with TUNSETLINK ioctl command, set tun->dev->addr_len to match the appropriate type, using new tun_get_addr_len utility function which returns appropriate address length for given type. Fixes a KMSAN-found uninit-value bug reported by syzbot at: https://syzkaller.appspot.com/bug?id=0766d38c656abeace60621896d705743aeefed51 Reported-by: syzbot+001516d86dbe88862cec@syzkaller.appspotmail.com Diagnosed-by: Eric Dumazet Signed-off-by: Phillip Potter Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/tun.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/drivers/net/tun.c b/drivers/net/tun.c index fc86da7f1628..4cf38be26dc9 100644 --- a/drivers/net/tun.c +++ b/drivers/net/tun.c @@ -69,6 +69,14 @@ #include #include #include +#include +#include +#include +#include +#include +#include +#include +#include #include #include @@ -2919,6 +2927,45 @@ static int tun_set_ebpf(struct tun_struct *tun, struct tun_prog __rcu **prog_p, return __tun_set_ebpf(tun, prog_p, prog); } +/* Return correct value for tun->dev->addr_len based on tun->dev->type. */ +static unsigned char tun_get_addr_len(unsigned short type) +{ + switch (type) { + case ARPHRD_IP6GRE: + case ARPHRD_TUNNEL6: + return sizeof(struct in6_addr); + case ARPHRD_IPGRE: + case ARPHRD_TUNNEL: + case ARPHRD_SIT: + return 4; + case ARPHRD_ETHER: + return ETH_ALEN; + case ARPHRD_IEEE802154: + case ARPHRD_IEEE802154_MONITOR: + return IEEE802154_EXTENDED_ADDR_LEN; + case ARPHRD_PHONET_PIPE: + case ARPHRD_PPP: + case ARPHRD_NONE: + return 0; + case ARPHRD_6LOWPAN: + return EUI64_ADDR_LEN; + case ARPHRD_FDDI: + return FDDI_K_ALEN; + case ARPHRD_HIPPI: + return HIPPI_ALEN; + case ARPHRD_IEEE802: + return FC_ALEN; + case ARPHRD_ROSE: + return ROSE_ADDR_LEN; + case ARPHRD_NETROM: + return AX25_ADDR_LEN; + case ARPHRD_LOCALTLK: + return LTALK_ALEN; + default: + return 0; + } +} + static long __tun_chr_ioctl(struct file *file, unsigned int cmd, unsigned long arg, int ifreq_len) { @@ -3082,6 +3129,7 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd, break; } tun->dev->type = (int) arg; + tun->dev->addr_len = tun_get_addr_len(tun->dev->type); netif_info(tun, drv, tun->dev, "linktype set to %d\n", tun->dev->type); call_netdevice_notifiers(NETDEV_POST_TYPE_CHANGE, From 5219d6012d46ec1fa3397e50bfeb7b8c16df72cf Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Apr 2021 15:58:15 -0700 Subject: [PATCH 0752/1091] docs: ethtool: fix some copy-paste errors Fix incorrect documentation. Mostly referring to other objects, likely because the text was copied and not adjusted. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- Documentation/networking/ethtool-netlink.rst | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Documentation/networking/ethtool-netlink.rst b/Documentation/networking/ethtool-netlink.rst index 05073482db05..dc03ff884541 100644 --- a/Documentation/networking/ethtool-netlink.rst +++ b/Documentation/networking/ethtool-netlink.rst @@ -976,9 +976,9 @@ constraints on coalescing parameters and their values. PAUSE_GET -============ +========= -Gets channel counts like ``ETHTOOL_GPAUSE`` ioctl request. +Gets pause frame settings like ``ETHTOOL_GPAUSEPARAM`` ioctl request. Request contents: @@ -1007,7 +1007,7 @@ the statistics in the following structure: Each member has a corresponding attribute defined. PAUSE_SET -============ +========= Sets pause parameters like ``ETHTOOL_GPAUSEPARAM`` ioctl request. @@ -1024,7 +1024,7 @@ Request contents: EEE_GET ======= -Gets channel counts like ``ETHTOOL_GEEE`` ioctl request. +Gets Energy Efficient Ethernet settings like ``ETHTOOL_GEEE`` ioctl request. Request contents: @@ -1054,7 +1054,7 @@ first 32 are provided by the ``ethtool_ops`` callback. EEE_SET ======= -Sets pause parameters like ``ETHTOOL_GEEEPARAM`` ioctl request. +Sets Energy Efficient Ethernet parameters like ``ETHTOOL_SEEE`` ioctl request. Request contents: From 4f0ed93fb92d3528c73c80317509df3f800a222b Mon Sep 17 00:00:00 2001 From: Al Viro Date: Tue, 6 Apr 2021 19:46:51 -0400 Subject: [PATCH 0753/1091] LOOKUP_MOUNTPOINT: we are cleaning "jumped" flag too late That (and traversals in case of umount .) should be done before complete_walk(). Either a braino or mismerge damage on queue reorders - either way, I should've spotted that much earlier. Fucked-up-by: Al Viro X-Paperbag: Brown Fixes: 161aff1d93ab "LOOKUP_MOUNTPOINT: fold path_mountpointat() into path_lookupat()" Cc: stable@vger.kernel.org # v5.7+ Signed-off-by: Al Viro --- fs/namei.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/fs/namei.c b/fs/namei.c index fc8760d4314e..48a2f288e802 100644 --- a/fs/namei.c +++ b/fs/namei.c @@ -2421,16 +2421,16 @@ static int path_lookupat(struct nameidata *nd, unsigned flags, struct path *path while (!(err = link_path_walk(s, nd)) && (s = lookup_last(nd)) != NULL) ; + if (!err && unlikely(nd->flags & LOOKUP_MOUNTPOINT)) { + err = handle_lookup_down(nd); + nd->flags &= ~LOOKUP_JUMPED; // no d_weak_revalidate(), please... + } if (!err) err = complete_walk(nd); if (!err && nd->flags & LOOKUP_DIRECTORY) if (!d_can_lookup(nd->path.dentry)) err = -ENOTDIR; - if (!err && unlikely(nd->flags & LOOKUP_MOUNTPOINT)) { - err = handle_lookup_down(nd); - nd->flags &= ~LOOKUP_JUMPED; // no d_weak_revalidate(), please... - } if (!err) { *path = nd->path; nd->path.mnt = NULL; From 1a73704c82ed4ee95532ac04645d02075bd1ce3d Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Wed, 24 Mar 2021 09:46:09 +0200 Subject: [PATCH 0754/1091] net/mlx5: Fix HW spec violation configuring uplink Make sure to modify uplink port to follow only if the uplink_follow capability is set as required by the HW spec. Failure to do so causes traffic to the uplink representor net device to cease after switching to switchdev mode. Fixes: 7d0314b11cdd ("net/mlx5e: Modify uplink state on interface up/down") Signed-off-by: Eli Cohen Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_rep.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c index a132fff7a980..8d39bfee84a9 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_rep.c @@ -1107,8 +1107,9 @@ static void mlx5e_uplink_rep_enable(struct mlx5e_priv *priv) mlx5e_rep_tc_enable(priv); - mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK, - 0, 0, MLX5_VPORT_ADMIN_STATE_AUTO); + if (MLX5_CAP_GEN(mdev, uplink_follow)) + mlx5_modify_vport_admin_state(mdev, MLX5_VPORT_STATE_OP_MOD_UPLINK, + 0, 0, MLX5_VPORT_ADMIN_STATE_AUTO); mlx5_lag_add(mdev, netdev); priv->events_nb.notifier_call = uplink_rep_async_event; mlx5_notifier_register(mdev, &priv->events_nb); From a14587dfc5ad2312dabdd42a610d80ecd0dc8bea Mon Sep 17 00:00:00 2001 From: Raed Salem Date: Thu, 21 Jan 2021 16:01:37 +0200 Subject: [PATCH 0755/1091] net/mlx5: Fix placement of log_max_flow_counter The cited commit wrongly placed log_max_flow_counter field of mlx5_ifc_flow_table_prop_layout_bits, align it to the HW spec intended placement. Fixes: 16f1c5bb3ed7 ("net/mlx5: Check device capability for maximum flow counters") Signed-off-by: Raed Salem Reviewed-by: Roi Dayan Signed-off-by: Saeed Mahameed --- include/linux/mlx5/mlx5_ifc.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index df5d91c8b2d4..1ccedb7816d0 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -437,11 +437,11 @@ struct mlx5_ifc_flow_table_prop_layout_bits { u8 reserved_at_60[0x18]; u8 log_max_ft_num[0x8]; - u8 reserved_at_80[0x18]; + u8 reserved_at_80[0x10]; + u8 log_max_flow_counter[0x8]; u8 log_max_destination[0x8]; - u8 log_max_flow_counter[0x8]; - u8 reserved_at_a8[0x10]; + u8 reserved_at_a0[0x18]; u8 log_max_flow[0x8]; u8 reserved_at_c0[0x40]; From ce28f0fd670ddffcd564ce7119bdefbaf08f02d3 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Sun, 4 Apr 2021 10:50:50 +0300 Subject: [PATCH 0756/1091] net/mlx5: Fix PPLM register mapping Add reserved mapping to cover all the register in order to avoid setting arbitrary values to newer FW which implements the reserved fields. Fixes: a58837f52d43 ("net/mlx5e: Expose FEC feilds and related capability bit") Signed-off-by: Aya Levin Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- include/linux/mlx5/mlx5_ifc.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 1ccedb7816d0..9940070cda8f 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -8835,6 +8835,8 @@ struct mlx5_ifc_pplm_reg_bits { u8 fec_override_admin_100g_2x[0x10]; u8 fec_override_admin_50g_1x[0x10]; + + u8 reserved_at_140[0x140]; }; struct mlx5_ifc_ppcnt_reg_bits { From 534b1204ca4694db1093b15cf3e79a99fcb6a6da Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Sun, 4 Apr 2021 12:55:00 +0300 Subject: [PATCH 0757/1091] net/mlx5: Fix PBMC register mapping Add reserved mapping to cover all the register in order to avoid setting arbitrary values to newer FW which implements the reserved fields. Fixes: 50b4a3c23646 ("net/mlx5: PPTB and PBMC register firmware command support") Signed-off-by: Aya Levin Reviewed-by: Moshe Shemesh Signed-off-by: Saeed Mahameed --- include/linux/mlx5/mlx5_ifc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/mlx5/mlx5_ifc.h b/include/linux/mlx5/mlx5_ifc.h index 9940070cda8f..9c68b2da14c6 100644 --- a/include/linux/mlx5/mlx5_ifc.h +++ b/include/linux/mlx5/mlx5_ifc.h @@ -10200,7 +10200,7 @@ struct mlx5_ifc_pbmc_reg_bits { struct mlx5_ifc_bufferx_reg_bits buffer[10]; - u8 reserved_at_2e0[0x40]; + u8 reserved_at_2e0[0x80]; }; struct mlx5_ifc_qtct_reg_bits { From d5f9b005c3062d6d96872896b695e5116b921f52 Mon Sep 17 00:00:00 2001 From: Xiaoming Ni Date: Mon, 5 Apr 2021 10:53:39 +0800 Subject: [PATCH 0758/1091] net/mlx5: fix kfree mismatch in indir_table.c Memory allocated by kvzalloc() should be freed by kvfree(). Fixes: 34ca65352ddf2 ("net/mlx5: E-Switch, Indirect table infrastructur") Signed-off-by: Xiaoming Ni Reviewed-by: Leon Romanovsky Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/esw/indir_table.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/esw/indir_table.c b/drivers/net/ethernet/mellanox/mlx5/core/esw/indir_table.c index 6f6772bf61a2..3da7becc1069 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/esw/indir_table.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/esw/indir_table.c @@ -248,7 +248,7 @@ err_mod_hdr_regc0: err_ethertype: kfree(rule); out: - kfree(rule_spec); + kvfree(rule_spec); return err; } @@ -328,7 +328,7 @@ static int mlx5_create_indir_recirc_group(struct mlx5_eswitch *esw, e->recirc_cnt = 0; out: - kfree(in); + kvfree(in); return err; } @@ -347,7 +347,7 @@ static int mlx5_create_indir_fwd_group(struct mlx5_eswitch *esw, spec = kvzalloc(sizeof(*spec), GFP_KERNEL); if (!spec) { - kfree(in); + kvfree(in); return -ENOMEM; } @@ -371,8 +371,8 @@ static int mlx5_create_indir_fwd_group(struct mlx5_eswitch *esw, } err_out: - kfree(spec); - kfree(in); + kvfree(spec); + kvfree(in); return err; } From 3a62583c2853b0ab37a57dde79decea210b5fb89 Mon Sep 17 00:00:00 2001 From: William Roche Date: Tue, 6 Apr 2021 11:28:59 -0400 Subject: [PATCH 0759/1091] RAS/CEC: Correct ce_add_elem()'s returned values ce_add_elem() uses different return values to signal a result from adding an element to the collector. Commit in Fixes: broke the case where the element being added is not found in the array. Correct that. [ bp: Rewrite commit message, add kernel-doc comments. ] Fixes: de0e0624d86f ("RAS/CEC: Check count_threshold unconditionally") Signed-off-by: William Roche Signed-off-by: Borislav Petkov Cc: Link: https://lkml.kernel.org/r/1617722939-29670-1-git-send-email-william.roche@oracle.com --- drivers/ras/cec.c | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/drivers/ras/cec.c b/drivers/ras/cec.c index ddecf25b5dd4..d7894f178bd4 100644 --- a/drivers/ras/cec.c +++ b/drivers/ras/cec.c @@ -309,11 +309,20 @@ static bool sanity_check(struct ce_array *ca) return ret; } +/** + * cec_add_elem - Add an element to the CEC array. + * @pfn: page frame number to insert + * + * Return values: + * - <0: on error + * - 0: on success + * - >0: when the inserted pfn was offlined + */ static int cec_add_elem(u64 pfn) { struct ce_array *ca = &ce_arr; + int count, err, ret = 0; unsigned int to = 0; - int count, ret = 0; /* * We can be called very early on the identify_cpu() path where we are @@ -330,8 +339,8 @@ static int cec_add_elem(u64 pfn) if (ca->n == MAX_ELEMS) WARN_ON(!del_lru_elem_unlocked(ca)); - ret = find_elem(ca, pfn, &to); - if (ret < 0) { + err = find_elem(ca, pfn, &to); + if (err < 0) { /* * Shift range [to-end] to make room for one more element. */ From fbb9e86636ba8aa4d890091ab06cc7b2f4751322 Mon Sep 17 00:00:00 2001 From: Chen-Yu Tsai Date: Mon, 4 Jan 2021 16:19:17 +0800 Subject: [PATCH 0760/1091] arm64: dts: allwinner: h6: Switch to macros for RSB clock/reset indices The macros for the clock and reset indices for the RSB hardware block were replaced with raw numbers when the RSB controller node was added. This was done to avoid cross-tree dependencies. Now that both the clk and DT changes have been merged, we can switch back to using the macros. Signed-off-by: Chen-Yu Tsai Signed-off-by: Maxime Ripard --- arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi index 49e979794094..af8b7d0ef750 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6.dtsi @@ -995,9 +995,9 @@ compatible = "allwinner,sun8i-a23-rsb"; reg = <0x07083000 0x400>; interrupts = ; - clocks = <&r_ccu 13>; + clocks = <&r_ccu CLK_R_APB2_RSB>; clock-frequency = <3000000>; - resets = <&r_ccu 7>; + resets = <&r_ccu RST_R_APB2_RSB>; pinctrl-names = "default"; pinctrl-0 = <&r_rsb_pins>; status = "disabled"; From 3dd4ce4185df6798dcdcc3669bddb35899d7d5e1 Mon Sep 17 00:00:00 2001 From: Andre Przywara Date: Tue, 16 Mar 2021 14:42:19 +0000 Subject: [PATCH 0761/1091] arm64: dts: allwinner: Fix SD card CD GPIO for SOPine systems Commit 941432d00768 ("arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card") enabled the card detect GPIO for the SOPine module, along the way with the Pine64-LTS, which share the same base .dtsi. However while both boards indeed have a working CD GPIO on PF6, the polarity is different: the SOPine modules uses a "push-pull" socket, which has an active-high switch, while the Pine64-LTS use the more traditional push-push socket and the common active-low switch. Fix the polarity in the sopine.dtsi, and overwrite it in the LTS board .dts, to make the SD card work again on systems using SOPine modules. Fixes: 941432d00768 ("arm64: dts: allwinner: Drop non-removable from SoPine/LTS SD card") Reported-by: Ashley Signed-off-by: Andre Przywara Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210316144219.5973-1-andre.przywara@arm.com --- arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts | 4 ++++ arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts index 437ffe3628a5..e79ce49e7e6a 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-pine64-lts.dts @@ -19,3 +19,7 @@ }; }; }; + +&mmc0 { + cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 push-push switch */ +}; diff --git a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi index 3402cec87035..df62044ff7a7 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi +++ b/arch/arm64/boot/dts/allwinner/sun50i-a64-sopine.dtsi @@ -34,7 +34,7 @@ vmmc-supply = <®_dcdc1>; disable-wp; bus-width = <4>; - cd-gpios = <&pio 5 6 GPIO_ACTIVE_LOW>; /* PF6 */ + cd-gpios = <&pio 5 6 GPIO_ACTIVE_HIGH>; /* PF6 push-pull switch */ status = "okay"; }; From c89f3af3b5ba4d8b232c7b397e54dd228c49f6b1 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 31 Mar 2021 15:08:29 +0200 Subject: [PATCH 0762/1091] MAINTAINERS: Add our new mailing-list We've been struggling to get an LF-hosted mailing list for a while, but now that lists.linux.dev is there we opted in. Let's add it to MAINTAINERS. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Acked-by: Jernej Skrabec Link: https://lore.kernel.org/r/20210331130830.64182-1-maxime@cerno.tech --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index d92f85ca831d..d8c00df4045c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1576,6 +1576,7 @@ R: Jernej Skrabec L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Maintained T: git git://git.kernel.org/pub/scm/linux/kernel/git/sunxi/linux.git +L: linux-sunxi@lists.linux.dev F: arch/arm/mach-sunxi/ F: arch/arm64/boot/dts/allwinner/ F: drivers/clk/sunxi-ng/ From 2a996ecd142df9ff2369241fd62ab7778ef07874 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Wed, 31 Mar 2021 15:08:30 +0200 Subject: [PATCH 0763/1091] MAINTAINERS: Match on allwinner keyword Some drivers (phy, crypto, net) folders don't have sunxi in it but allwinner. Add that keyword to match on it too. Signed-off-by: Maxime Ripard Acked-by: Chen-Yu Tsai Acked-by: Jernej Skrabec Link: https://lore.kernel.org/r/20210331130830.64182-2-maxime@cerno.tech --- MAINTAINERS | 1 + 1 file changed, 1 insertion(+) diff --git a/MAINTAINERS b/MAINTAINERS index d8c00df4045c..5e808daae799 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1582,6 +1582,7 @@ F: arch/arm64/boot/dts/allwinner/ F: drivers/clk/sunxi-ng/ F: drivers/pinctrl/sunxi/ F: drivers/soc/sunxi/ +N: allwinner N: sun[x456789]i N: sun50i From 7a2f6e69e9c1060a7a09c1f8322ccb8d942b3078 Mon Sep 17 00:00:00 2001 From: Jernej Skrabec Date: Tue, 30 Mar 2021 20:42:18 +0200 Subject: [PATCH 0764/1091] arm64: dts: allwinner: h6: beelink-gs1: Remove ext. 32 kHz osc reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Although every Beelink GS1 seems to have external 32768 Hz oscillator, it works only on one from four tested. There are more reports of RTC issues elsewhere, like Armbian forum. One Beelink GS1 owner read RTC osc status register on Android which shipped with the box. Reported value indicated problems with external oscillator. In order to fix RTC and related issues (HDMI-CEC and suspend/resume with Crust) on all boards, switch to internal oscillator. Fixes: 32507b868119 ("arm64: dts: allwinner: h6: Move ext. oscillator to board DTs") Signed-off-by: Jernej Skrabec Tested-by: Clément Péron Signed-off-by: Maxime Ripard Link: https://lore.kernel.org/r/20210330184218.279738-1-jernej.skrabec@siol.net --- arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts | 4 ---- 1 file changed, 4 deletions(-) diff --git a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts index 4f4755152fce..b5808047d6e4 100644 --- a/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts +++ b/arch/arm64/boot/dts/allwinner/sun50i-h6-beelink-gs1.dts @@ -289,10 +289,6 @@ vcc-pm-supply = <®_aldo1>; }; -&rtc { - clocks = <&ext_osc32k>; -}; - &spdif { status = "okay"; }; From ad31a8c05196a3dc5283b193e9c74a72022d3c65 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 5 Apr 2021 22:32:27 +0200 Subject: [PATCH 0765/1091] s390/setup: use memblock_free_late() to free old stack Use memblock_free_late() to free the old machine check stack to the buddy allocator instead of leaking it. Fixes: b61b1595124a ("s390: add stack for machine check handler") Cc: Vasily Gorbik Acked-by: Sven Schnelle Signed-off-by: Heiko Carstens --- arch/s390/kernel/setup.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/s390/kernel/setup.c b/arch/s390/kernel/setup.c index 60da976eee6f..72134f9f6ff5 100644 --- a/arch/s390/kernel/setup.c +++ b/arch/s390/kernel/setup.c @@ -354,7 +354,7 @@ static int __init stack_realloc(void) if (!new) panic("Couldn't allocate machine check stack"); WRITE_ONCE(S390_lowcore.mcck_stack, new + STACK_INIT_OFFSET); - memblock_free(old, THREAD_SIZE); + memblock_free_late(old, THREAD_SIZE); return 0; } early_initcall(stack_realloc); From d120198bd5ff1d41808b6914e1eb89aff937415c Mon Sep 17 00:00:00 2001 From: Luca Fancellu Date: Tue, 6 Apr 2021 11:51:04 +0100 Subject: [PATCH 0766/1091] xen/evtchn: Change irq_info lock to raw_spinlock_t Unmask operation must be called with interrupt disabled, on preempt_rt spin_lock_irqsave/spin_unlock_irqrestore don't disable/enable interrupts, so use raw_* implementation and change lock variable in struct irq_info from spinlock_t to raw_spinlock_t Cc: stable@vger.kernel.org Fixes: 25da4618af24 ("xen/events: don't unmask an event channel when an eoi is pending") Signed-off-by: Luca Fancellu Reviewed-by: Julien Grall Reviewed-by: Wei Liu Link: https://lore.kernel.org/r/20210406105105.10141-1-luca.fancellu@arm.com Signed-off-by: Boris Ostrovsky --- drivers/xen/events/events_base.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/drivers/xen/events/events_base.c b/drivers/xen/events/events_base.c index 8236e2364eeb..7bbfd58958bc 100644 --- a/drivers/xen/events/events_base.c +++ b/drivers/xen/events/events_base.c @@ -110,7 +110,7 @@ struct irq_info { unsigned short eoi_cpu; /* EOI must happen on this cpu-1 */ unsigned int irq_epoch; /* If eoi_cpu valid: irq_epoch of event */ u64 eoi_time; /* Time in jiffies when to EOI. */ - spinlock_t lock; + raw_spinlock_t lock; union { unsigned short virq; @@ -312,7 +312,7 @@ static int xen_irq_info_common_setup(struct irq_info *info, info->evtchn = evtchn; info->cpu = cpu; info->mask_reason = EVT_MASK_REASON_EXPLICIT; - spin_lock_init(&info->lock); + raw_spin_lock_init(&info->lock); ret = set_evtchn_to_irq(evtchn, irq); if (ret < 0) @@ -472,28 +472,28 @@ static void do_mask(struct irq_info *info, u8 reason) { unsigned long flags; - spin_lock_irqsave(&info->lock, flags); + raw_spin_lock_irqsave(&info->lock, flags); if (!info->mask_reason) mask_evtchn(info->evtchn); info->mask_reason |= reason; - spin_unlock_irqrestore(&info->lock, flags); + raw_spin_unlock_irqrestore(&info->lock, flags); } static void do_unmask(struct irq_info *info, u8 reason) { unsigned long flags; - spin_lock_irqsave(&info->lock, flags); + raw_spin_lock_irqsave(&info->lock, flags); info->mask_reason &= ~reason; if (!info->mask_reason) unmask_evtchn(info->evtchn); - spin_unlock_irqrestore(&info->lock, flags); + raw_spin_unlock_irqrestore(&info->lock, flags); } #ifdef CONFIG_X86 From 6f68accaa8641b70b698da659216f82f87537869 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 7 Apr 2021 16:57:14 +0200 Subject: [PATCH 0767/1091] ASoC: meson: axg-frddr: set fifo depth according to the period When the period is small, using all the FRDDR fifo depth increases the latency of the playback because the following device won't start pulling data until the fifo reaches the depth set. We can adjust this depth so trim it down for small periods. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210407145714.311138-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-frddr.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index c3ae8ac30745..8ed114de0bdf 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c @@ -11,6 +11,7 @@ #include #include #include +#include #include #include @@ -46,11 +47,28 @@ static int g12a_frddr_dai_prepare(struct snd_pcm_substream *substream, return 0; } +static int axg_frddr_dai_hw_params(struct snd_pcm_substream *substream, + struct snd_pcm_hw_params *params, + struct snd_soc_dai *dai) +{ + struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); + unsigned int period, depth, val; + + period = params_period_bytes(params); + + /* Trim the FIFO depth if the period is small to improve latency */ + depth = min(period, fifo->depth); + val = (depth / AXG_FIFO_BURST) - 1; + regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK, + CTRL1_FRDDR_DEPTH(val)); + + return 0; +} + static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, struct snd_soc_dai *dai) { struct axg_fifo *fifo = snd_soc_dai_get_drvdata(dai); - unsigned int val; int ret; /* Enable pclk to access registers and clock the fifo ip */ @@ -61,11 +79,6 @@ static int axg_frddr_dai_startup(struct snd_pcm_substream *substream, /* Apply single buffer mode to the interface */ regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_FRDDR_PP_MODE, 0); - /* Use all fifo depth */ - val = (fifo->depth / AXG_FIFO_BURST) - 1; - regmap_update_bits(fifo->map, FIFO_CTRL1, CTRL1_FRDDR_DEPTH_MASK, - CTRL1_FRDDR_DEPTH(val)); - return 0; } @@ -84,6 +97,7 @@ static int axg_frddr_pcm_new(struct snd_soc_pcm_runtime *rtd, } static const struct snd_soc_dai_ops axg_frddr_ops = { + .hw_params = axg_frddr_dai_hw_params, .startup = axg_frddr_dai_startup, .shutdown = axg_frddr_dai_shutdown, }; From 73a4808892b83c8336c3d913d44b8de68d881369 Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Tue, 6 Apr 2021 16:24:36 +0200 Subject: [PATCH 0768/1091] ASoC: codecs: tlv320aic3x: move model definitions Model definitions moved to header file. Preparation for SPI and I2C separated files. Signed-off-by: Jiri Prchal Link: https://lore.kernel.org/r/20210406142439.102396-2-jiri.prchal@aksignal.cz Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 4 ---- sound/soc/codecs/tlv320aic3x.h | 5 +++++ 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index db1444127444..812f0f117fd3 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -82,10 +82,6 @@ struct aic3x_priv { int master; int gpio_reset; int power; -#define AIC3X_MODEL_3X 0 -#define AIC3X_MODEL_33 1 -#define AIC3X_MODEL_3007 2 -#define AIC3X_MODEL_3104 3 u16 model; /* Selects the micbias voltage */ diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 66d3580cf2b1..21dd6edf1059 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -9,6 +9,11 @@ #ifndef _AIC3X_H #define _AIC3X_H +#define AIC3X_MODEL_3X 0 +#define AIC3X_MODEL_33 1 +#define AIC3X_MODEL_3007 2 +#define AIC3X_MODEL_3104 3 + /* AIC3X register space */ #define AIC3X_CACHEREGNUM 110 From b015df6ac03ee81b259dcb2f1a6faf4cf04ace5a Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Tue, 6 Apr 2021 16:24:37 +0200 Subject: [PATCH 0769/1091] ASoC: codecs: tlv320aic3x: rename probe function Renamed function to have it free for generic probe. Signed-off-by: Jiri Prchal Link: https://lore.kernel.org/r/20210406142439.102396-3-jiri.prchal@aksignal.cz Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 812f0f117fd3..6549ad9296ce 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1610,7 +1610,7 @@ static bool aic3x_is_shared_reset(struct aic3x_priv *aic3x) return false; } -static int aic3x_probe(struct snd_soc_component *component) +static int aic3x_component_probe(struct snd_soc_component *component) { struct aic3x_priv *aic3x = snd_soc_component_get_drvdata(component); int ret, i; @@ -1689,7 +1689,7 @@ static int aic3x_probe(struct snd_soc_component *component) static const struct snd_soc_component_driver soc_component_dev_aic3x = { .set_bias_level = aic3x_set_bias_level, - .probe = aic3x_probe, + .probe = aic3x_component_probe, .controls = aic3x_snd_controls, .num_controls = ARRAY_SIZE(aic3x_snd_controls), .dapm_widgets = aic3x_dapm_widgets, From a96d2ba2d8248d5e8170f2f44f98d4a33329b08a Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Tue, 6 Apr 2021 16:24:38 +0200 Subject: [PATCH 0770/1091] ASoC: codecs: tlv320aic3x: move I2C to separated file Moved I2C related staff to separated source file. Signed-off-by: Jiri Prchal Link: https://lore.kernel.org/r/20210406142439.102396-4-jiri.prchal@aksignal.cz Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 9 ++- sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tlv320aic3x-i2c.c | 70 ++++++++++++++++++++ sound/soc/codecs/tlv320aic3x.c | 100 ++++++++--------------------- sound/soc/codecs/tlv320aic3x.h | 7 ++ 5 files changed, 112 insertions(+), 76 deletions(-) create mode 100644 sound/soc/codecs/tlv320aic3x-i2c.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index 6d9cb00aa3d2..b0323dbabf11 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -218,7 +218,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TLV320AIC31XX imply SND_SOC_TLV320AIC32X4_I2C imply SND_SOC_TLV320AIC32X4_SPI - imply SND_SOC_TLV320AIC3X + imply SND_SOC_TLV320AIC3X_I2C imply SND_SOC_TPA6130A2 imply SND_SOC_TLV320DAC33 imply SND_SOC_TSCS42XX @@ -1446,8 +1446,13 @@ config SND_SOC_TLV320AIC32X4_SPI select SND_SOC_TLV320AIC32X4 config SND_SOC_TLV320AIC3X - tristate "Texas Instruments TLV320AIC3x CODECs" + tristate + +config SND_SOC_TLV320AIC3X_I2C + tristate "Texas Instruments TLV320AIC3x audio CODECs - I2C" depends on I2C + select SND_SOC_TLV320AIC3X + select REGMAP_I2C config SND_SOC_TLV320DAC33 tristate diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index 1d8980be7019..f014ea9f2318 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -238,6 +238,7 @@ snd-soc-tlv320aic32x4-objs := tlv320aic32x4.o tlv320aic32x4-clk.o snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o +snd-soc-tlv320aic3x-i2c-objs := tlv320aic3x-i2c.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-tlv320adcx140-objs := tlv320adcx140.o snd-soc-tscs42xx-objs := tscs42xx.o @@ -558,6 +559,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC32X4) += snd-soc-tlv320aic32x4.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4_SPI) += snd-soc-tlv320aic32x4-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o +obj-$(CONFIG_SND_SOC_TLV320AIC3X_I2C) += snd-soc-tlv320aic3x-i2c.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TLV320ADCX140) += snd-soc-tlv320adcx140.o obj-$(CONFIG_SND_SOC_TSCS42XX) += snd-soc-tscs42xx.o diff --git a/sound/soc/codecs/tlv320aic3x-i2c.c b/sound/soc/codecs/tlv320aic3x-i2c.c new file mode 100644 index 000000000000..4535bb8dbadc --- /dev/null +++ b/sound/soc/codecs/tlv320aic3x-i2c.c @@ -0,0 +1,70 @@ +/* SPDX-License-Identifier: GPL-2.0-only + * + * ALSA SoC TLV320AIC3x codec driver I2C interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + */ + +#include +#include +#include +#include +#include + +#include "tlv320aic3x.h" + +static int aic3x_i2c_probe(struct i2c_client *i2c, const struct i2c_device_id *id) +{ + struct regmap *regmap; + struct regmap_config config; + + config = aic3x_regmap; + config.reg_bits = 8; + config.val_bits = 8; + + regmap = devm_regmap_init_i2c(i2c, &config); + return aic3x_probe(&i2c->dev, regmap, id->driver_data); +} + +static int aic3x_i2c_remove(struct i2c_client *i2c) +{ + return aic3x_remove(&i2c->dev); +} + +static const struct i2c_device_id aic3x_i2c_id[] = { + { "tlv320aic3x", AIC3X_MODEL_3X }, + { "tlv320aic33", AIC3X_MODEL_33 }, + { "tlv320aic3007", AIC3X_MODEL_3007 }, + { "tlv320aic3104", AIC3X_MODEL_3104 }, + { } +}; +MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); + +static const struct of_device_id aic3x_of_id[] = { + { .compatible = "ti,tlv320aic3x", }, + { .compatible = "ti,tlv320aic33" }, + { .compatible = "ti,tlv320aic3007" }, + { .compatible = "ti,tlv320aic3104" }, + {}, +}; +MODULE_DEVICE_TABLE(of, aic3x_of_id); + +static struct i2c_driver aic3x_i2c_driver = { + .driver = { + .name = "tlv320aic3x", + .of_match_table = aic3x_of_id, + }, + .probe = aic3x_i2c_probe, + .remove = aic3x_i2c_remove, + .id_table = aic3x_i2c_id, +}; + +module_i2c_driver(aic3x_i2c_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC3x codec driver I2C"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 6549ad9296ce..2f351747b714 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-2.0-only -/* - * ALSA SoC TLV320AIC3X codec driver +/* ALSA SoC TLV320AIC3X codec driver * * Author: Vladimir Barinov, * Copyright: (C) 2007 MontaVista Software, Inc., @@ -131,10 +130,7 @@ static bool aic3x_volatile_reg(struct device *dev, unsigned int reg) } } -static const struct regmap_config aic3x_regmap = { - .reg_bits = 8, - .val_bits = 8, - +const struct regmap_config aic3x_regmap = { .max_register = DAC_ICC_ADJ, .reg_defaults = aic3x_reg, .num_reg_defaults = ARRAY_SIZE(aic3x_reg), @@ -143,6 +139,7 @@ static const struct regmap_config aic3x_regmap = { .cache_type = REGCACHE_RBTREE, }; +EXPORT_SYMBOL_GPL(aic3x_regmap); #define SOC_DAPM_SINGLE_AIC3X(xname, reg, shift, mask, invert) \ SOC_SINGLE_EXT(xname, reg, shift, mask, invert, \ @@ -1701,10 +1698,9 @@ static const struct snd_soc_component_driver soc_component_dev_aic3x = { .non_legacy_dai_naming = 1, }; -static void aic3x_configure_ocmv(struct i2c_client *client) +static void aic3x_configure_ocmv(struct device *dev, struct aic3x_priv *aic3x) { - struct device_node *np = client->dev.of_node; - struct aic3x_priv *aic3x = i2c_get_clientdata(client); + struct device_node *np = dev->of_node; u32 value; int dvdd, avdd; @@ -1720,7 +1716,7 @@ static void aic3x_configure_ocmv(struct i2c_client *client) avdd = regulator_get_voltage(aic3x->supplies[2].consumer); if (avdd > 3600000 || dvdd > 1950000) { - dev_warn(&client->dev, + dev_warn(dev, "Too high supply voltage(s) AVDD: %d, DVDD: %d\n", avdd, dvdd); } else if (avdd == 3600000 && dvdd == 1950000) { @@ -1732,26 +1728,12 @@ static void aic3x_configure_ocmv(struct i2c_client *client) } else if (avdd >= 2700000 && dvdd >= 1525000) { aic3x->ocmv = HPOUT_SC_OCMV_1_35V; } else { - dev_warn(&client->dev, + dev_warn(dev, "Invalid supply voltage(s) AVDD: %d, DVDD: %d\n", avdd, dvdd); } } -/* - * AIC3X 2 wire address can be up to 4 devices with device addresses - * 0x18, 0x19, 0x1A, 0x1B - */ - -static const struct i2c_device_id aic3x_i2c_id[] = { - { "tlv320aic3x", AIC3X_MODEL_3X }, - { "tlv320aic33", AIC3X_MODEL_33 }, - { "tlv320aic3007", AIC3X_MODEL_3007 }, - { "tlv320aic3106", AIC3X_MODEL_3X }, - { "tlv320aic3104", AIC3X_MODEL_3104 }, - { } -}; -MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); static const struct reg_sequence aic3007_class_d[] = { /* Class-D speaker driver init; datasheet p. 46 */ @@ -1763,25 +1745,20 @@ static const struct reg_sequence aic3007_class_d[] = { { AIC3X_PAGE_SELECT, 0x00 }, }; -/* - * If the i2c layer weren't so broken, we could pass this kind of data - * around - */ -static int aic3x_i2c_probe(struct i2c_client *i2c, - const struct i2c_device_id *id) +int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver_data) { - struct aic3x_pdata *pdata = i2c->dev.platform_data; + struct aic3x_pdata *pdata = dev->platform_data; struct aic3x_priv *aic3x; struct aic3x_setup_data *ai3x_setup; - struct device_node *np = i2c->dev.of_node; + struct device_node *np = dev->of_node; int ret, i; u32 value; - aic3x = devm_kzalloc(&i2c->dev, sizeof(struct aic3x_priv), GFP_KERNEL); + aic3x = devm_kzalloc(dev, sizeof(struct aic3x_priv), GFP_KERNEL); if (!aic3x) return -ENOMEM; - aic3x->regmap = devm_regmap_init_i2c(i2c, &aic3x_regmap); + aic3x->regmap = regmap; if (IS_ERR(aic3x->regmap)) { ret = PTR_ERR(aic3x->regmap); return ret; @@ -1789,14 +1766,13 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, regcache_cache_only(aic3x->regmap, true); - i2c_set_clientdata(i2c, aic3x); + dev_set_drvdata(dev, aic3x); if (pdata) { aic3x->gpio_reset = pdata->gpio_reset; aic3x->setup = pdata->setup; aic3x->micbias_vg = pdata->micbias_vg; } else if (np) { - ai3x_setup = devm_kzalloc(&i2c->dev, sizeof(*ai3x_setup), - GFP_KERNEL); + ai3x_setup = devm_kzalloc(dev, sizeof(*ai3x_setup), GFP_KERNEL); if (!ai3x_setup) return -ENOMEM; @@ -1806,7 +1782,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, } else { ret = of_get_named_gpio(np, "gpio-reset", 0); if (ret > 0) { - dev_warn(&i2c->dev, "Using deprecated property \"gpio-reset\", please update your DT"); + dev_warn(dev, "Using deprecated property \"gpio-reset\", please update your DT"); aic3x->gpio_reset = ret; } else { aic3x->gpio_reset = -1; @@ -1831,7 +1807,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, break; default : aic3x->micbias_vg = AIC3X_MICBIAS_OFF; - dev_err(&i2c->dev, "Unsuitable MicBias voltage " + dev_err(dev, "Unsuitable MicBias voltage " "found in DT\n"); } } else { @@ -1842,7 +1818,7 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, aic3x->gpio_reset = -1; } - aic3x->model = id->driver_data; + aic3x->model = driver_data; if (gpio_is_valid(aic3x->gpio_reset) && !aic3x_is_shared_reset(aic3x)) { @@ -1855,25 +1831,24 @@ static int aic3x_i2c_probe(struct i2c_client *i2c, for (i = 0; i < ARRAY_SIZE(aic3x->supplies); i++) aic3x->supplies[i].supply = aic3x_supply_names[i]; - ret = devm_regulator_bulk_get(&i2c->dev, ARRAY_SIZE(aic3x->supplies), + ret = devm_regulator_bulk_get(dev, ARRAY_SIZE(aic3x->supplies), aic3x->supplies); if (ret != 0) { - dev_err(&i2c->dev, "Failed to request supplies: %d\n", ret); + dev_err(dev, "Failed to request supplies: %d\n", ret); goto err_gpio; } - aic3x_configure_ocmv(i2c); + aic3x_configure_ocmv(dev, aic3x); if (aic3x->model == AIC3X_MODEL_3007) { ret = regmap_register_patch(aic3x->regmap, aic3007_class_d, ARRAY_SIZE(aic3007_class_d)); if (ret != 0) - dev_err(&i2c->dev, "Failed to init class D: %d\n", + dev_err(dev, "Failed to init class D: %d\n", ret); } - ret = devm_snd_soc_register_component(&i2c->dev, - &soc_component_dev_aic3x, &aic3x_dai, 1); + ret = devm_snd_soc_register_component(dev, &soc_component_dev_aic3x, &aic3x_dai, 1); if (ret != 0) goto err_gpio; @@ -1890,10 +1865,11 @@ err_gpio: err: return ret; } +EXPORT_SYMBOL(aic3x_probe); -static int aic3x_i2c_remove(struct i2c_client *client) +int aic3x_remove(struct device *dev) { - struct aic3x_priv *aic3x = i2c_get_clientdata(client); + struct aic3x_priv *aic3x = dev_get_drvdata(dev); list_del(&aic3x->list); @@ -1904,31 +1880,7 @@ static int aic3x_i2c_remove(struct i2c_client *client) } return 0; } - -#if defined(CONFIG_OF) -static const struct of_device_id tlv320aic3x_of_match[] = { - { .compatible = "ti,tlv320aic3x", }, - { .compatible = "ti,tlv320aic33" }, - { .compatible = "ti,tlv320aic3007" }, - { .compatible = "ti,tlv320aic3106" }, - { .compatible = "ti,tlv320aic3104" }, - {}, -}; -MODULE_DEVICE_TABLE(of, tlv320aic3x_of_match); -#endif - -/* machine i2c codec control layer */ -static struct i2c_driver aic3x_i2c_driver = { - .driver = { - .name = "tlv320aic3x-codec", - .of_match_table = of_match_ptr(tlv320aic3x_of_match), - }, - .probe = aic3x_i2c_probe, - .remove = aic3x_i2c_remove, - .id_table = aic3x_i2c_id, -}; - -module_i2c_driver(aic3x_i2c_driver); +EXPORT_SYMBOL(aic3x_remove); MODULE_DESCRIPTION("ASoC TLV320AIC3X codec driver"); MODULE_AUTHOR("Vladimir Barinov"); diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 21dd6edf1059..00908f1734a7 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -9,6 +9,13 @@ #ifndef _AIC3X_H #define _AIC3X_H +struct device; +struct regmap_config; + +extern const struct regmap_config aic3x_regmap; +int aic3x_probe(struct device *dev, struct regmap *regmap, kernel_ulong_t driver_data); +int aic3x_remove(struct device *dev); + #define AIC3X_MODEL_3X 0 #define AIC3X_MODEL_33 1 #define AIC3X_MODEL_3007 2 From fd4daab3b139a24e71cae5de4f0ca715dbb6634a Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Tue, 6 Apr 2021 16:24:39 +0200 Subject: [PATCH 0771/1091] ASoC: codecs: tlv320aic3x: add SPI support Added SPI support. Signed-off-by: Jiri Prchal Link: https://lore.kernel.org/r/20210406142439.102396-5-jiri.prchal@aksignal.cz Signed-off-by: Mark Brown --- sound/soc/codecs/Kconfig | 7 +++ sound/soc/codecs/Makefile | 2 + sound/soc/codecs/tlv320aic3x-spi.c | 76 ++++++++++++++++++++++++++++++ 3 files changed, 85 insertions(+) create mode 100644 sound/soc/codecs/tlv320aic3x-spi.c diff --git a/sound/soc/codecs/Kconfig b/sound/soc/codecs/Kconfig index b0323dbabf11..2a7b3e363069 100644 --- a/sound/soc/codecs/Kconfig +++ b/sound/soc/codecs/Kconfig @@ -219,6 +219,7 @@ config SND_SOC_ALL_CODECS imply SND_SOC_TLV320AIC32X4_I2C imply SND_SOC_TLV320AIC32X4_SPI imply SND_SOC_TLV320AIC3X_I2C + imply SND_SOC_TLV320AIC3X_SPI imply SND_SOC_TPA6130A2 imply SND_SOC_TLV320DAC33 imply SND_SOC_TSCS42XX @@ -1454,6 +1455,12 @@ config SND_SOC_TLV320AIC3X_I2C select SND_SOC_TLV320AIC3X select REGMAP_I2C +config SND_SOC_TLV320AIC3X_SPI + tristate "Texas Instruments TLV320AIC3x audio CODECs - SPI" + depends on SPI_MASTER + select SND_SOC_TLV320AIC3X + select REGMAP_SPI + config SND_SOC_TLV320DAC33 tristate depends on I2C diff --git a/sound/soc/codecs/Makefile b/sound/soc/codecs/Makefile index f014ea9f2318..0efdba609048 100644 --- a/sound/soc/codecs/Makefile +++ b/sound/soc/codecs/Makefile @@ -239,6 +239,7 @@ snd-soc-tlv320aic32x4-i2c-objs := tlv320aic32x4-i2c.o snd-soc-tlv320aic32x4-spi-objs := tlv320aic32x4-spi.o snd-soc-tlv320aic3x-objs := tlv320aic3x.o snd-soc-tlv320aic3x-i2c-objs := tlv320aic3x-i2c.o +snd-soc-tlv320aic3x-spi-objs := tlv320aic3x-spi.o snd-soc-tlv320dac33-objs := tlv320dac33.o snd-soc-tlv320adcx140-objs := tlv320adcx140.o snd-soc-tscs42xx-objs := tscs42xx.o @@ -560,6 +561,7 @@ obj-$(CONFIG_SND_SOC_TLV320AIC32X4_I2C) += snd-soc-tlv320aic32x4-i2c.o obj-$(CONFIG_SND_SOC_TLV320AIC32X4_SPI) += snd-soc-tlv320aic32x4-spi.o obj-$(CONFIG_SND_SOC_TLV320AIC3X) += snd-soc-tlv320aic3x.o obj-$(CONFIG_SND_SOC_TLV320AIC3X_I2C) += snd-soc-tlv320aic3x-i2c.o +obj-$(CONFIG_SND_SOC_TLV320AIC3X_SPI) += snd-soc-tlv320aic3x-spi.o obj-$(CONFIG_SND_SOC_TLV320DAC33) += snd-soc-tlv320dac33.o obj-$(CONFIG_SND_SOC_TLV320ADCX140) += snd-soc-tlv320adcx140.o obj-$(CONFIG_SND_SOC_TSCS42XX) += snd-soc-tscs42xx.o diff --git a/sound/soc/codecs/tlv320aic3x-spi.c b/sound/soc/codecs/tlv320aic3x-spi.c new file mode 100644 index 000000000000..bd78ab0910da --- /dev/null +++ b/sound/soc/codecs/tlv320aic3x-spi.c @@ -0,0 +1,76 @@ +/* SPDX-License-Identifier: GPL-2.0 + * + * ALSA SoC TLV320AIC3x codec driver SPI interface + * + * Author: Arun KS, + * Copyright: (C) 2008 Mistral Solutions Pvt Ltd., + * + * Based on sound/soc/codecs/wm8731.c by Richard Purdie + * + */ + +#include +#include +#include +#include +#include + +#include "tlv320aic3x.h" + +static int aic3x_spi_probe(struct spi_device *spi) +{ + struct regmap *regmap; + struct regmap_config config; + const struct spi_device_id *id = spi_get_device_id(spi); + + config = aic3x_regmap; + config.reg_bits = 7; + config.pad_bits = 1; + config.val_bits = 8; + config.read_flag_mask = 0x01; + + dev_dbg(&spi->dev, "probing tlv320aic3x spi device\n"); + + regmap = devm_regmap_init_spi(spi, &config); + return aic3x_probe(&spi->dev, regmap, id->driver_data); +} + +static int aic3x_spi_remove(struct spi_device *spi) +{ + return aic3x_remove(&spi->dev); +} + +static const struct spi_device_id aic3x_spi_id[] = { + { "tlv320aic3x", AIC3X_MODEL_3X }, + { "tlv320aic33", AIC3X_MODEL_33 }, + { "tlv320aic3007", AIC3X_MODEL_3007 }, + { "tlv320aic3104", AIC3X_MODEL_3104 }, + { } +}; +MODULE_DEVICE_TABLE(spi, aic3x_spi_id); + +static const struct of_device_id aic3x_of_id[] = { + { .compatible = "ti,tlv320aic3x", }, + { .compatible = "ti,tlv320aic33" }, + { .compatible = "ti,tlv320aic3007" }, + { .compatible = "ti,tlv320aic3104" }, + {}, +}; +MODULE_DEVICE_TABLE(of, aic3x_of_id); + +static struct spi_driver aic3x_spi_driver = { + .driver = { + .name = "tlv320aic3x", + .owner = THIS_MODULE, + .of_match_table = aic3x_of_id, + }, + .probe = aic3x_spi_probe, + .remove = aic3x_spi_remove, + .id_table = aic3x_spi_id, +}; + +module_spi_driver(aic3x_spi_driver); + +MODULE_DESCRIPTION("ASoC TLV320AIC3x codec driver SPI"); +MODULE_AUTHOR("Arun KS "); +MODULE_LICENSE("GPL"); From af4b54127b2b8a69f0f50e54cf099f26b82c9244 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Wed, 7 Apr 2021 15:42:18 +0800 Subject: [PATCH 0772/1091] ASoC: codecs: lpass-va-macro: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210407074218.3051979-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-va-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 3d6976a3d9e4..5294c57b2cd4 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -894,7 +894,7 @@ static int va_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) return 0; } -static struct snd_soc_dai_ops va_macro_dai_ops = { +static const struct snd_soc_dai_ops va_macro_dai_ops = { .hw_params = va_macro_hw_params, .get_channel_map = va_macro_get_channel_map, .mute_stream = va_macro_digital_mute, From fa74c223b6fd78a5314b4c61b9abdbed3c2185b4 Mon Sep 17 00:00:00 2001 From: Krzysztof Kozlowski Date: Wed, 7 Apr 2021 11:20:27 +0200 Subject: [PATCH 0773/1091] ASoC: simple-card: fix possible uninitialized single_cpu local variable The 'single_cpu' local variable is assigned by asoc_simple_parse_dai() and later used in a asoc_simple_canonicalize_cpu() call, assuming the entire function did not exit on errors. However the first function returns 0 if passed device_node is NULL, thus leaving the variable uninitialized and reporting success. Addresses-Coverity: Uninitialized scalar variable Fixes: 8f7f298a3337 ("ASoC: simple-card-utils: separate asoc_simple_card_parse_dai()") Signed-off-by: Krzysztof Kozlowski Acked-by: Sameer Pujar Link: https://lore.kernel.org/r/20210407092027.60769-1-krzysztof.kozlowski@canonical.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 2 +- sound/soc/generic/simple-card.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index ee1d924d68e5..76036ea377a9 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -367,7 +367,7 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, struct device_node *top = dev->of_node; struct asoc_simple_dai *cpu_dai; struct asoc_simple_dai *codec_dai; - int ret, single_cpu; + int ret, single_cpu = 0; dev_dbg(dev, "link_of (%pOF)\n", cpu_ep); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 41aa40765a8d..9a05f44fc3a9 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -249,7 +249,7 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, struct device_node *plat = NULL; char prop[128]; char *prefix = ""; - int ret, single_cpu; + int ret, single_cpu = 0; cpu = np; node = of_get_parent(np); From 9be701ec3493d3348723a38f0c19702d710758ce Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 7 Apr 2021 16:59:14 +0200 Subject: [PATCH 0774/1091] ASoC: meson: axg-fifo: add NO_PERIOD_WAKEUP support On the AXG family, the fifo irq is not necessary for the HW to operate. It is just used to notify that a period has elapsed. If userpace does not care for these wakeups (such as pipewire), we are just wasting CPU cycles. Add support for NO_PERIOD_WAKEUP and disable irq when they are no needed. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210407145914.311479-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-fifo.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sound/soc/meson/axg-fifo.c b/sound/soc/meson/axg-fifo.c index b2e867113226..b9af2d513e09 100644 --- a/sound/soc/meson/axg-fifo.c +++ b/sound/soc/meson/axg-fifo.c @@ -27,8 +27,8 @@ static struct snd_pcm_hardware axg_fifo_hw = { SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_BLOCK_TRANSFER | - SNDRV_PCM_INFO_PAUSE), - + SNDRV_PCM_INFO_PAUSE | + SNDRV_PCM_INFO_NO_PERIOD_WAKEUP), .formats = AXG_FIFO_FORMATS, .rate_min = 5512, .rate_max = 192000, @@ -113,7 +113,7 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, { struct snd_pcm_runtime *runtime = ss->runtime; struct axg_fifo *fifo = axg_fifo_data(ss); - unsigned int burst_num, period, threshold; + unsigned int burst_num, period, threshold, irq_en; dma_addr_t end_ptr; period = params_period_bytes(params); @@ -142,10 +142,11 @@ int axg_fifo_pcm_hw_params(struct snd_soc_component *component, regmap_field_write(fifo->field_threshold, threshold ? threshold - 1 : 0); - /* Enable block count irq */ + /* Enable irq if necessary */ + irq_en = runtime->no_period_wakeup ? 0 : FIFO_INT_COUNT_REPEAT; regmap_update_bits(fifo->map, FIFO_CTRL0, CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT), - CTRL0_INT_EN(FIFO_INT_COUNT_REPEAT)); + CTRL0_INT_EN(irq_en)); return 0; } From fa26d0c778b432d3d9814ea82552e813b33eeb5c Mon Sep 17 00:00:00 2001 From: Vitaly Kuznetsov Date: Tue, 6 Apr 2021 17:56:40 +0200 Subject: [PATCH 0775/1091] ACPI: processor: Fix build when CONFIG_ACPI_PROCESSOR=m Commit 8cdddd182bd7 ("ACPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead()") tried to fix CPU0 hotplug breakage by copying wakeup_cpu0() + start_cpu0() logic from hlt_play_dead()//mwait_play_dead() into acpi_idle_play_dead(). The problem is that these functions are not exported to modules so when CONFIG_ACPI_PROCESSOR=m build fails. The issue could've been fixed by exporting both wakeup_cpu0()/start_cpu0() (the later from assembly) but it seems putting the whole pattern into a new function and exporting it instead is better. Reported-by: kernel test robot Fixes: 8cdddd182bd7 ("CPI: processor: Fix CPU0 wakeup in acpi_idle_play_dead()") Cc: # 5.10+ Signed-off-by: Vitaly Kuznetsov Signed-off-by: Rafael J. Wysocki --- arch/x86/include/asm/smp.h | 2 +- arch/x86/kernel/smpboot.c | 26 ++++++++++++-------------- drivers/acpi/processor_idle.c | 4 +--- 3 files changed, 14 insertions(+), 18 deletions(-) diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h index 57ef2094af93..630ff08532be 100644 --- a/arch/x86/include/asm/smp.h +++ b/arch/x86/include/asm/smp.h @@ -132,7 +132,7 @@ void native_play_dead(void); void play_dead_common(void); void wbinvd_on_cpu(int cpu); int wbinvd_on_all_cpus(void); -bool wakeup_cpu0(void); +void cond_wakeup_cpu0(void); void native_smp_send_reschedule(int cpu); void native_send_call_func_ipi(const struct cpumask *mask); diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c index f877150a91da..16703c35a944 100644 --- a/arch/x86/kernel/smpboot.c +++ b/arch/x86/kernel/smpboot.c @@ -1659,13 +1659,17 @@ void play_dead_common(void) local_irq_disable(); } -bool wakeup_cpu0(void) +/** + * cond_wakeup_cpu0 - Wake up CPU0 if needed. + * + * If NMI wants to wake up CPU0, start CPU0. + */ +void cond_wakeup_cpu0(void) { if (smp_processor_id() == 0 && enable_start_cpu0) - return true; - - return false; + start_cpu0(); } +EXPORT_SYMBOL_GPL(cond_wakeup_cpu0); /* * We need to flush the caches before going to sleep, lest we have @@ -1734,11 +1738,8 @@ static inline void mwait_play_dead(void) __monitor(mwait_ptr, 0, 0); mb(); __mwait(eax, 0); - /* - * If NMI wants to wake up CPU0, start CPU0. - */ - if (wakeup_cpu0()) - start_cpu0(); + + cond_wakeup_cpu0(); } } @@ -1749,11 +1750,8 @@ void hlt_play_dead(void) while (1) { native_halt(); - /* - * If NMI wants to wake up CPU0, start CPU0. - */ - if (wakeup_cpu0()) - start_cpu0(); + + cond_wakeup_cpu0(); } } diff --git a/drivers/acpi/processor_idle.c b/drivers/acpi/processor_idle.c index 768a6b4d2368..4e2d76b8b697 100644 --- a/drivers/acpi/processor_idle.c +++ b/drivers/acpi/processor_idle.c @@ -544,9 +544,7 @@ static int acpi_idle_play_dead(struct cpuidle_device *dev, int index) return -ENODEV; #if defined(CONFIG_X86) && defined(CONFIG_HOTPLUG_CPU) - /* If NMI wants to wake up CPU0, start CPU0. */ - if (wakeup_cpu0()) - start_cpu0(); + cond_wakeup_cpu0(); #endif } From 649cab56de8eb2952498de9b752761ca980cb88a Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Sun, 4 Apr 2021 22:28:45 -0500 Subject: [PATCH 0776/1091] of: properly check for error returned by fdt_get_name() fdt_get_name() returns error values via a parameter pointer instead of in function return. Fix check for this error value in populate_node() and callers of populate_node(). Chasing up the caller tree showed callers of various functions failing to initialize the value of pointer parameters that can return error values. Initialize those values to NULL. The bug was introduced by commit e6a6928c3ea1 ("of/fdt: Convert FDT functions to use libfdt") but this patch can not be backported directly to that commit because the relevant code has further been restructured by commit dfbd4c6eff35 ("drivers/of: Split unflatten_dt_node()") The bug became visible by triggering a crash on openrisc with: commit 79edff12060f ("scripts/dtc: Update to upstream version v1.6.0-51-g183df9e9c2b9") as reported in: https://lore.kernel.org/lkml/20210327224116.69309-1-linux@roeck-us.net/ Fixes: 79edff12060f ("scripts/dtc: Update to upstream version v1.6.0-51-g183df9e9c2b9") Reported-by: Guenter Roeck Signed-off-by: Frank Rowand Tested-by: Guenter Roeck Link: https://lore.kernel.org/r/20210405032845.1942533-1-frowand.list@gmail.com Signed-off-by: Rob Herring --- drivers/of/fdt.c | 36 +++++++++++++++++++++++------------- drivers/of/overlay.c | 2 +- drivers/of/unittest.c | 15 ++++++++++----- 3 files changed, 34 insertions(+), 19 deletions(-) diff --git a/drivers/of/fdt.c b/drivers/of/fdt.c index dcc1dd96911a..adb26aff481d 100644 --- a/drivers/of/fdt.c +++ b/drivers/of/fdt.c @@ -205,7 +205,7 @@ static void populate_properties(const void *blob, *pprev = NULL; } -static bool populate_node(const void *blob, +static int populate_node(const void *blob, int offset, void **mem, struct device_node *dad, @@ -214,24 +214,24 @@ static bool populate_node(const void *blob, { struct device_node *np; const char *pathp; - unsigned int l, allocl; + int len; - pathp = fdt_get_name(blob, offset, &l); + pathp = fdt_get_name(blob, offset, &len); if (!pathp) { *pnp = NULL; - return false; + return len; } - allocl = ++l; + len++; - np = unflatten_dt_alloc(mem, sizeof(struct device_node) + allocl, + np = unflatten_dt_alloc(mem, sizeof(struct device_node) + len, __alignof__(struct device_node)); if (!dryrun) { char *fn; of_node_init(np); np->full_name = fn = ((char *)np) + sizeof(*np); - memcpy(fn, pathp, l); + memcpy(fn, pathp, len); if (dad != NULL) { np->parent = dad; @@ -295,6 +295,7 @@ static int unflatten_dt_nodes(const void *blob, struct device_node *nps[FDT_MAX_DEPTH]; void *base = mem; bool dryrun = !base; + int ret; if (nodepp) *nodepp = NULL; @@ -322,9 +323,10 @@ static int unflatten_dt_nodes(const void *blob, !of_fdt_device_is_available(blob, offset)) continue; - if (!populate_node(blob, offset, &mem, nps[depth], - &nps[depth+1], dryrun)) - return mem - base; + ret = populate_node(blob, offset, &mem, nps[depth], + &nps[depth+1], dryrun); + if (ret < 0) + return ret; if (!dryrun && nodepp && !*nodepp) *nodepp = nps[depth+1]; @@ -372,6 +374,10 @@ void *__unflatten_device_tree(const void *blob, { int size; void *mem; + int ret; + + if (mynodes) + *mynodes = NULL; pr_debug(" -> unflatten_device_tree()\n"); @@ -392,7 +398,7 @@ void *__unflatten_device_tree(const void *blob, /* First pass, scan for size */ size = unflatten_dt_nodes(blob, NULL, dad, NULL); - if (size < 0) + if (size <= 0) return NULL; size = ALIGN(size, 4); @@ -410,12 +416,16 @@ void *__unflatten_device_tree(const void *blob, pr_debug(" unflattening %p...\n", mem); /* Second pass, do actual unflattening */ - unflatten_dt_nodes(blob, mem, dad, mynodes); + ret = unflatten_dt_nodes(blob, mem, dad, mynodes); + if (be32_to_cpup(mem + size) != 0xdeadbeef) pr_warn("End of tree marker overwritten: %08x\n", be32_to_cpup(mem + size)); - if (detached && mynodes) { + if (ret <= 0) + return NULL; + + if (detached && mynodes && *mynodes) { of_node_set_flag(*mynodes, OF_DETACHED); pr_debug("unflattened tree is detached\n"); } diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index 50bbe0edf538..e12c643b6ba8 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -1017,7 +1017,7 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, const void *new_fdt; int ret; u32 size; - struct device_node *overlay_root; + struct device_node *overlay_root = NULL; *ovcs_id = 0; ret = 0; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index eb100627c186..f9b5b698249f 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -1408,7 +1408,7 @@ static void attach_node_and_children(struct device_node *np) static int __init unittest_data_add(void) { void *unittest_data; - struct device_node *unittest_data_node, *np; + struct device_node *unittest_data_node = NULL, *np; /* * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically * created by cmd_dt_S_dtb in scripts/Makefile.lib @@ -1417,10 +1417,10 @@ static int __init unittest_data_add(void) extern uint8_t __dtb_testcases_end[]; const int size = __dtb_testcases_end - __dtb_testcases_begin; int rc; + void *ret; if (!size) { - pr_warn("%s: No testcase data to attach; not running tests\n", - __func__); + pr_warn("%s: testcases is empty\n", __func__); return -ENODATA; } @@ -1429,9 +1429,14 @@ static int __init unittest_data_add(void) if (!unittest_data) return -ENOMEM; - of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); + ret = of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); + if (!ret) { + pr_warn("%s: unflatten testcases tree failed\n", __func__); + kfree(unittest_data); + return -ENODATA; + } if (!unittest_data_node) { - pr_warn("%s: No tree to attach; not running tests\n", __func__); + pr_warn("%s: testcases tree is empty\n", __func__); kfree(unittest_data); return -ENODATA; } From 603c4690b01aaffe3a6c3605a429f6dac39852ae Mon Sep 17 00:00:00 2001 From: Potnuri Bharat Teja Date: Wed, 31 Mar 2021 19:27:15 +0530 Subject: [PATCH 0777/1091] RDMA/cxgb4: check for ipv6 address properly while destroying listener ipv6 bit is wrongly set by the below which causes fatal adapter lookup engine errors for ipv4 connections while destroying a listener. Fix it to properly check the local address for ipv6. Fixes: 3408be145a5d ("RDMA/cxgb4: Fix adapter LE hash errors while destroying ipv6 listening server") Link: https://lore.kernel.org/r/20210331135715.30072-1-bharat@chelsio.com Signed-off-by: Potnuri Bharat Teja Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/cxgb4/cm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/cxgb4/cm.c b/drivers/infiniband/hw/cxgb4/cm.c index 81903749d241..e42c812e74c3 100644 --- a/drivers/infiniband/hw/cxgb4/cm.c +++ b/drivers/infiniband/hw/cxgb4/cm.c @@ -3616,7 +3616,8 @@ int c4iw_destroy_listen(struct iw_cm_id *cm_id) c4iw_init_wr_wait(ep->com.wr_waitp); err = cxgb4_remove_server( ep->com.dev->rdev.lldi.ports[0], ep->stid, - ep->com.dev->rdev.lldi.rxq_ids[0], true); + ep->com.dev->rdev.lldi.rxq_ids[0], + ep->com.local_addr.ss_family == AF_INET6); if (err) goto done; err = c4iw_wait_for_reply(&ep->com.dev->rdev, ep->com.wr_waitp, From 5de61a47eb9064cbbc5f3360d639e8e34a690a54 Mon Sep 17 00:00:00 2001 From: Mike Marciniszyn Date: Mon, 29 Mar 2021 09:48:19 -0400 Subject: [PATCH 0778/1091] IB/hfi1: Fix probe time panic when AIP is enabled with a buggy BIOS A panic can result when AIP is enabled: BUG: unable to handle kernel NULL pointer dereference at 000000000000000 PGD 0 P4D 0 Oops: 0000 1 SMP PTI CPU: 70 PID: 981 Comm: systemd-udevd Tainted: G OE --------- - - 4.18.0-240.el8.x86_64 #1 Hardware name: Intel Corporation S2600KP/S2600KP, BIOS SE5C610.86B.01.01.0005.101720141054 10/17/2014 RIP: 0010:__bitmap_and+0x1b/0x70 RSP: 0018:ffff99aa0845f9f0 EFLAGS: 00010246 RAX: 0000000000000000 RBX: ffff8d5a6fc18000 RCX: 0000000000000048 RDX: 0000000000000000 RSI: ffffffffc06336f0 RDI: ffff8d5a8fa67750 RBP: 0000000000000079 R08: 0000000fffffffff R09: 0000000000000000 R10: 0000000000000000 R11: 0000000000000001 R12: ffffffffc06336f0 R13: 00000000000000a0 R14: ffff8d5a6fc18000 R15: 0000000000000003 FS: 00007fec137a5980(0000) GS:ffff8d5a9fa80000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 0000000000000000 CR3: 0000000a04b48002 CR4: 00000000001606e0 Call Trace: hfi1_num_netdev_contexts+0x7c/0x110 [hfi1] hfi1_init_dd+0xd7f/0x1a90 [hfi1] ? pci_bus_read_config_dword+0x49/0x70 ? pci_mmcfg_read+0x3e/0xe0 do_init_one.isra.18+0x336/0x640 [hfi1] local_pci_probe+0x41/0x90 pci_device_probe+0x105/0x1c0 really_probe+0x212/0x440 driver_probe_device+0x49/0xc0 device_driver_attach+0x50/0x60 __driver_attach+0x61/0x130 ? device_driver_attach+0x60/0x60 bus_for_each_dev+0x77/0xc0 ? klist_add_tail+0x3b/0x70 bus_add_driver+0x14d/0x1e0 ? dev_init+0x10b/0x10b [hfi1] driver_register+0x6b/0xb0 ? dev_init+0x10b/0x10b [hfi1] hfi1_mod_init+0x1e6/0x20a [hfi1] do_one_initcall+0x46/0x1c3 ? free_unref_page_commit+0x91/0x100 ? _cond_resched+0x15/0x30 ? kmem_cache_alloc_trace+0x140/0x1c0 do_init_module+0x5a/0x220 load_module+0x14b4/0x17e0 ? __do_sys_finit_module+0xa8/0x110 __do_sys_finit_module+0xa8/0x110 do_syscall_64+0x5b/0x1a0 The issue happens when pcibus_to_node() returns NO_NUMA_NODE. Fix this issue by moving the initialization of dd->node to hfi1_devdata allocation and remove the other pcibus_to_node() calls in the probe path and use dd->node instead. Affinity logic is adjusted to use a new field dd->affinity_entry as a guard instead of dd->node. Fixes: 4730f4a6c6b2 ("IB/hfi1: Activate the dummy netdev") Link: https://lore.kernel.org/r/1617025700-31865-4-git-send-email-dennis.dalessandro@cornelisnetworks.com Cc: stable@vger.kernel.org Signed-off-by: Mike Marciniszyn Signed-off-by: Dennis Dalessandro Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/hfi1/affinity.c | 21 +++++---------------- drivers/infiniband/hw/hfi1/hfi.h | 1 + drivers/infiniband/hw/hfi1/init.c | 10 +++++++++- drivers/infiniband/hw/hfi1/netdev_rx.c | 3 +-- 4 files changed, 16 insertions(+), 19 deletions(-) diff --git a/drivers/infiniband/hw/hfi1/affinity.c b/drivers/infiniband/hw/hfi1/affinity.c index 2a91b8d95e12..04b1e8f021f6 100644 --- a/drivers/infiniband/hw/hfi1/affinity.c +++ b/drivers/infiniband/hw/hfi1/affinity.c @@ -632,22 +632,11 @@ static void _dev_comp_vect_cpu_mask_clean_up(struct hfi1_devdata *dd, */ int hfi1_dev_affinity_init(struct hfi1_devdata *dd) { - int node = pcibus_to_node(dd->pcidev->bus); struct hfi1_affinity_node *entry; const struct cpumask *local_mask; int curr_cpu, possible, i, ret; bool new_entry = false; - /* - * If the BIOS does not have the NUMA node information set, select - * NUMA 0 so we get consistent performance. - */ - if (node < 0) { - dd_dev_err(dd, "Invalid PCI NUMA node. Performance may be affected\n"); - node = 0; - } - dd->node = node; - local_mask = cpumask_of_node(dd->node); if (cpumask_first(local_mask) >= nr_cpu_ids) local_mask = topology_core_cpumask(0); @@ -660,7 +649,7 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd) * create an entry in the global affinity structure and initialize it. */ if (!entry) { - entry = node_affinity_allocate(node); + entry = node_affinity_allocate(dd->node); if (!entry) { dd_dev_err(dd, "Unable to allocate global affinity node\n"); @@ -751,6 +740,7 @@ int hfi1_dev_affinity_init(struct hfi1_devdata *dd) if (new_entry) node_affinity_add_tail(entry); + dd->affinity_entry = entry; mutex_unlock(&node_affinity.lock); return 0; @@ -766,10 +756,9 @@ void hfi1_dev_affinity_clean_up(struct hfi1_devdata *dd) { struct hfi1_affinity_node *entry; - if (dd->node < 0) - return; - mutex_lock(&node_affinity.lock); + if (!dd->affinity_entry) + goto unlock; entry = node_affinity_lookup(dd->node); if (!entry) goto unlock; @@ -780,8 +769,8 @@ void hfi1_dev_affinity_clean_up(struct hfi1_devdata *dd) */ _dev_comp_vect_cpu_mask_clean_up(dd, entry); unlock: + dd->affinity_entry = NULL; mutex_unlock(&node_affinity.lock); - dd->node = NUMA_NO_NODE; } /* diff --git a/drivers/infiniband/hw/hfi1/hfi.h b/drivers/infiniband/hw/hfi1/hfi.h index e09e8244a94c..2a9a040569eb 100644 --- a/drivers/infiniband/hw/hfi1/hfi.h +++ b/drivers/infiniband/hw/hfi1/hfi.h @@ -1409,6 +1409,7 @@ struct hfi1_devdata { spinlock_t irq_src_lock; int vnic_num_vports; struct net_device *dummy_netdev; + struct hfi1_affinity_node *affinity_entry; /* Keeps track of IPoIB RSM rule users */ atomic_t ipoib_rsm_usr_num; diff --git a/drivers/infiniband/hw/hfi1/init.c b/drivers/infiniband/hw/hfi1/init.c index cb7ad1288821..786c6316273f 100644 --- a/drivers/infiniband/hw/hfi1/init.c +++ b/drivers/infiniband/hw/hfi1/init.c @@ -1277,7 +1277,6 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, dd->pport = (struct hfi1_pportdata *)(dd + 1); dd->pcidev = pdev; pci_set_drvdata(pdev, dd); - dd->node = NUMA_NO_NODE; ret = xa_alloc_irq(&hfi1_dev_table, &dd->unit, dd, xa_limit_32b, GFP_KERNEL); @@ -1287,6 +1286,15 @@ static struct hfi1_devdata *hfi1_alloc_devdata(struct pci_dev *pdev, goto bail; } rvt_set_ibdev_name(&dd->verbs_dev.rdi, "%s_%d", class_name(), dd->unit); + /* + * If the BIOS does not have the NUMA node information set, select + * NUMA 0 so we get consistent performance. + */ + dd->node = pcibus_to_node(pdev->bus); + if (dd->node == NUMA_NO_NODE) { + dd_dev_err(dd, "Invalid PCI NUMA node. Performance may be affected\n"); + dd->node = 0; + } /* * Initialize all locks for the device. This needs to be as early as diff --git a/drivers/infiniband/hw/hfi1/netdev_rx.c b/drivers/infiniband/hw/hfi1/netdev_rx.c index 1fb6e1a0e4e1..1bcab992ac26 100644 --- a/drivers/infiniband/hw/hfi1/netdev_rx.c +++ b/drivers/infiniband/hw/hfi1/netdev_rx.c @@ -173,8 +173,7 @@ u32 hfi1_num_netdev_contexts(struct hfi1_devdata *dd, u32 available_contexts, return 0; } - cpumask_and(node_cpu_mask, cpu_mask, - cpumask_of_node(pcibus_to_node(dd->pcidev->bus))); + cpumask_and(node_cpu_mask, cpu_mask, cpumask_of_node(dd->node)); available_cpus = cpumask_weight(node_cpu_mask); From f2013278ae40b89cc27916366c407ce5261815ef Mon Sep 17 00:00:00 2001 From: Jin Yao Date: Wed, 7 Apr 2021 10:44:52 +0800 Subject: [PATCH 0779/1091] perf report: Fix wrong LBR block sorting When '--total-cycles' is specified, it supports sorting for all blocks by 'Sampled Cycles%'. This is useful to concentrate on the globally hottest blocks. 'Sampled Cycles%' - block sampled cycles aggregation / total sampled cycles But in current code, it doesn't use the cycles aggregation. Part of 'cycles' counting is possibly dropped for some overlap jumps. But for identifying the hot block, we always need the full cycles. # perf record -b ./triad_loop # perf report --total-cycles --stdio Before: # # Sampled Cycles% Sampled Cycles Avg Cycles% Avg Cycles [Program Block Range] Shared Object # ............... .............. ........... .......... ............................................................. ................. # 0.81% 793 4.32% 793 [setup-vdso.h:34 -> setup-vdso.h:40] ld-2.27.so 0.49% 480 0.87% 160 [native_write_msr+0 -> native_write_msr+16] [kernel.kallsyms] 0.48% 476 0.52% 95 [native_read_msr+0 -> native_read_msr+29] [kernel.kallsyms] 0.31% 303 1.65% 303 [nmi_restore+0 -> nmi_restore+37] [kernel.kallsyms] 0.26% 255 1.39% 255 [nohz_balance_exit_idle+75 -> nohz_balance_exit_idle+162] [kernel.kallsyms] 0.24% 234 1.28% 234 [end_repeat_nmi+67 -> end_repeat_nmi+83] [kernel.kallsyms] 0.23% 227 1.24% 227 [__irqentry_text_end+96 -> __irqentry_text_end+126] [kernel.kallsyms] 0.20% 194 1.06% 194 [native_set_debugreg+52 -> native_set_debugreg+56] [kernel.kallsyms] 0.11% 106 0.14% 26 [native_sched_clock+0 -> native_sched_clock+98] [kernel.kallsyms] 0.10% 97 0.53% 97 [trigger_load_balance+0 -> trigger_load_balance+67] [kernel.kallsyms] 0.09% 85 0.46% 85 [get-dynamic-info.h:102 -> get-dynamic-info.h:111] ld-2.27.so ... 0.00% 92.7K 0.02% 4 [triad_loop.c:64 -> triad_loop.c:65] triad_loop The hottest block '[triad_loop.c:64 -> triad_loop.c:65]' is not at the top of output. After: # Sampled Cycles% Sampled Cycles Avg Cycles% Avg Cycles [Program Block Range] Shared Object # ............... .............. ........... .......... .............................................................. ................. # 94.35% 92.7K 0.02% 4 [triad_loop.c:64 -> triad_loop.c:65] triad_loop 0.81% 793 4.32% 793 [setup-vdso.h:34 -> setup-vdso.h:40] ld-2.27.so 0.49% 480 0.87% 160 [native_write_msr+0 -> native_write_msr+16] [kernel.kallsyms] 0.48% 476 0.52% 95 [native_read_msr+0 -> native_read_msr+29] [kernel.kallsyms] 0.31% 303 1.65% 303 [nmi_restore+0 -> nmi_restore+37] [kernel.kallsyms] 0.26% 255 1.39% 255 [nohz_balance_exit_idle+75 -> nohz_balance_exit_idle+162] [kernel.kallsyms] 0.24% 234 1.28% 234 [end_repeat_nmi+67 -> end_repeat_nmi+83] [kernel.kallsyms] 0.23% 227 1.24% 227 [__irqentry_text_end+96 -> __irqentry_text_end+126] [kernel.kallsyms] 0.20% 194 1.06% 194 [native_set_debugreg+52 -> native_set_debugreg+56] [kernel.kallsyms] 0.11% 106 0.14% 26 [native_sched_clock+0 -> native_sched_clock+98] [kernel.kallsyms] 0.10% 97 0.53% 97 [trigger_load_balance+0 -> trigger_load_balance+67] [kernel.kallsyms] 0.09% 85 0.46% 85 [get-dynamic-info.h:102 -> get-dynamic-info.h:111] ld-2.27.so 0.08% 82 0.06% 11 [intel_pmu_drain_pebs_nhm+580 -> intel_pmu_drain_pebs_nhm+627] [kernel.kallsyms] 0.08% 77 0.42% 77 [lru_add_drain_cpu+0 -> lru_add_drain_cpu+133] [kernel.kallsyms] 0.08% 74 0.10% 18 [handle_pmi_common+271 -> handle_pmi_common+310] [kernel.kallsyms] 0.08% 74 0.40% 74 [get-dynamic-info.h:131 -> get-dynamic-info.h:157] ld-2.27.so 0.07% 69 0.09% 17 [intel_pmu_drain_pebs_nhm+432 -> intel_pmu_drain_pebs_nhm+468] [kernel.kallsyms] Now the hottest block is reported at the top of output. Fixes: b65a7d372b1a55db ("perf hist: Support block formats with compare/sort/display") Signed-off-by: Jin Yao Reviewed-by: Andi Kleen Cc: Alexander Shishkin Cc: Jin Yao Cc: Jiri Olsa Cc: Kan Liang Cc: Peter Zijlstra Link: http://lore.kernel.org/lkml/20210407024452.29988-1-yao.jin@linux.intel.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/block-info.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tools/perf/util/block-info.c b/tools/perf/util/block-info.c index 423ec69bda6c..5ecd4f401f32 100644 --- a/tools/perf/util/block-info.c +++ b/tools/perf/util/block-info.c @@ -201,7 +201,7 @@ static int block_total_cycles_pct_entry(struct perf_hpp_fmt *fmt, double ratio = 0.0; if (block_fmt->total_cycles) - ratio = (double)bi->cycles / (double)block_fmt->total_cycles; + ratio = (double)bi->cycles_aggr / (double)block_fmt->total_cycles; return color_pct(hpp, block_fmt->width, 100.0 * ratio); } @@ -216,9 +216,9 @@ static int64_t block_total_cycles_pct_sort(struct perf_hpp_fmt *fmt, double l, r; if (block_fmt->total_cycles) { - l = ((double)bi_l->cycles / + l = ((double)bi_l->cycles_aggr / (double)block_fmt->total_cycles) * 100000.0; - r = ((double)bi_r->cycles / + r = ((double)bi_r->cycles_aggr / (double)block_fmt->total_cycles) * 100000.0; return (int64_t)l - (int64_t)r; } From 92f1e8adf7db2ef9b90e5662182810c0cf8ac22e Mon Sep 17 00:00:00 2001 From: Ian Rogers Date: Wed, 7 Apr 2021 08:39:55 -0700 Subject: [PATCH 0780/1091] perf arm-spe: Avoid potential buffer overrun SPE extended headers are > 1 byte so ensure the buffer contains at least this before reading. This issue was detected by fuzzing. Signed-off-by: Ian Rogers Cc: Alexander Shishkin Cc: Andre Przywara Cc: Dave Martin Cc: Jiri Olsa Cc: Leo Yan Cc: Mark Rutland Cc: Namhyung Kim Cc: Peter Zijlstra Cc: Stephane Eranian Cc: Will Deacon Link: http://lore.kernel.org/lkml/20210407153955.317215-1-irogers@google.com Signed-off-by: Arnaldo Carvalho de Melo --- tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c index f3ac9d40cebf..2e5eff4f8f03 100644 --- a/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c +++ b/tools/perf/util/arm-spe-decoder/arm-spe-pkt-decoder.c @@ -210,8 +210,10 @@ static int arm_spe_do_get_packet(const unsigned char *buf, size_t len, if ((hdr & SPE_HEADER0_MASK2) == SPE_HEADER0_EXTENDED) { /* 16-bit extended format header */ - ext_hdr = 1; + if (len == 1) + return ARM_SPE_BAD_PACKET; + ext_hdr = 1; hdr = buf[1]; if (hdr == SPE_HEADER1_ALIGNMENT) return arm_spe_get_alignment(buf, len, packet); From 0c85a7e87465f2d4cbc768e245f4f45b2f299b05 Mon Sep 17 00:00:00 2001 From: Aditya Pakki Date: Tue, 6 Apr 2021 19:09:12 -0500 Subject: [PATCH 0781/1091] net/rds: Avoid potential use after free in rds_send_remove_from_sock In case of rs failure in rds_send_remove_from_sock(), the 'rm' resource is freed and later under spinlock, causing potential use-after-free. Set the free pointer to NULL to avoid undefined behavior. Signed-off-by: Aditya Pakki Acked-by: Santosh Shilimkar Signed-off-by: David S. Miller --- net/rds/message.c | 1 + net/rds/send.c | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/net/rds/message.c b/net/rds/message.c index 799034e0f513..4fc66ff0f1ec 100644 --- a/net/rds/message.c +++ b/net/rds/message.c @@ -180,6 +180,7 @@ void rds_message_put(struct rds_message *rm) rds_message_purge(rm); kfree(rm); + rm = NULL; } } EXPORT_SYMBOL_GPL(rds_message_put); diff --git a/net/rds/send.c b/net/rds/send.c index 985d0b7713ac..fe5264b9d4b3 100644 --- a/net/rds/send.c +++ b/net/rds/send.c @@ -665,7 +665,7 @@ static void rds_send_remove_from_sock(struct list_head *messages, int status) unlock_and_drop: spin_unlock_irqrestore(&rm->m_rs_lock, flags); rds_message_put(rm); - if (was_on_sock) + if (was_on_sock && rm) rds_message_put(rm); } From f0ebc2b6b7df7716749445cda26734b3826a48cf Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Apr 2021 17:28:25 -0700 Subject: [PATCH 0782/1091] ethtool: un-kdocify extended link state Extended link state structures and enums use kdoc headers but then do not describe any of the members. Convert to normal comments. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/linux/ethtool.h | 4 +--- include/uapi/linux/ethtool.h | 26 ++++++-------------------- 2 files changed, 7 insertions(+), 23 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index ec4cd3921c67..a2b1a21ee7fd 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -87,9 +87,7 @@ u32 ethtool_op_get_link(struct net_device *dev); int ethtool_op_get_ts_info(struct net_device *dev, struct ethtool_ts_info *eti); -/** - * struct ethtool_link_ext_state_info - link extended state and substate. - */ +/* Link extended state and substate. */ struct ethtool_link_ext_state_info { enum ethtool_link_ext_state link_ext_state; union { diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index cde753bb2093..dc87ba092891 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -579,9 +579,7 @@ struct ethtool_pauseparam { __u32 tx_pause; }; -/** - * enum ethtool_link_ext_state - link extended state - */ +/* Link extended state */ enum ethtool_link_ext_state { ETHTOOL_LINK_EXT_STATE_AUTONEG, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, @@ -595,10 +593,7 @@ enum ethtool_link_ext_state { ETHTOOL_LINK_EXT_STATE_OVERHEAT, }; -/** - * enum ethtool_link_ext_substate_autoneg - more information in addition to - * ETHTOOL_LINK_EXT_STATE_AUTONEG. - */ +/* More information in addition to ETHTOOL_LINK_EXT_STATE_AUTONEG. */ enum ethtool_link_ext_substate_autoneg { ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED = 1, ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED, @@ -608,9 +603,7 @@ enum ethtool_link_ext_substate_autoneg { ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD, }; -/** - * enum ethtool_link_ext_substate_link_training - more information in addition to - * ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. +/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE. */ enum ethtool_link_ext_substate_link_training { ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED = 1, @@ -619,9 +612,7 @@ enum ethtool_link_ext_substate_link_training { ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT, }; -/** - * enum ethtool_link_ext_substate_logical_mismatch - more information in addition - * to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. +/* More information in addition to ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH. */ enum ethtool_link_ext_substate_link_logical_mismatch { ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK = 1, @@ -631,19 +622,14 @@ enum ethtool_link_ext_substate_link_logical_mismatch { ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED, }; -/** - * enum ethtool_link_ext_substate_bad_signal_integrity - more information in - * addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. +/* More information in addition to ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY. */ enum ethtool_link_ext_substate_bad_signal_integrity { ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS = 1, ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE, }; -/** - * enum ethtool_link_ext_substate_cable_issue - more information in - * addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. - */ +/* More information in addition to ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE. */ enum ethtool_link_ext_substate_cable_issue { ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE = 1, ETHTOOL_LINK_EXT_SUBSTATE_CI_CABLE_TEST_FAILURE, From 83e5feeb385e6d69ae95dd30e0c424afaa17cc6b Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Apr 2021 17:28:26 -0700 Subject: [PATCH 0783/1091] ethtool: document reserved fields in the uAPI Add a note on expected handling of reserved fields, and references to all kdocs. This fixes a bunch of kdoc warnings. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/uapi/linux/ethtool.h | 22 +++++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index dc87ba092891..c9c18e88c215 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -26,6 +26,14 @@ * have the same layout for 32-bit and 64-bit userland. */ +/* Note on reserved space. + * Reserved fields must not be accessed directly by user space because + * they may be replaced by a different field in the future. They must + * be initialized to zero before making the request, e.g. via memset + * of the entire structure or implicitly by not being set in a structure + * initializer. + */ + /** * struct ethtool_cmd - DEPRECATED, link control and status * This structure is DEPRECATED, please use struct ethtool_link_settings. @@ -67,6 +75,7 @@ * and other link features that the link partner advertised * through autonegotiation; 0 if unknown or not applicable. * Read-only. + * @reserved: Reserved for future use; see the note on reserved space. * * The link speed in Mbps is split between @speed and @speed_hi. Use * the ethtool_cmd_speed() and ethtool_cmd_speed_set() functions to @@ -155,6 +164,7 @@ static inline __u32 ethtool_cmd_speed(const struct ethtool_cmd *ep) * @bus_info: Device bus address. This should match the dev_name() * string for the underlying bus device, if there is one. May be * an empty string. + * @reserved2: Reserved for future use; see the note on reserved space. * @n_priv_flags: Number of flags valid for %ETHTOOL_GPFLAGS and * %ETHTOOL_SPFLAGS commands; also the number of strings in the * %ETH_SS_PRIV_FLAGS set @@ -356,6 +366,7 @@ struct ethtool_eeprom { * @tx_lpi_timer: Time in microseconds the interface delays prior to asserting * its tx lpi (after reaching 'idle' state). Effective only when eee * was negotiated and tx_lpi_enabled was set. + * @reserved: Reserved for future use; see the note on reserved space. */ struct ethtool_eee { __u32 cmd; @@ -374,6 +385,7 @@ struct ethtool_eee { * @cmd: %ETHTOOL_GMODULEINFO * @type: Standard the module information conforms to %ETH_MODULE_SFF_xxxx * @eeprom_len: Length of the eeprom + * @reserved: Reserved for future use; see the note on reserved space. * * This structure is used to return the information to * properly size memory for a subsequent call to %ETHTOOL_GMODULEEEPROM. @@ -701,6 +713,7 @@ struct ethtool_gstrings { /** * struct ethtool_sset_info - string set information * @cmd: Command number = %ETHTOOL_GSSET_INFO + * @reserved: Reserved for future use; see the note on reserved space. * @sset_mask: On entry, a bitmask of string sets to query, with bits * numbered according to &enum ethtool_stringset. On return, a * bitmask of those string sets queried that are supported. @@ -745,6 +758,7 @@ enum ethtool_test_flags { * @flags: A bitmask of flags from &enum ethtool_test_flags. Some * flags may be set by the user on entry; others may be set by * the driver on return. + * @reserved: Reserved for future use; see the note on reserved space. * @len: On return, the number of test results * @data: Array of test results * @@ -945,6 +959,7 @@ union ethtool_flow_union { * @vlan_etype: VLAN EtherType * @vlan_tci: VLAN tag control information * @data: user defined data + * @padding: Reserved for future use; see the note on reserved space. * * Note, @vlan_etype, @vlan_tci, and @data are only valid if %FLOW_EXT * is set in &struct ethtool_rx_flow_spec @flow_type. @@ -1120,7 +1135,8 @@ struct ethtool_rxfh_indir { * hardware hash key. * @hfunc: Defines the current RSS hash function used by HW (or to be set to). * Valid values are one of the %ETH_RSS_HASH_*. - * @rsvd: Reserved for future extensions. + * @rsvd8: Reserved for future use; see the note on reserved space. + * @rsvd32: Reserved for future use; see the note on reserved space. * @rss_config: RX ring/queue index for each hash value i.e., indirection table * of @indir_size __u32 elements, followed by hash key of @key_size * bytes. @@ -1288,7 +1304,9 @@ struct ethtool_sfeatures { * @so_timestamping: bit mask of the sum of the supported SO_TIMESTAMPING flags * @phc_index: device index of the associated PHC, or -1 if there is none * @tx_types: bit mask of the supported hwtstamp_tx_types enumeration values + * @tx_reserved: Reserved for future use; see the note on reserved space. * @rx_filters: bit mask of the supported hwtstamp_rx_filters enumeration values + * @rx_reserved: Reserved for future use; see the note on reserved space. * * The bits in the 'tx_types' and 'rx_filters' fields correspond to * the 'hwtstamp_tx_types' and 'hwtstamp_rx_filters' enumeration values, @@ -1944,6 +1962,8 @@ enum ethtool_reset_flags { * autonegotiation; 0 if unknown or not applicable. Read-only. * @transceiver: Used to distinguish different possible PHY types, * reported consistently by PHYLIB. Read-only. + * @reserved: Reserved for future use; see the note on reserved space. + * @reserved1: Reserved for future use; see the note on reserved space. * * If autonegotiation is disabled, the speed and @duplex represent the * fixed link mode and are writable if the driver supports multiple From d9c65de0c1e1574d2cc8007dbe02291fe47db1d9 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 6 Apr 2021 17:28:27 -0700 Subject: [PATCH 0784/1091] ethtool: fix kdoc in headers Fix remaining issues with kdoc in the ethtool headers. Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- include/linux/ethtool.h | 9 +++++++-- include/uapi/linux/ethtool.h | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index a2b1a21ee7fd..7c88dfff7420 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -290,6 +290,9 @@ struct ethtool_pause_stats { * do not attach ext_substate attribute to netlink message). If link_ext_state * and link_ext_substate are unknown, return -ENODATA. If not implemented, * link_ext_state and link_ext_substate will not be sent to userspace. + * @get_eeprom_len: Read range of EEPROM addresses for validation of + * @get_eeprom and @set_eeprom requests. + * Returns 0 if device does not support EEPROM access. * @get_eeprom: Read data from the device EEPROM. * Should fill in the magic field. Don't need to check len for zero * or wraparound. Fill in the data argument with the eeprom values @@ -382,6 +385,8 @@ struct ethtool_pause_stats { * @get_module_eeprom: Get the eeprom information from the plug-in module * @get_eee: Get Energy-Efficient (EEE) supported and status. * @set_eee: Set EEE status (enable/disable) as well as LPI timers. + * @get_tunable: Read the value of a driver / device tunable. + * @set_tunable: Set the value of a driver / device tunable. * @get_per_queue_coalesce: Get interrupt coalescing parameters per queue. * It must check that the given queue number is valid. If neither a RX nor * a TX queue has this number, return -EINVAL. If only a RX queue or a TX @@ -545,8 +550,8 @@ struct phy_tdr_config; * @get_sset_count: Get number of strings that @get_strings will write. * @get_strings: Return a set of strings that describe the requested objects * @get_stats: Return extended statistics about the PHY device. - * @start_cable_test - Start a cable test - * @start_cable_test_tdr - Start a Time Domain Reflectometry cable test + * @start_cable_test: Start a cable test + * @start_cable_test_tdr: Start a Time Domain Reflectometry cable test * * All operations are optional (i.e. the function pointer may be set to %NULL) * and callers must take this into account. Callers must hold the RTNL lock. diff --git a/include/uapi/linux/ethtool.h b/include/uapi/linux/ethtool.h index c9c18e88c215..5afea692a3f7 100644 --- a/include/uapi/linux/ethtool.h +++ b/include/uapi/linux/ethtool.h @@ -659,6 +659,7 @@ enum ethtool_link_ext_substate_cable_issue { * now deprecated * @ETH_SS_FEATURES: Device feature names * @ETH_SS_RSS_HASH_FUNCS: RSS hush function names + * @ETH_SS_TUNABLES: tunable names * @ETH_SS_PHY_STATS: Statistic names, for use with %ETHTOOL_GPHYSTATS * @ETH_SS_PHY_TUNABLES: PHY tunable names * @ETH_SS_LINK_MODES: link mode names @@ -668,6 +669,8 @@ enum ethtool_link_ext_substate_cable_issue { * @ETH_SS_TS_TX_TYPES: timestamping Tx types * @ETH_SS_TS_RX_FILTERS: timestamping Rx filters * @ETH_SS_UDP_TUNNEL_TYPES: UDP tunnel types + * + * @ETH_SS_COUNT: number of defined string sets */ enum ethtool_stringset { ETH_SS_TEST = 0, @@ -1962,8 +1965,11 @@ enum ethtool_reset_flags { * autonegotiation; 0 if unknown or not applicable. Read-only. * @transceiver: Used to distinguish different possible PHY types, * reported consistently by PHYLIB. Read-only. + * @master_slave_cfg: Master/slave port mode. + * @master_slave_state: Master/slave port state. * @reserved: Reserved for future use; see the note on reserved space. * @reserved1: Reserved for future use; see the note on reserved space. + * @link_mode_masks: Variable length bitmaps. * * If autonegotiation is disabled, the speed and @duplex represent the * fixed link mode and are writable if the driver supports multiple From 9d6803921a16f4d768dc41a75375629828f4d91e Mon Sep 17 00:00:00 2001 From: Kurt Kanzenbach Date: Tue, 6 Apr 2021 09:35:09 +0200 Subject: [PATCH 0785/1091] net: hsr: Reset MAC header for Tx path Reset MAC header in HSR Tx path. This is needed, because direct packet transmission, e.g. by specifying PACKET_QDISC_BYPASS does not reset the MAC header. This has been observed using the following setup: |$ ip link add name hsr0 type hsr slave1 lan0 slave2 lan1 supervision 45 version 1 |$ ifconfig hsr0 up |$ ./test hsr0 The test binary is using mmap'ed sockets and is specifying the PACKET_QDISC_BYPASS socket option. This patch resolves the following warning on a non-patched kernel: |[ 112.725394] ------------[ cut here ]------------ |[ 112.731418] WARNING: CPU: 1 PID: 257 at net/hsr/hsr_forward.c:560 hsr_forward_skb+0x484/0x568 |[ 112.739962] net/hsr/hsr_forward.c:560: Malformed frame (port_src hsr0) The warning can be safely removed, because the other call sites of hsr_forward_skb() make sure that the skb is prepared correctly. Fixes: d346a3fae3ff ("packet: introduce PACKET_QDISC_BYPASS socket option") Signed-off-by: Kurt Kanzenbach Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- net/hsr/hsr_device.c | 1 + net/hsr/hsr_forward.c | 6 ------ 2 files changed, 1 insertion(+), 6 deletions(-) diff --git a/net/hsr/hsr_device.c b/net/hsr/hsr_device.c index 7444ec6e298e..bfcdc75fc01e 100644 --- a/net/hsr/hsr_device.c +++ b/net/hsr/hsr_device.c @@ -217,6 +217,7 @@ static netdev_tx_t hsr_dev_xmit(struct sk_buff *skb, struct net_device *dev) master = hsr_port_get_hsr(hsr, HSR_PT_MASTER); if (master) { skb->dev = master->dev; + skb_reset_mac_header(skb); hsr_forward_skb(skb, master); } else { atomic_long_inc(&dev->tx_dropped); diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index ed82a470b6e1..b218e4594009 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -555,12 +555,6 @@ void hsr_forward_skb(struct sk_buff *skb, struct hsr_port *port) { struct hsr_frame_info frame; - if (skb_mac_header(skb) != skb->data) { - WARN_ONCE(1, "%s:%d: Malformed frame (port_src %s)\n", - __FILE__, __LINE__, port->dev->name); - goto out_drop; - } - if (fill_frame_info(&frame, skb, port) < 0) goto out_drop; From a79ace4b312953c5835fafb12adc3cb6878b26bd Mon Sep 17 00:00:00 2001 From: Zheng Yongjun Date: Wed, 7 Apr 2021 09:59:45 +0800 Subject: [PATCH 0786/1091] net: tipc: Fix spelling errors in net/tipc module These patches fix a series of spelling errors in net/tipc module. Reported-by: Hulk Robot Signed-off-by: Zheng Yongjun Signed-off-by: David S. Miller --- net/tipc/bearer.h | 6 +++--- net/tipc/net.c | 2 +- net/tipc/node.c | 2 +- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/net/tipc/bearer.h b/net/tipc/bearer.h index 6bf4550aa1ac..57c6a1a719e2 100644 --- a/net/tipc/bearer.h +++ b/net/tipc/bearer.h @@ -154,9 +154,9 @@ struct tipc_media { * care of initializing all other fields. */ struct tipc_bearer { - void __rcu *media_ptr; /* initalized by media */ - u32 mtu; /* initalized by media */ - struct tipc_media_addr addr; /* initalized by media */ + void __rcu *media_ptr; /* initialized by media */ + u32 mtu; /* initialized by media */ + struct tipc_media_addr addr; /* initialized by media */ char name[TIPC_MAX_BEARER_NAME]; struct tipc_media *media; struct tipc_media_addr bcast_addr; diff --git a/net/tipc/net.c b/net/tipc/net.c index a129f661bee3..faf6bf554514 100644 --- a/net/tipc/net.c +++ b/net/tipc/net.c @@ -89,7 +89,7 @@ * - A spin lock to protect the registry of kernel/driver users (reg.c) * - A global spin_lock (tipc_port_lock), which only task is to ensure * consistency where more than one port is involved in an operation, - * i.e., whe a port is part of a linked list of ports. + * i.e., when a port is part of a linked list of ports. * There are two such lists; 'port_list', which is used for management, * and 'wait_list', which is used to queue ports during congestion. * diff --git a/net/tipc/node.c b/net/tipc/node.c index 136338b85504..e0ee83263a39 100644 --- a/net/tipc/node.c +++ b/net/tipc/node.c @@ -1734,7 +1734,7 @@ int tipc_node_xmit(struct net *net, struct sk_buff_head *list, } /* tipc_node_xmit_skb(): send single buffer to destination - * Buffers sent via this functon are generally TIPC_SYSTEM_IMPORTANCE + * Buffers sent via this function are generally TIPC_SYSTEM_IMPORTANCE * messages, which will not be rejected * The only exception is datagram messages rerouted after secondary * lookup, which are rare and safe to dispose of anyway. From df7232c4c676be29f1cf45058ec156c1183539ff Mon Sep 17 00:00:00 2001 From: Qingqing Zhuo Date: Thu, 25 Mar 2021 03:44:11 -0400 Subject: [PATCH 0787/1091] drm/amd/display: Add missing mask for DCN3 [Why] DCN3 is not reusing DCN1 mask_sh_list, causing SURFACE_FLIP_INT_MASK missing in the mapping. [How] Add the corresponding entry to DCN3 list. Signed-off-by: Qingqing Zhuo Reviewed-by: Nicholas Kazlauskas Acked-by: Qingqing Zhuo Signed-off-by: Alex Deucher --- drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h index 705fbfc37502..8a32772d4e91 100644 --- a/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h +++ b/drivers/gpu/drm/amd/display/dc/dcn30/dcn30_hubp.h @@ -134,6 +134,7 @@ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_EN, mask_sh),\ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_BLK, mask_sh),\ HUBP_SF(HUBPREQ0_DCSURF_SURFACE_CONTROL, SECONDARY_SURFACE_DCC_IND_BLK_C, mask_sh),\ + HUBP_SF(HUBPREQ0_DCSURF_SURFACE_FLIP_INTERRUPT, SURFACE_FLIP_INT_MASK, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, DET_BUF_PLANE1_BASE_ADDRESS, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CB_B, mask_sh),\ HUBP_SF(HUBPRET0_HUBPRET_CONTROL, CROSSBAR_SRC_CR_R, mask_sh),\ From a975d7d8a356ce92872af0b007b101183f0224e2 Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Wed, 7 Apr 2021 13:06:51 +0300 Subject: [PATCH 0788/1091] ethtool: Remove link_mode param and derive link params from driver Some drivers clear the 'ethtool_link_ksettings' struct in their get_link_ksettings() callback, before populating it with actual values. Such drivers will set the new 'link_mode' field to zero, resulting in user space receiving wrong link mode information given that zero is a valid value for the field. Another problem is that some drivers (notably tun) can report random values in the 'link_mode' field. This can result in a general protection fault when the field is used as an index to the 'link_mode_params' array [1]. This happens because such drivers implement their set_link_ksettings() callback by simply overwriting their private copy of 'ethtool_link_ksettings' struct with the one they get from the stack, which is not always properly initialized. Fix these problems by removing 'link_mode' from 'ethtool_link_ksettings' and instead have drivers call ethtool_params_from_link_mode() with the current link mode. The function will derive the link parameters (e.g., speed) from the link mode and fill them in the 'ethtool_link_ksettings' struct. v3: * Remove link_mode parameter and derive the link parameters in the driver instead of passing link_mode parameter to ethtool and derive it there. v2: * Introduce 'cap_link_mode_supported' instead of adding a validity field to 'ethtool_link_ksettings' struct. [1] general protection fault, probably for non-canonical address 0xdffffc00f14cc32c: 0000 [#1] PREEMPT SMP KASAN KASAN: probably user-memory-access in range [0x000000078a661960-0x000000078a661967] CPU: 0 PID: 8452 Comm: syz-executor360 Not tainted 5.11.0-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:__ethtool_get_link_ksettings+0x1a3/0x3a0 net/ethtool/ioctl.c:446 Code: b7 3e fa 83 fd ff 0f 84 30 01 00 00 e8 16 b0 3e fa 48 8d 3c ed 60 d5 69 8a 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 +38 d0 7c 08 84 d2 0f 85 b9 RSP: 0018:ffffc900019df7a0 EFLAGS: 00010202 RAX: dffffc0000000000 RBX: ffff888026136008 RCX: 0000000000000000 RDX: 00000000f14cc32c RSI: ffffffff873439ca RDI: 000000078a661960 RBP: 00000000ffff8880 R08: 00000000ffffffff R09: ffff88802613606f R10: ffffffff873439bc R11: 0000000000000000 R12: 0000000000000000 R13: ffff88802613606c R14: ffff888011d0c210 R15: ffff888011d0c210 FS: 0000000000749300(0000) GS:ffff8880b9c00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000004b60f0 CR3: 00000000185c2000 CR4: 00000000001506f0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: linkinfo_prepare_data+0xfd/0x280 net/ethtool/linkinfo.c:37 ethnl_default_notify+0x1dc/0x630 net/ethtool/netlink.c:586 ethtool_notify+0xbd/0x1f0 net/ethtool/netlink.c:656 ethtool_set_link_ksettings+0x277/0x330 net/ethtool/ioctl.c:620 dev_ethtool+0x2b35/0x45d0 net/ethtool/ioctl.c:2842 dev_ioctl+0x463/0xb70 net/core/dev_ioctl.c:440 sock_do_ioctl+0x148/0x2d0 net/socket.c:1060 sock_ioctl+0x477/0x6a0 net/socket.c:1177 vfs_ioctl fs/ioctl.c:48 [inline] __do_sys_ioctl fs/ioctl.c:753 [inline] __se_sys_ioctl fs/ioctl.c:739 [inline] __x64_sys_ioctl+0x193/0x200 fs/ioctl.c:739 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xa9 Fixes: c8907043c6ac9 ("ethtool: Get link mode in use instead of speed and duplex parameters") Signed-off-by: Danielle Ratson Reported-by: Eric Dumazet Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- .../mellanox/mlxsw/spectrum_ethtool.c | 19 ++++++++++++++----- include/linux/ethtool.h | 9 ++++++++- net/ethtool/common.c | 16 ++++++++++++++++ net/ethtool/ioctl.c | 18 +----------------- 4 files changed, 39 insertions(+), 23 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c index 0bd64169bf81..078601d31cde 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c @@ -1230,16 +1230,22 @@ mlxsw_sp1_from_ptys_link_mode(struct mlxsw_sp *mlxsw_sp, bool carrier_ok, u32 ptys_eth_proto, struct ethtool_link_ksettings *cmd) { + struct mlxsw_sp1_port_link_mode link; int i; - cmd->link_mode = -1; + cmd->base.speed = SPEED_UNKNOWN; + cmd->base.duplex = DUPLEX_UNKNOWN; + cmd->lanes = 0; if (!carrier_ok) return; for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { - if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) - cmd->link_mode = mlxsw_sp1_port_link_mode[i].mask_ethtool; + if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) { + link = mlxsw_sp1_port_link_mode[i]; + ethtool_params_from_link_mode(cmd, + link.mask_ethtool); + } } } @@ -1672,7 +1678,9 @@ mlxsw_sp2_from_ptys_link_mode(struct mlxsw_sp *mlxsw_sp, bool carrier_ok, struct mlxsw_sp2_port_link_mode link; int i; - cmd->link_mode = -1; + cmd->base.speed = SPEED_UNKNOWN; + cmd->base.duplex = DUPLEX_UNKNOWN; + cmd->lanes = 0; if (!carrier_ok) return; @@ -1680,7 +1688,8 @@ mlxsw_sp2_from_ptys_link_mode(struct mlxsw_sp *mlxsw_sp, bool carrier_ok, for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) { link = mlxsw_sp2_port_link_mode[i]; - cmd->link_mode = link.mask_ethtool[1]; + ethtool_params_from_link_mode(cmd, + link.mask_ethtool[1]); } } } diff --git a/include/linux/ethtool.h b/include/linux/ethtool.h index 7c88dfff7420..cdca84e6dd6b 100644 --- a/include/linux/ethtool.h +++ b/include/linux/ethtool.h @@ -127,7 +127,6 @@ struct ethtool_link_ksettings { __ETHTOOL_DECLARE_LINK_MODE_MASK(lp_advertising); } link_modes; u32 lanes; - enum ethtool_link_mode_bit_indices link_mode; }; /** @@ -574,4 +573,12 @@ struct ethtool_phy_ops { */ void ethtool_set_ethtool_phy_ops(const struct ethtool_phy_ops *ops); +/* + * ethtool_params_from_link_mode - Derive link parameters from a given link mode + * @link_ksettings: Link parameters to be derived from the link mode + * @link_mode: Link mode + */ +void +ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings, + enum ethtool_link_mode_bit_indices link_mode); #endif /* _LINUX_ETHTOOL_H */ diff --git a/net/ethtool/common.c b/net/ethtool/common.c index c6a383dfd6c2..030aa7984a91 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -562,3 +562,19 @@ void ethtool_set_ethtool_phy_ops(const struct ethtool_phy_ops *ops) rtnl_unlock(); } EXPORT_SYMBOL_GPL(ethtool_set_ethtool_phy_ops); + +void +ethtool_params_from_link_mode(struct ethtool_link_ksettings *link_ksettings, + enum ethtool_link_mode_bit_indices link_mode) +{ + const struct link_mode_info *link_info; + + if (WARN_ON_ONCE(link_mode >= __ETHTOOL_LINK_MODE_MASK_NBITS)) + return; + + link_info = &link_mode_params[link_mode]; + link_ksettings->base.speed = link_info->speed; + link_ksettings->lanes = link_info->lanes; + link_ksettings->base.duplex = link_info->duplex; +} +EXPORT_SYMBOL_GPL(ethtool_params_from_link_mode); diff --git a/net/ethtool/ioctl.c b/net/ethtool/ioctl.c index 24783b71c584..771688e1b0da 100644 --- a/net/ethtool/ioctl.c +++ b/net/ethtool/ioctl.c @@ -426,29 +426,13 @@ struct ethtool_link_usettings { int __ethtool_get_link_ksettings(struct net_device *dev, struct ethtool_link_ksettings *link_ksettings) { - const struct link_mode_info *link_info; - int err; - ASSERT_RTNL(); if (!dev->ethtool_ops->get_link_ksettings) return -EOPNOTSUPP; memset(link_ksettings, 0, sizeof(*link_ksettings)); - - link_ksettings->link_mode = -1; - err = dev->ethtool_ops->get_link_ksettings(dev, link_ksettings); - if (err) - return err; - - if (link_ksettings->link_mode != -1) { - link_info = &link_mode_params[link_ksettings->link_mode]; - link_ksettings->base.speed = link_info->speed; - link_ksettings->lanes = link_info->lanes; - link_ksettings->base.duplex = link_info->duplex; - } - - return 0; + return dev->ethtool_ops->get_link_ksettings(dev, link_ksettings); } EXPORT_SYMBOL(__ethtool_get_link_ksettings); From fde32dbe712bc7cea61d8c5ed14e10e17eec8257 Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Wed, 7 Apr 2021 13:06:52 +0300 Subject: [PATCH 0789/1091] ethtool: Add lanes parameter for ETHTOOL_LINK_MODE_10000baseR_FEC_BIT Lanes field is missing for ETHTOOL_LINK_MODE_10000baseR_FEC_BIT link mode and it causes a failure when trying to set 'speed 10000 lanes 1' on Spectrum-2 machines when autoneg is set to on. Add the lanes parameter for ETHTOOL_LINK_MODE_10000baseR_FEC_BIT link mode. Fixes: c8907043c6ac9 ("ethtool: Get link mode in use instead of speed and duplex parameters") Signed-off-by: Danielle Ratson Reviewed-by: Ido Schimmel Signed-off-by: David S. Miller --- net/ethtool/common.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/ethtool/common.c b/net/ethtool/common.c index 030aa7984a91..f9dcbad84788 100644 --- a/net/ethtool/common.c +++ b/net/ethtool/common.c @@ -273,6 +273,7 @@ const struct link_mode_info link_mode_params[] = { __DEFINE_LINK_MODE_PARAMS(10000, KR, Full), [ETHTOOL_LINK_MODE_10000baseR_FEC_BIT] = { .speed = SPEED_10000, + .lanes = 1, .duplex = DUPLEX_FULL, }, __DEFINE_LINK_MODE_PARAMS(20000, MLD2, Full), From 8a12f8836145ffe37e9c8733dce18c22fb668b66 Mon Sep 17 00:00:00 2001 From: Anirudh Rayabharam Date: Wed, 7 Apr 2021 22:57:22 +0530 Subject: [PATCH 0790/1091] net: hso: fix null-ptr-deref during tty device unregistration Multiple ttys try to claim the same the minor number causing a double unregistration of the same device. The first unregistration succeeds but the next one results in a null-ptr-deref. The get_free_serial_index() function returns an available minor number but doesn't assign it immediately. The assignment is done by the caller later. But before this assignment, calls to get_free_serial_index() would return the same minor number. Fix this by modifying get_free_serial_index to assign the minor number immediately after one is found to be and rename it to obtain_minor() to better reflect what it does. Similary, rename set_serial_by_index() to release_minor() and modify it to free up the minor number of the given hso_serial. Every obtain_minor() should have corresponding release_minor() call. Fixes: 72dc1c096c705 ("HSO: add option hso driver") Reported-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com Tested-by: syzbot+c49fe6089f295a05e6f8@syzkaller.appspotmail.com Reviewed-by: Greg Kroah-Hartman Signed-off-by: Anirudh Rayabharam Signed-off-by: David S. Miller --- drivers/net/usb/hso.c | 33 ++++++++++++--------------------- 1 file changed, 12 insertions(+), 21 deletions(-) diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index 31d51346786a..9bc58e64b5b7 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -611,7 +611,7 @@ static struct hso_serial *get_serial_by_index(unsigned index) return serial; } -static int get_free_serial_index(void) +static int obtain_minor(struct hso_serial *serial) { int index; unsigned long flags; @@ -619,8 +619,10 @@ static int get_free_serial_index(void) spin_lock_irqsave(&serial_table_lock, flags); for (index = 0; index < HSO_SERIAL_TTY_MINORS; index++) { if (serial_table[index] == NULL) { + serial_table[index] = serial->parent; + serial->minor = index; spin_unlock_irqrestore(&serial_table_lock, flags); - return index; + return 0; } } spin_unlock_irqrestore(&serial_table_lock, flags); @@ -629,15 +631,12 @@ static int get_free_serial_index(void) return -1; } -static void set_serial_by_index(unsigned index, struct hso_serial *serial) +static void release_minor(struct hso_serial *serial) { unsigned long flags; spin_lock_irqsave(&serial_table_lock, flags); - if (serial) - serial_table[index] = serial->parent; - else - serial_table[index] = NULL; + serial_table[serial->minor] = NULL; spin_unlock_irqrestore(&serial_table_lock, flags); } @@ -2230,6 +2229,7 @@ static int hso_stop_serial_device(struct hso_device *hso_dev) static void hso_serial_tty_unregister(struct hso_serial *serial) { tty_unregister_device(tty_drv, serial->minor); + release_minor(serial); } static void hso_serial_common_free(struct hso_serial *serial) @@ -2253,24 +2253,22 @@ static void hso_serial_common_free(struct hso_serial *serial) static int hso_serial_common_create(struct hso_serial *serial, int num_urbs, int rx_size, int tx_size) { - int minor; int i; tty_port_init(&serial->port); - minor = get_free_serial_index(); - if (minor < 0) + if (obtain_minor(serial)) goto exit2; /* register our minor number */ serial->parent->dev = tty_port_register_device_attr(&serial->port, - tty_drv, minor, &serial->parent->interface->dev, + tty_drv, serial->minor, &serial->parent->interface->dev, serial->parent, hso_serial_dev_groups); - if (IS_ERR(serial->parent->dev)) + if (IS_ERR(serial->parent->dev)) { + release_minor(serial); goto exit2; + } - /* fill in specific data for later use */ - serial->minor = minor; serial->magic = HSO_SERIAL_MAGIC; spin_lock_init(&serial->serial_lock); serial->num_rx_urbs = num_urbs; @@ -2667,9 +2665,6 @@ static struct hso_device *hso_create_bulk_serial_device( serial->write_data = hso_std_serial_write_data; - /* and record this serial */ - set_serial_by_index(serial->minor, serial); - /* setup the proc dirs and files if needed */ hso_log_port(hso_dev); @@ -2726,9 +2721,6 @@ struct hso_device *hso_create_mux_serial_device(struct usb_interface *interface, serial->shared_int->ref_count++; mutex_unlock(&serial->shared_int->shared_int_lock); - /* and record this serial */ - set_serial_by_index(serial->minor, serial); - /* setup the proc dirs and files if needed */ hso_log_port(hso_dev); @@ -3113,7 +3105,6 @@ static void hso_free_interface(struct usb_interface *interface) cancel_work_sync(&serial_table[i]->async_get_intf); hso_serial_tty_unregister(serial); kref_put(&serial_table[i]->ref, hso_serial_ref_free); - set_serial_by_index(i, NULL); } } From 50ce6826a48f119baf2794fa384a64efe9bd84a5 Mon Sep 17 00:00:00 2001 From: Dmitry Baryshkov Date: Wed, 7 Apr 2021 02:06:06 +0300 Subject: [PATCH 0791/1091] clk: fixed: fix double free in resource managed fixed-factor clock devm_clk_hw_register_fixed_factor_release(), the release function for the devm_clk_hw_register_fixed_factor(), calls clk_hw_unregister_fixed_factor(), which will kfree() the clock. However after that the devres functions will also kfree the allocated data, resulting in double free/memory corruption. Just call clk_hw_unregister() instead, leaving kfree() to devres code. Reported-by: Rob Clark Cc: Daniel Palmer Signed-off-by: Dmitry Baryshkov Link: https://lore.kernel.org/r/20210406230606.3007138-1-dmitry.baryshkov@linaro.org Fixes: 0b9266d295ce ("clk: fixed: add devm helper for clk_hw_register_fixed_factor()") [sboyd@kernel.org: Remove ugly cast] Signed-off-by: Stephen Boyd --- drivers/clk/clk-fixed-factor.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/clk/clk-fixed-factor.c b/drivers/clk/clk-fixed-factor.c index 4f7bf3929d6d..4e4b6d367612 100644 --- a/drivers/clk/clk-fixed-factor.c +++ b/drivers/clk/clk-fixed-factor.c @@ -66,7 +66,14 @@ EXPORT_SYMBOL_GPL(clk_fixed_factor_ops); static void devm_clk_hw_register_fixed_factor_release(struct device *dev, void *res) { - clk_hw_unregister_fixed_factor(&((struct clk_fixed_factor *)res)->hw); + struct clk_fixed_factor *fix = res; + + /* + * We can not use clk_hw_unregister_fixed_factor, since it will kfree() + * the hw, resulting in double free. Just unregister the hw and let + * devres code kfree() it. + */ + clk_hw_unregister(&fix->hw); } static struct clk_hw * From b6a37a93c9ac3900987c79b726d0bb3699d8db4e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Fri, 2 Apr 2021 10:23:17 +0200 Subject: [PATCH 0792/1091] drm/i915: Fix invalid access to ACPI _DSM objects MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit intel_dsm_platform_mux_info() tries to parse the ACPI package data from _DSM for the debug information, but it assumes the fixed format without checking what values are stored in the elements actually. When an unexpected value is returned from BIOS, it may lead to GPF or NULL dereference, as reported recently. Add the checks of the contents in the returned values and skip the values for invalid cases. v1->v2: Check the info contents before dereferencing, too BugLink: http://bugzilla.opensuse.org/show_bug.cgi?id=1184074 Cc: Signed-off-by: Takashi Iwai Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20210402082317.871-1-tiwai@suse.de (cherry picked from commit 337d7a1621c7f02af867229990ac67c97da1b53a) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_acpi.c | 22 ++++++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/intel_acpi.c b/drivers/gpu/drm/i915/display/intel_acpi.c index e21fb14d5e07..833d0c1be4f1 100644 --- a/drivers/gpu/drm/i915/display/intel_acpi.c +++ b/drivers/gpu/drm/i915/display/intel_acpi.c @@ -84,13 +84,31 @@ static void intel_dsm_platform_mux_info(acpi_handle dhandle) return; } + if (!pkg->package.count) { + DRM_DEBUG_DRIVER("no connection in _DSM\n"); + return; + } + connector_count = &pkg->package.elements[0]; DRM_DEBUG_DRIVER("MUX info connectors: %lld\n", (unsigned long long)connector_count->integer.value); for (i = 1; i < pkg->package.count; i++) { union acpi_object *obj = &pkg->package.elements[i]; - union acpi_object *connector_id = &obj->package.elements[0]; - union acpi_object *info = &obj->package.elements[1]; + union acpi_object *connector_id; + union acpi_object *info; + + if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count < 2) { + DRM_DEBUG_DRIVER("Invalid object for MUX #%d\n", i); + continue; + } + + connector_id = &obj->package.elements[0]; + info = &obj->package.elements[1]; + if (info->type != ACPI_TYPE_BUFFER || info->buffer.length < 4) { + DRM_DEBUG_DRIVER("Invalid info for MUX obj #%d\n", i); + continue; + } + DRM_DEBUG_DRIVER("Connector id: 0x%016llx\n", (unsigned long long)connector_id->integer.value); DRM_DEBUG_DRIVER(" port id: %s\n", From e1ad897b9c738d5550be6762bf3a6ef1672259a4 Mon Sep 17 00:00:00 2001 From: Kamal Heib Date: Sun, 4 Apr 2021 15:55:01 +0300 Subject: [PATCH 0793/1091] RDMA/qedr: Fix kernel panic when trying to access recv_cq As INI QP does not require a recv_cq, avoid the following null pointer dereference by checking if the qp_type is not INI before trying to extract the recv_cq. BUG: kernel NULL pointer dereference, address: 00000000000000e0 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 0 P4D 0 Oops: 0000 [#1] SMP PTI CPU: 0 PID: 54250 Comm: mpitests-IMB-MP Not tainted 5.12.0-rc5 #1 Hardware name: Dell Inc. PowerEdge R320/0KM5PX, BIOS 2.7.0 08/19/2019 RIP: 0010:qedr_create_qp+0x378/0x820 [qedr] Code: 02 00 00 50 e8 29 d4 a9 d1 48 83 c4 18 e9 65 fe ff ff 48 8b 53 10 48 8b 43 18 44 8b 82 e0 00 00 00 45 85 c0 0f 84 10 74 00 00 <8b> b8 e0 00 00 00 85 ff 0f 85 50 fd ff ff e9 fd 73 00 00 48 8d bd RSP: 0018:ffff9c8f056f7a70 EFLAGS: 00010202 RAX: 0000000000000000 RBX: ffff9c8f056f7b58 RCX: 0000000000000009 RDX: ffff8c41a9744c00 RSI: ffff9c8f056f7b58 RDI: ffff8c41c0dfa280 RBP: ffff8c41c0dfa280 R08: 0000000000000002 R09: 0000000000000001 R10: 0000000000000000 R11: ffff8c41e06fc608 R12: ffff8c4194052000 R13: 0000000000000000 R14: ffff8c4191546070 R15: ffff8c41c0dfa280 FS: 00007f78b2787b80(0000) GS:ffff8c43a3200000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000000000e0 CR3: 00000001011d6002 CR4: 00000000001706f0 Call Trace: ib_uverbs_handler_UVERBS_METHOD_QP_CREATE+0x4e4/0xb90 [ib_uverbs] ? ib_uverbs_cq_event_handler+0x30/0x30 [ib_uverbs] ib_uverbs_run_method+0x6f6/0x7a0 [ib_uverbs] ? ib_uverbs_handler_UVERBS_METHOD_QP_DESTROY+0x70/0x70 [ib_uverbs] ? __cond_resched+0x15/0x30 ? __kmalloc+0x5a/0x440 ib_uverbs_cmd_verbs+0x195/0x360 [ib_uverbs] ? xa_load+0x6e/0x90 ? cred_has_capability+0x7c/0x130 ? avc_has_extended_perms+0x17f/0x440 ? vma_link+0xae/0xb0 ? vma_set_page_prot+0x2a/0x60 ? mmap_region+0x298/0x6c0 ? do_mmap+0x373/0x520 ? selinux_file_ioctl+0x17f/0x220 ib_uverbs_ioctl+0xa7/0x110 [ib_uverbs] __x64_sys_ioctl+0x84/0xc0 do_syscall_64+0x33/0x40 entry_SYSCALL_64_after_hwframe+0x44/0xae RIP: 0033:0x7f78b120262b Fixes: 06e8d1df46ed ("RDMA/qedr: Add support for user mode XRC-SRQ's") Link: https://lore.kernel.org/r/20210404125501.154789-1-kamalheib1@gmail.com Signed-off-by: Kamal Heib Signed-off-by: Jason Gunthorpe --- drivers/infiniband/hw/qedr/verbs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/hw/qedr/verbs.c b/drivers/infiniband/hw/qedr/verbs.c index 0eb6a7a618e0..9ea542270ed4 100644 --- a/drivers/infiniband/hw/qedr/verbs.c +++ b/drivers/infiniband/hw/qedr/verbs.c @@ -1244,7 +1244,8 @@ static int qedr_check_qp_attrs(struct ib_pd *ibpd, struct qedr_dev *dev, * TGT QP isn't associated with RQ/SQ */ if ((attrs->qp_type != IB_QPT_GSI) && (dev->gsi_qp_created) && - (attrs->qp_type != IB_QPT_XRC_TGT)) { + (attrs->qp_type != IB_QPT_XRC_TGT) && + (attrs->qp_type != IB_QPT_XRC_INI)) { struct qedr_cq *send_cq = get_qedr_cq(attrs->send_cq); struct qedr_cq *recv_cq = get_qedr_cq(attrs->recv_cq); From 9ad6e9cb39c66366bf7b9aece114aca277981a1f Mon Sep 17 00:00:00 2001 From: Ondrej Mosnacek Date: Wed, 7 Apr 2021 09:24:43 +0200 Subject: [PATCH 0794/1091] selinux: fix race between old and new sidtab Since commit 1b8b31a2e612 ("selinux: convert policy read-write lock to RCU"), there is a small window during policy load where the new policy pointer has already been installed, but some threads may still be holding the old policy pointer in their read-side RCU critical sections. This means that there may be conflicting attempts to add a new SID entry to both tables via sidtab_context_to_sid(). See also (and the rest of the thread): https://lore.kernel.org/selinux/CAFqZXNvfux46_f8gnvVvRYMKoes24nwm2n3sPbMjrB8vKTW00g@mail.gmail.com/ Fix this by installing the new policy pointer under the old sidtab's spinlock along with marking the old sidtab as "frozen". Then, if an attempt to add new entry to a "frozen" sidtab is detected, make sidtab_context_to_sid() return -ESTALE to indicate that a new policy has been installed and that the caller will have to abort the policy transaction and try again after re-taking the policy pointer (which is guaranteed to be a newer policy). This requires adding a retry-on-ESTALE logic to all callers of sidtab_context_to_sid(), but fortunately these are easy to determine and aren't that many. This seems to be the simplest solution for this problem, even if it looks somewhat ugly. Note that other places in the kernel (e.g. do_mknodat() in fs/namei.c) use similar stale-retry patterns, so I think it's reasonable. Cc: stable@vger.kernel.org Fixes: 1b8b31a2e612 ("selinux: convert policy read-write lock to RCU") Signed-off-by: Ondrej Mosnacek Signed-off-by: Paul Moore --- security/selinux/ss/services.c | 157 +++++++++++++++++++++++++-------- security/selinux/ss/sidtab.c | 21 +++++ security/selinux/ss/sidtab.h | 4 + 3 files changed, 145 insertions(+), 37 deletions(-) diff --git a/security/selinux/ss/services.c b/security/selinux/ss/services.c index 4a907e008a98..6f095c0dc658 100644 --- a/security/selinux/ss/services.c +++ b/security/selinux/ss/services.c @@ -1551,6 +1551,7 @@ static int security_context_to_sid_core(struct selinux_state *state, if (!str) goto out; } +retry: rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -1564,6 +1565,15 @@ static int security_context_to_sid_core(struct selinux_state *state, } else if (rc) goto out_unlock; rc = sidtab_context_to_sid(sidtab, &context, sid); + if (rc == -ESTALE) { + rcu_read_unlock(); + if (context.str) { + str = context.str; + context.str = NULL; + } + context_destroy(&context); + goto retry; + } context_destroy(&context); out_unlock: rcu_read_unlock(); @@ -1713,7 +1723,7 @@ static int security_compute_sid(struct selinux_state *state, struct selinux_policy *policy; struct policydb *policydb; struct sidtab *sidtab; - struct class_datum *cladatum = NULL; + struct class_datum *cladatum; struct context *scontext, *tcontext, newcontext; struct sidtab_entry *sentry, *tentry; struct avtab_key avkey; @@ -1735,6 +1745,8 @@ static int security_compute_sid(struct selinux_state *state, goto out; } +retry: + cladatum = NULL; context_init(&newcontext); rcu_read_lock(); @@ -1879,6 +1891,11 @@ static int security_compute_sid(struct selinux_state *state, } /* Obtain the sid for the context. */ rc = sidtab_context_to_sid(sidtab, &newcontext, out_sid); + if (rc == -ESTALE) { + rcu_read_unlock(); + context_destroy(&newcontext); + goto retry; + } out_unlock: rcu_read_unlock(); context_destroy(&newcontext); @@ -2190,6 +2207,7 @@ void selinux_policy_commit(struct selinux_state *state, struct selinux_load_state *load_state) { struct selinux_policy *oldpolicy, *newpolicy = load_state->policy; + unsigned long flags; u32 seqno; oldpolicy = rcu_dereference_protected(state->policy, @@ -2211,7 +2229,13 @@ void selinux_policy_commit(struct selinux_state *state, seqno = newpolicy->latest_granting; /* Install the new policy. */ - rcu_assign_pointer(state->policy, newpolicy); + if (oldpolicy) { + sidtab_freeze_begin(oldpolicy->sidtab, &flags); + rcu_assign_pointer(state->policy, newpolicy); + sidtab_freeze_end(oldpolicy->sidtab, &flags); + } else { + rcu_assign_pointer(state->policy, newpolicy); + } /* Load the policycaps from the new policy */ security_load_policycaps(state, newpolicy); @@ -2355,13 +2379,15 @@ int security_port_sid(struct selinux_state *state, struct policydb *policydb; struct sidtab *sidtab; struct ocontext *c; - int rc = 0; + int rc; if (!selinux_initialized(state)) { *out_sid = SECINITSID_PORT; return 0; } +retry: + rc = 0; rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -2380,6 +2406,10 @@ int security_port_sid(struct selinux_state *state, if (!c->sid[0]) { rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out; } @@ -2406,13 +2436,15 @@ int security_ib_pkey_sid(struct selinux_state *state, struct policydb *policydb; struct sidtab *sidtab; struct ocontext *c; - int rc = 0; + int rc; if (!selinux_initialized(state)) { *out_sid = SECINITSID_UNLABELED; return 0; } +retry: + rc = 0; rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -2433,6 +2465,10 @@ int security_ib_pkey_sid(struct selinux_state *state, rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out; } @@ -2458,13 +2494,15 @@ int security_ib_endport_sid(struct selinux_state *state, struct policydb *policydb; struct sidtab *sidtab; struct ocontext *c; - int rc = 0; + int rc; if (!selinux_initialized(state)) { *out_sid = SECINITSID_UNLABELED; return 0; } +retry: + rc = 0; rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -2485,6 +2523,10 @@ int security_ib_endport_sid(struct selinux_state *state, if (!c->sid[0]) { rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out; } @@ -2508,7 +2550,7 @@ int security_netif_sid(struct selinux_state *state, struct selinux_policy *policy; struct policydb *policydb; struct sidtab *sidtab; - int rc = 0; + int rc; struct ocontext *c; if (!selinux_initialized(state)) { @@ -2516,6 +2558,8 @@ int security_netif_sid(struct selinux_state *state, return 0; } +retry: + rc = 0; rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -2532,10 +2576,18 @@ int security_netif_sid(struct selinux_state *state, if (!c->sid[0] || !c->sid[1]) { rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out; rc = sidtab_context_to_sid(sidtab, &c->context[1], &c->sid[1]); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out; } @@ -2585,6 +2637,7 @@ int security_node_sid(struct selinux_state *state, return 0; } +retry: rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -2633,6 +2686,10 @@ int security_node_sid(struct selinux_state *state, rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out; } @@ -2674,18 +2731,24 @@ int security_get_user_sids(struct selinux_state *state, struct sidtab *sidtab; struct context *fromcon, usercon; u32 *mysids = NULL, *mysids2, sid; - u32 mynel = 0, maxnel = SIDS_NEL; + u32 i, j, mynel, maxnel = SIDS_NEL; struct user_datum *user; struct role_datum *role; struct ebitmap_node *rnode, *tnode; - int rc = 0, i, j; + int rc; *sids = NULL; *nel = 0; if (!selinux_initialized(state)) - goto out; + return 0; + mysids = kcalloc(maxnel, sizeof(*mysids), GFP_KERNEL); + if (!mysids) + return -ENOMEM; + +retry: + mynel = 0; rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -2705,11 +2768,6 @@ int security_get_user_sids(struct selinux_state *state, usercon.user = user->value; - rc = -ENOMEM; - mysids = kcalloc(maxnel, sizeof(*mysids), GFP_ATOMIC); - if (!mysids) - goto out_unlock; - ebitmap_for_each_positive_bit(&user->roles, rnode, i) { role = policydb->role_val_to_struct[i]; usercon.role = i + 1; @@ -2721,6 +2779,10 @@ int security_get_user_sids(struct selinux_state *state, continue; rc = sidtab_context_to_sid(sidtab, &usercon, &sid); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out_unlock; if (mynel < maxnel) { @@ -2743,14 +2805,14 @@ out_unlock: rcu_read_unlock(); if (rc || !mynel) { kfree(mysids); - goto out; + return rc; } rc = -ENOMEM; mysids2 = kcalloc(mynel, sizeof(*mysids2), GFP_KERNEL); if (!mysids2) { kfree(mysids); - goto out; + return rc; } for (i = 0, j = 0; i < mynel; i++) { struct av_decision dummy_avd; @@ -2763,12 +2825,10 @@ out_unlock: mysids2[j++] = mysids[i]; cond_resched(); } - rc = 0; kfree(mysids); *sids = mysids2; *nel = j; -out: - return rc; + return 0; } /** @@ -2781,6 +2841,9 @@ out: * Obtain a SID to use for a file in a filesystem that * cannot support xattr or use a fixed labeling behavior like * transition SIDs or task SIDs. + * + * WARNING: This function may return -ESTALE, indicating that the caller + * must retry the operation after re-acquiring the policy pointer! */ static inline int __security_genfs_sid(struct selinux_policy *policy, const char *fstype, @@ -2859,11 +2922,13 @@ int security_genfs_sid(struct selinux_state *state, return 0; } - rcu_read_lock(); - policy = rcu_dereference(state->policy); - retval = __security_genfs_sid(policy, - fstype, path, orig_sclass, sid); - rcu_read_unlock(); + do { + rcu_read_lock(); + policy = rcu_dereference(state->policy); + retval = __security_genfs_sid(policy, fstype, path, + orig_sclass, sid); + rcu_read_unlock(); + } while (retval == -ESTALE); return retval; } @@ -2886,7 +2951,7 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) struct selinux_policy *policy; struct policydb *policydb; struct sidtab *sidtab; - int rc = 0; + int rc; struct ocontext *c; struct superblock_security_struct *sbsec = sb->s_security; const char *fstype = sb->s_type->name; @@ -2897,6 +2962,8 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) return 0; } +retry: + rc = 0; rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -2914,6 +2981,10 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) if (!c->sid[0]) { rc = sidtab_context_to_sid(sidtab, &c->context[0], &c->sid[0]); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) goto out; } @@ -2921,6 +2992,10 @@ int security_fs_use(struct selinux_state *state, struct super_block *sb) } else { rc = __security_genfs_sid(policy, fstype, "/", SECCLASS_DIR, &sbsec->sid); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) { sbsec->behavior = SECURITY_FS_USE_NONE; rc = 0; @@ -3130,12 +3205,13 @@ int security_sid_mls_copy(struct selinux_state *state, u32 len; int rc; - rc = 0; if (!selinux_initialized(state)) { *new_sid = sid; - goto out; + return 0; } +retry: + rc = 0; context_init(&newcon); rcu_read_lock(); @@ -3194,10 +3270,14 @@ int security_sid_mls_copy(struct selinux_state *state, } } rc = sidtab_context_to_sid(sidtab, &newcon, new_sid); + if (rc == -ESTALE) { + rcu_read_unlock(); + context_destroy(&newcon); + goto retry; + } out_unlock: rcu_read_unlock(); context_destroy(&newcon); -out: return rc; } @@ -3790,6 +3870,8 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, return 0; } +retry: + rc = 0; rcu_read_lock(); policy = rcu_dereference(state->policy); policydb = &policy->policydb; @@ -3816,23 +3898,24 @@ int security_netlbl_secattr_to_sid(struct selinux_state *state, goto out; } rc = -EIDRM; - if (!mls_context_isvalid(policydb, &ctx_new)) - goto out_free; + if (!mls_context_isvalid(policydb, &ctx_new)) { + ebitmap_destroy(&ctx_new.range.level[0].cat); + goto out; + } rc = sidtab_context_to_sid(sidtab, &ctx_new, sid); + ebitmap_destroy(&ctx_new.range.level[0].cat); + if (rc == -ESTALE) { + rcu_read_unlock(); + goto retry; + } if (rc) - goto out_free; + goto out; security_netlbl_cache_add(secattr, *sid); - - ebitmap_destroy(&ctx_new.range.level[0].cat); } else *sid = SECSID_NULL; - rcu_read_unlock(); - return 0; -out_free: - ebitmap_destroy(&ctx_new.range.level[0].cat); out: rcu_read_unlock(); return rc; diff --git a/security/selinux/ss/sidtab.c b/security/selinux/ss/sidtab.c index 5ee190bd30f5..656d50b09f76 100644 --- a/security/selinux/ss/sidtab.c +++ b/security/selinux/ss/sidtab.c @@ -39,6 +39,7 @@ int sidtab_init(struct sidtab *s) for (i = 0; i < SECINITSID_NUM; i++) s->isids[i].set = 0; + s->frozen = false; s->count = 0; s->convert = NULL; hash_init(s->context_to_sid); @@ -281,6 +282,15 @@ int sidtab_context_to_sid(struct sidtab *s, struct context *context, if (*sid) goto out_unlock; + if (unlikely(s->frozen)) { + /* + * This sidtab is now frozen - tell the caller to abort and + * get the new one. + */ + rc = -ESTALE; + goto out_unlock; + } + count = s->count; convert = s->convert; @@ -474,6 +484,17 @@ void sidtab_cancel_convert(struct sidtab *s) spin_unlock_irqrestore(&s->lock, flags); } +void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock) +{ + spin_lock_irqsave(&s->lock, *flags); + s->frozen = true; + s->convert = NULL; +} +void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock) +{ + spin_unlock_irqrestore(&s->lock, *flags); +} + static void sidtab_destroy_entry(struct sidtab_entry *entry) { context_destroy(&entry->context); diff --git a/security/selinux/ss/sidtab.h b/security/selinux/ss/sidtab.h index 80c744d07ad6..4eff0e49dcb2 100644 --- a/security/selinux/ss/sidtab.h +++ b/security/selinux/ss/sidtab.h @@ -86,6 +86,7 @@ struct sidtab { u32 count; /* access only under spinlock */ struct sidtab_convert_params *convert; + bool frozen; spinlock_t lock; #if CONFIG_SECURITY_SELINUX_SID2STR_CACHE_SIZE > 0 @@ -125,6 +126,9 @@ int sidtab_convert(struct sidtab *s, struct sidtab_convert_params *params); void sidtab_cancel_convert(struct sidtab *s); +void sidtab_freeze_begin(struct sidtab *s, unsigned long *flags) __acquires(&s->lock); +void sidtab_freeze_end(struct sidtab *s, unsigned long *flags) __releases(&s->lock); + int sidtab_context_to_sid(struct sidtab *s, struct context *context, u32 *sid); void sidtab_destroy(struct sidtab *s); From 0dcf8febcb7b9d42bec98bc068e01d1a6ea578b8 Mon Sep 17 00:00:00 2001 From: Mike Christie Date: Tue, 6 Apr 2021 12:17:46 -0500 Subject: [PATCH 0795/1091] scsi: iscsi: Fix iSCSI cls conn state In commit 9e67600ed6b8 ("scsi: iscsi: Fix race condition between login and sync thread") I missed that libiscsi was now setting the iSCSI class state, and that patch ended up resetting the state during conn stoppage and using the wrong state value during ep_disconnect. This patch moves the setting of the class state to the class module and then fixes the two issues above. Link: https://lore.kernel.org/r/20210406171746.5016-1-michael.christie@oracle.com Fixes: 9e67600ed6b8 ("scsi: iscsi: Fix race condition between login and sync thread") Cc: Gulam Mohamed Signed-off-by: Mike Christie Signed-off-by: Martin K. Petersen --- drivers/scsi/libiscsi.c | 26 +++----------------------- drivers/scsi/scsi_transport_iscsi.c | 20 ++++++++++++++++---- 2 files changed, 19 insertions(+), 27 deletions(-) diff --git a/drivers/scsi/libiscsi.c b/drivers/scsi/libiscsi.c index 7ad11e42306d..bfd2aaa9b66b 100644 --- a/drivers/scsi/libiscsi.c +++ b/drivers/scsi/libiscsi.c @@ -3179,9 +3179,10 @@ fail_mgmt_tasks(struct iscsi_session *session, struct iscsi_conn *conn) } } -static void iscsi_start_session_recovery(struct iscsi_session *session, - struct iscsi_conn *conn, int flag) +void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) { + struct iscsi_conn *conn = cls_conn->dd_data; + struct iscsi_session *session = conn->session; int old_stop_stage; mutex_lock(&session->eh_mutex); @@ -3239,27 +3240,6 @@ static void iscsi_start_session_recovery(struct iscsi_session *session, spin_unlock_bh(&session->frwd_lock); mutex_unlock(&session->eh_mutex); } - -void iscsi_conn_stop(struct iscsi_cls_conn *cls_conn, int flag) -{ - struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session = conn->session; - - switch (flag) { - case STOP_CONN_RECOVER: - cls_conn->state = ISCSI_CONN_FAILED; - break; - case STOP_CONN_TERM: - cls_conn->state = ISCSI_CONN_DOWN; - break; - default: - iscsi_conn_printk(KERN_ERR, conn, - "invalid stop flag %d\n", flag); - return; - } - - iscsi_start_session_recovery(session, conn, flag); -} EXPORT_SYMBOL_GPL(iscsi_conn_stop); int iscsi_conn_bind(struct iscsi_cls_session *cls_session, diff --git a/drivers/scsi/scsi_transport_iscsi.c b/drivers/scsi/scsi_transport_iscsi.c index bebfb355abdf..21a2d997a72e 100644 --- a/drivers/scsi/scsi_transport_iscsi.c +++ b/drivers/scsi/scsi_transport_iscsi.c @@ -2470,10 +2470,22 @@ static void iscsi_if_stop_conn(struct iscsi_cls_conn *conn, int flag) * it works. */ mutex_lock(&conn_mutex); - conn->transport->stop_conn(conn, flag); - conn->state = ISCSI_CONN_DOWN; - mutex_unlock(&conn_mutex); + switch (flag) { + case STOP_CONN_RECOVER: + conn->state = ISCSI_CONN_FAILED; + break; + case STOP_CONN_TERM: + conn->state = ISCSI_CONN_DOWN; + break; + default: + iscsi_cls_conn_printk(KERN_ERR, conn, + "invalid stop flag %d\n", flag); + goto unlock; + } + conn->transport->stop_conn(conn, flag); +unlock: + mutex_unlock(&conn_mutex); } static void stop_conn_work_fn(struct work_struct *work) @@ -2961,7 +2973,7 @@ static int iscsi_if_ep_disconnect(struct iscsi_transport *transport, mutex_lock(&conn->ep_mutex); conn->ep = NULL; mutex_unlock(&conn->ep_mutex); - conn->state = ISCSI_CONN_DOWN; + conn->state = ISCSI_CONN_FAILED; } transport->ep_disconnect(ep); From 176ddd89171ddcf661862d90c5d257877f7326d6 Mon Sep 17 00:00:00 2001 From: Jolly Shah Date: Thu, 18 Mar 2021 15:56:32 -0700 Subject: [PATCH 0796/1091] scsi: libsas: Reset num_scatter if libata marks qc as NODATA When the cache_type for the SCSI device is changed, the SCSI layer issues a MODE_SELECT command. The caching mode details are communicated via a request buffer associated with the SCSI command with data direction set as DMA_TO_DEVICE (scsi_mode_select()). When this command reaches the libata layer, as a part of generic initial setup, libata layer sets up the scatterlist for the command using the SCSI command (ata_scsi_qc_new()). This command is then translated by the libata layer into ATA_CMD_SET_FEATURES (ata_scsi_mode_select_xlat()). The libata layer treats this as a non-data command (ata_mselect_caching()), since it only needs an ATA taskfile to pass the caching on/off information to the device. It does not need the scatterlist that has been setup, so it does not perform dma_map_sg() on the scatterlist (ata_qc_issue()). Unfortunately, when this command reaches the libsas layer (sas_ata_qc_issue()), libsas layer sees it as a non-data command with a scatterlist. It cannot extract the correct DMA length since the scatterlist has not been mapped with dma_map_sg() for a DMA operation. When this partially constructed SAS task reaches pm80xx LLDD, it results in the following warning: "pm80xx_chip_sata_req 6058: The sg list address start_addr=0x0000000000000000 data_len=0x0end_addr_high=0xffffffff end_addr_low=0xffffffff has crossed 4G boundary" Update libsas to handle ATA non-data commands separately so num_scatter and total_xfer_len remain 0. Link: https://lore.kernel.org/r/20210318225632.2481291-1-jollys@google.com Fixes: 53de092f47ff ("scsi: libsas: Set data_dir as DMA_NONE if libata marks qc as NODATA") Tested-by: Luo Jiaxing Reviewed-by: John Garry Signed-off-by: Jolly Shah Signed-off-by: Martin K. Petersen --- drivers/scsi/libsas/sas_ata.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/drivers/scsi/libsas/sas_ata.c b/drivers/scsi/libsas/sas_ata.c index 024e5a550759..8b9a39077dba 100644 --- a/drivers/scsi/libsas/sas_ata.c +++ b/drivers/scsi/libsas/sas_ata.c @@ -201,18 +201,17 @@ static unsigned int sas_ata_qc_issue(struct ata_queued_cmd *qc) memcpy(task->ata_task.atapi_packet, qc->cdb, qc->dev->cdb_len); task->total_xfer_len = qc->nbytes; task->num_scatter = qc->n_elem; + task->data_dir = qc->dma_dir; + } else if (qc->tf.protocol == ATA_PROT_NODATA) { + task->data_dir = DMA_NONE; } else { for_each_sg(qc->sg, sg, qc->n_elem, si) xfer += sg_dma_len(sg); task->total_xfer_len = xfer; task->num_scatter = si; - } - - if (qc->tf.protocol == ATA_PROT_NODATA) - task->data_dir = DMA_NONE; - else task->data_dir = qc->dma_dir; + } task->scatter = qc->sg; task->ata_task.retry_count = 1; task->task_state_flags = SAS_TASK_STATE_PENDING; From 4e456b30f78c429b183db420e23b26cde7e03a78 Mon Sep 17 00:00:00 2001 From: Shyam Prasad N Date: Wed, 31 Mar 2021 14:35:24 +0000 Subject: [PATCH 0797/1091] cifs: On cifs_reconnect, resolve the hostname again. On cifs_reconnect, make sure that DNS resolution happens again. It could be the cause of connection to go dead in the first place. This also contains the fix for a build issue identified by Intel bot. Reported-by: kernel test robot Signed-off-by: Shyam Prasad N Reviewed-by: Paulo Alcantara (SUSE) Reviewed-by: Pavel Shilovsky CC: # 5.11+ Signed-off-by: Steve French --- fs/cifs/Kconfig | 3 +-- fs/cifs/Makefile | 5 +++-- fs/cifs/connect.c | 17 ++++++++++++++++- 3 files changed, 20 insertions(+), 5 deletions(-) diff --git a/fs/cifs/Kconfig b/fs/cifs/Kconfig index fe03cbdae959..bf52e9326ebe 100644 --- a/fs/cifs/Kconfig +++ b/fs/cifs/Kconfig @@ -18,6 +18,7 @@ config CIFS select CRYPTO_AES select CRYPTO_LIB_DES select KEYS + select DNS_RESOLVER help This is the client VFS module for the SMB3 family of NAS protocols, (including support for the most recent, most secure dialect SMB3.1.1) @@ -112,7 +113,6 @@ config CIFS_WEAK_PW_HASH config CIFS_UPCALL bool "Kerberos/SPNEGO advanced session setup" depends on CIFS - select DNS_RESOLVER help Enables an upcall mechanism for CIFS which accesses userspace helper utilities to provide SPNEGO packaged (RFC 4178) Kerberos tickets @@ -179,7 +179,6 @@ config CIFS_DEBUG_DUMP_KEYS config CIFS_DFS_UPCALL bool "DFS feature support" depends on CIFS - select DNS_RESOLVER help Distributed File System (DFS) support is used to access shares transparently in an enterprise name space, even if the share diff --git a/fs/cifs/Makefile b/fs/cifs/Makefile index 5213b20843b5..3ee3b7de4ded 100644 --- a/fs/cifs/Makefile +++ b/fs/cifs/Makefile @@ -10,13 +10,14 @@ cifs-y := trace.o cifsfs.o cifssmb.o cifs_debug.o connect.o dir.o file.o \ cifs_unicode.o nterr.o cifsencrypt.o \ readdir.o ioctl.o sess.o export.o smb1ops.o unc.o winucase.o \ smb2ops.o smb2maperror.o smb2transport.o \ - smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o + smb2misc.o smb2pdu.o smb2inode.o smb2file.o cifsacl.o fs_context.o \ + dns_resolve.o cifs-$(CONFIG_CIFS_XATTR) += xattr.o cifs-$(CONFIG_CIFS_UPCALL) += cifs_spnego.o -cifs-$(CONFIG_CIFS_DFS_UPCALL) += dns_resolve.o cifs_dfs_ref.o dfs_cache.o +cifs-$(CONFIG_CIFS_DFS_UPCALL) += cifs_dfs_ref.o dfs_cache.o cifs-$(CONFIG_CIFS_SWN_UPCALL) += netlink.o cifs_swn.o diff --git a/fs/cifs/connect.c b/fs/cifs/connect.c index eec8a2052da2..24668eb006c6 100644 --- a/fs/cifs/connect.c +++ b/fs/cifs/connect.c @@ -87,7 +87,6 @@ static void cifs_prune_tlinks(struct work_struct *work); * * This should be called with server->srv_mutex held. */ -#ifdef CONFIG_CIFS_DFS_UPCALL static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) { int rc; @@ -124,6 +123,7 @@ static int reconn_set_ipaddr_from_hostname(struct TCP_Server_Info *server) return !rc ? -1 : 0; } +#ifdef CONFIG_CIFS_DFS_UPCALL /* These functions must be called with server->srv_mutex held */ static void reconn_set_next_dfs_target(struct TCP_Server_Info *server, struct cifs_sb_info *cifs_sb, @@ -321,13 +321,28 @@ cifs_reconnect(struct TCP_Server_Info *server) #endif #ifdef CONFIG_CIFS_DFS_UPCALL + if (cifs_sb && cifs_sb->origin_fullpath) /* * Set up next DFS target server (if any) for reconnect. If DFS * feature is disabled, then we will retry last server we * connected to before. */ reconn_set_next_dfs_target(server, cifs_sb, &tgt_list, &tgt_it); + else { #endif + /* + * Resolve the hostname again to make sure that IP address is up-to-date. + */ + rc = reconn_set_ipaddr_from_hostname(server); + if (rc) { + cifs_dbg(FYI, "%s: failed to resolve hostname: %d\n", + __func__, rc); + } + +#ifdef CONFIG_CIFS_DFS_UPCALL + } +#endif + #ifdef CONFIG_CIFS_SWN_UPCALL } From d135be0a7fb83f4dd68721b3355fec6de686834c Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Thu, 1 Apr 2021 15:51:17 +0800 Subject: [PATCH 0798/1091] fs: cifs: Remove unnecessary struct declaration struct cifs_readdata is declared twice. One is declared at 208th line. And struct cifs_readdata is defined blew. The declaration here is not needed. Remove the duplicate. Signed-off-by: Wan Jiabing Reviewed-by: Shyam Prasad N Signed-off-by: Steve French --- fs/cifs/cifsglob.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/fs/cifs/cifsglob.h b/fs/cifs/cifsglob.h index 67c056a9a519..ec824ab8c5ca 100644 --- a/fs/cifs/cifsglob.h +++ b/fs/cifs/cifsglob.h @@ -1283,8 +1283,6 @@ struct cifs_aio_ctx { bool direct_io; }; -struct cifs_readdata; - /* asynchronous read support */ struct cifs_readdata { struct kref refcount; From 0fc9322ab5e1fe6910c9673e1a7ff29f7dd72611 Mon Sep 17 00:00:00 2001 From: Maciek Borzecki Date: Tue, 6 Apr 2021 17:02:29 +0200 Subject: [PATCH 0799/1091] cifs: escape spaces in share names Commit 653a5efb849a ("cifs: update super_operations to show_devname") introduced the display of devname for cifs mounts. However, when mounting a share which has a whitespace in the name, that exact share name is also displayed in mountinfo. Make sure that all whitespace is escaped. Signed-off-by: Maciek Borzecki CC: # 5.11+ Reviewed-by: Shyam Prasad N Signed-off-by: Steve French --- fs/cifs/cifsfs.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/fs/cifs/cifsfs.c b/fs/cifs/cifsfs.c index 099ad9f3660b..5ddd20b62484 100644 --- a/fs/cifs/cifsfs.c +++ b/fs/cifs/cifsfs.c @@ -476,7 +476,8 @@ static int cifs_show_devname(struct seq_file *m, struct dentry *root) seq_puts(m, "none"); else { convert_delimiter(devname, '/'); - seq_puts(m, devname); + /* escape all spaces in share names */ + seq_escape(m, devname, " \t"); kfree(devname); } return 0; From 6ad7f2332e84c46f0c94e73e05b5b7c2bc1a6b74 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 8 Apr 2021 01:54:39 +0100 Subject: [PATCH 0800/1091] io_uring: clear F_REISSUE right after getting it There are lots of ways r/w request may continue its path after getting REQ_F_REISSUE, it's not necessarily io-wq and can be, e.g. apoll, and submitted via io_async_task_func() -> __io_req_task_submit() Clear the flag right after getting it, so the next attempt is well prepared regardless how the request will be executed. Fixes: 230d50d448ac ("io_uring: move reissue into regular IO path") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/11dcead939343f4e27cab0074d34afcab771bfa4.1617842918.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- fs/io_uring.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index 65a17d560a73..f1881ac0744b 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -3294,6 +3294,7 @@ static int io_read(struct io_kiocb *req, unsigned int issue_flags) ret = io_iter_do_read(req, iter); if (ret == -EAGAIN || (req->flags & REQ_F_REISSUE)) { + req->flags &= ~REQ_F_REISSUE; /* IOPOLL retry should happen for io-wq threads */ if (!force_nonblock && !(req->ctx->flags & IORING_SETUP_IOPOLL)) goto done; @@ -3417,8 +3418,10 @@ static int io_write(struct io_kiocb *req, unsigned int issue_flags) else ret2 = -EINVAL; - if (req->flags & REQ_F_REISSUE) + if (req->flags & REQ_F_REISSUE) { + req->flags &= ~REQ_F_REISSUE; ret2 = -EAGAIN; + } /* * Raw bdev writes will return -EOPNOTSUPP for IOCB_NOWAIT. Just @@ -6173,7 +6176,6 @@ static void io_wq_submit_work(struct io_wq_work *work) ret = -ECANCELED; if (!ret) { - req->flags &= ~REQ_F_REISSUE; do { ret = io_issue_sqe(req, 0); /* From 1b0b6e939f112949089e32ec89fd27796677263a Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Wed, 7 Apr 2021 19:29:39 +0800 Subject: [PATCH 0801/1091] drm/amdgpu: Fix size overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ttm->num_pages is uint32. Hit overflow when << PAGE_SHIFT directly Fixes: 230c079fdcf4 ("drm/ttm: make num_pages uint32_t") Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c index 9fd2157b133a..5efa331e3ee8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ttm.c @@ -906,7 +906,7 @@ static int amdgpu_ttm_tt_pin_userptr(struct ttm_bo_device *bdev, /* Allocate an SG array and squash pages into it */ r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0, - ttm->num_pages << PAGE_SHIFT, + (u64)ttm->num_pages << PAGE_SHIFT, GFP_KERNEL); if (r) goto release_sg; From 2efc021060c2aa55e1e8f7b98249d3ea63232fc7 Mon Sep 17 00:00:00 2001 From: xinhui pan Date: Wed, 7 Apr 2021 20:57:50 +0800 Subject: [PATCH 0802/1091] drm/radeon: Fix size overflow MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ttm->num_pages is uint32. Hit overflow when << PAGE_SHIFT directly Fixes: 230c079fdcf4 ("drm/ttm: make num_pages uint32_t") Signed-off-by: xinhui pan Reviewed-by: Christian König Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/radeon/radeon_ttm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/radeon/radeon_ttm.c b/drivers/gpu/drm/radeon/radeon_ttm.c index e8c66d10478f..78893bea85ae 100644 --- a/drivers/gpu/drm/radeon/radeon_ttm.c +++ b/drivers/gpu/drm/radeon/radeon_ttm.c @@ -364,7 +364,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_bo_device *bdev, struct ttm_tt * if (gtt->userflags & RADEON_GEM_USERPTR_ANONONLY) { /* check that we only pin down anonymous memory to prevent problems with writeback */ - unsigned long end = gtt->userptr + ttm->num_pages * PAGE_SIZE; + unsigned long end = gtt->userptr + (u64)ttm->num_pages * PAGE_SIZE; struct vm_area_struct *vma; vma = find_vma(gtt->usermm, gtt->userptr); if (!vma || vma->vm_file || vma->vm_end < end) @@ -386,7 +386,7 @@ static int radeon_ttm_tt_pin_userptr(struct ttm_bo_device *bdev, struct ttm_tt * } while (pinned < ttm->num_pages); r = sg_alloc_table_from_pages(ttm->sg, ttm->pages, ttm->num_pages, 0, - ttm->num_pages << PAGE_SHIFT, + (u64)ttm->num_pages << PAGE_SHIFT, GFP_KERNEL); if (r) goto release_sg; From cdcc108a2aced5f9cbc45920e29bf49819e5477f Mon Sep 17 00:00:00 2001 From: Alex Deucher Date: Wed, 7 Apr 2021 09:28:23 -0400 Subject: [PATCH 0803/1091] drm/amdgpu/smu7: fix CAC setting on TOPAZ We need to enable MC CAC for mclk switching to work. Fixes: d765129a719f ("drm/amd/pm: correct sclk/mclk dpm enablement") Bug: https://gitlab.freedesktop.org/drm/amd/-/issues/1561 Tested-by: Konstantin Kharlamov Reviewed-by: Evan Quan Signed-off-by: Alex Deucher Cc: stable@vger.kernel.org --- drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c index d0ec83881fc5..c0565a932a12 100644 --- a/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c +++ b/drivers/gpu/drm/amd/pm/powerplay/hwmgr/smu7_hwmgr.c @@ -1224,7 +1224,8 @@ static int smu7_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) (hwmgr->chip_id == CHIP_POLARIS10) || (hwmgr->chip_id == CHIP_POLARIS11) || (hwmgr->chip_id == CHIP_POLARIS12) || - (hwmgr->chip_id == CHIP_TONGA)) + (hwmgr->chip_id == CHIP_TONGA) || + (hwmgr->chip_id == CHIP_TOPAZ)) PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); From dd0b45538146cb6a54d6da7663b8c3afd16ebcfd Mon Sep 17 00:00:00 2001 From: Seevalamuthu Mariappan Date: Fri, 19 Mar 2021 19:48:52 +0530 Subject: [PATCH 0804/1091] mac80211: clear sta->fast_rx when STA removed from 4-addr VLAN In some race conditions, with more clients and traffic configuration, below crash is seen when making the interface down. sta->fast_rx wasn't cleared when STA gets removed from 4-addr AP_VLAN interface. The crash is due to try accessing 4-addr AP_VLAN interface's net_device (fast_rx->dev) which has been deleted already. Resolve this by clearing sta->fast_rx pointer when STA removes from a 4-addr VLAN. [ 239.449529] Unable to handle kernel NULL pointer dereference at virtual address 00000004 [ 239.449531] pgd = 80204000 ... [ 239.481496] CPU: 1 PID: 0 Comm: swapper/1 Not tainted 4.4.60 #227 [ 239.481591] Hardware name: Generic DT based system [ 239.487665] task: be05b700 ti: be08e000 task.ti: be08e000 [ 239.492360] PC is at get_rps_cpu+0x2d4/0x31c [ 239.497823] LR is at 0xbe08fc54 ... [ 239.778574] [<80739740>] (get_rps_cpu) from [<8073cb10>] (netif_receive_skb_internal+0x8c/0xac) [ 239.786722] [<8073cb10>] (netif_receive_skb_internal) from [<8073d578>] (napi_gro_receive+0x48/0xc4) [ 239.795267] [<8073d578>] (napi_gro_receive) from [] (ieee80211_mark_rx_ba_filtered_frames+0xbcc/0x12d4 [mac80211]) [ 239.804776] [] (ieee80211_mark_rx_ba_filtered_frames [mac80211]) from [] (ieee80211_rx_napi+0x7b8/0x8c8 [mac8 0211]) [ 239.815857] [] (ieee80211_rx_napi [mac80211]) from [] (ath11k_dp_process_rx+0x7bc/0x8c8 [ath11k]) [ 239.827757] [] (ath11k_dp_process_rx [ath11k]) from [] (ath11k_dp_service_srng+0x2c0/0x2e0 [ath11k]) [ 239.838484] [] (ath11k_dp_service_srng [ath11k]) from [<7f55b7dc>] (ath11k_ahb_ext_grp_napi_poll+0x20/0x84 [ath11k_ahb] ) [ 239.849419] [<7f55b7dc>] (ath11k_ahb_ext_grp_napi_poll [ath11k_ahb]) from [<8073ce1c>] (net_rx_action+0xe0/0x28c) [ 239.860945] [<8073ce1c>] (net_rx_action) from [<80324868>] (__do_softirq+0xe4/0x228) [ 239.871269] [<80324868>] (__do_softirq) from [<80324c48>] (irq_exit+0x98/0x108) [ 239.879080] [<80324c48>] (irq_exit) from [<8035c59c>] (__handle_domain_irq+0x90/0xb4) [ 239.886114] [<8035c59c>] (__handle_domain_irq) from [<8030137c>] (gic_handle_irq+0x50/0x94) [ 239.894100] [<8030137c>] (gic_handle_irq) from [<803024c0>] (__irq_svc+0x40/0x74) Signed-off-by: Seevalamuthu Mariappan Link: https://lore.kernel.org/r/1616163532-3881-1-git-send-email-seevalam@codeaurora.org Signed-off-by: Johannes Berg --- net/mac80211/cfg.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 68a0de02b561..860bc35383d5 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c @@ -1788,8 +1788,10 @@ static int ieee80211_change_station(struct wiphy *wiphy, } if (sta->sdata->vif.type == NL80211_IFTYPE_AP_VLAN && - sta->sdata->u.vlan.sta) + sta->sdata->u.vlan.sta) { + ieee80211_clear_fast_rx(sta); RCU_INIT_POINTER(sta->sdata->u.vlan.sta, NULL); + } if (test_sta_flag(sta, WLAN_STA_AUTHORIZED)) ieee80211_vif_dec_num_mcast(sta->sdata); From 71826654ce40112f0651b6f4e94c422354f4adb6 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 19 Mar 2021 23:25:11 +0100 Subject: [PATCH 0805/1091] rfkill: revert back to old userspace API by default Recompiling with the new extended version of struct rfkill_event broke systemd in *two* ways: - It used "sizeof(struct rfkill_event)" to read the event, but then complained if it actually got something != 8, this broke it on new kernels (that include the updated API); - It used sizeof(struct rfkill_event) to write a command, but didn't implement the intended expansion protocol where the kernel returns only how many bytes it accepted, and errored out due to the unexpected smaller size on kernels that didn't include the updated API. Even though systemd has now been fixed, that fix may not be always deployed, and other applications could potentially have similar issues. As such, in the interest of avoiding regressions, revert the default API "struct rfkill_event" back to the original size. Instead, add a new "struct rfkill_event_ext" that extends it by the new field, and even more clearly document that applications should be prepared for extensions in two ways: * write might only accept fewer bytes on older kernels, and will return how many to let userspace know which data may have been ignored; * read might return anything between 8 (the original size) and whatever size the application sized its buffer at, indicating how much event data was supported by the kernel. Perhaps that will help avoid such issues in the future and we won't have to come up with another version of the struct if we ever need to extend it again. Applications that want to take advantage of the new field will have to be modified to use struct rfkill_event_ext instead now, which comes with the danger of them having already been updated to use it from 'struct rfkill_event', but I found no evidence of that, and it's still relatively new. Cc: stable@vger.kernel.org # 5.11 Reported-by: Takashi Iwai Tested-by: Sedat Dilek # LLVM/Clang v12.0.0-r4 (x86-64) Link: https://lore.kernel.org/r/20210319232510.f1a139cfdd9c.Ic5c7c9d1d28972059e132ea653a21a427c326678@changeid Signed-off-by: Johannes Berg --- include/uapi/linux/rfkill.h | 82 +++++++++++++++++++++++++++++++------ net/rfkill/core.c | 7 ++-- 2 files changed, 73 insertions(+), 16 deletions(-) diff --git a/include/uapi/linux/rfkill.h b/include/uapi/linux/rfkill.h index 03e8af87b364..9b77cfc42efa 100644 --- a/include/uapi/linux/rfkill.h +++ b/include/uapi/linux/rfkill.h @@ -86,8 +86,6 @@ enum rfkill_hard_block_reasons { * @op: operation code * @hard: hard state (0/1) * @soft: soft state (0/1) - * @hard_block_reasons: valid if hard is set. One or several reasons from - * &enum rfkill_hard_block_reasons. * * Structure used for userspace communication on /dev/rfkill, * used for events from the kernel and control to the kernel. @@ -98,22 +96,80 @@ struct rfkill_event { __u8 op; __u8 soft; __u8 hard; +} __attribute__((packed)); + +/** + * struct rfkill_event_ext - events for userspace on /dev/rfkill + * @idx: index of dev rfkill + * @type: type of the rfkill struct + * @op: operation code + * @hard: hard state (0/1) + * @soft: soft state (0/1) + * @hard_block_reasons: valid if hard is set. One or several reasons from + * &enum rfkill_hard_block_reasons. + * + * Structure used for userspace communication on /dev/rfkill, + * used for events from the kernel and control to the kernel. + * + * See the extensibility docs below. + */ +struct rfkill_event_ext { + __u32 idx; + __u8 type; + __u8 op; + __u8 soft; + __u8 hard; + + /* + * older kernels will accept/send only up to this point, + * and if extended further up to any chunk marked below + */ + __u8 hard_block_reasons; } __attribute__((packed)); -/* - * We are planning to be backward and forward compatible with changes - * to the event struct, by adding new, optional, members at the end. - * When reading an event (whether the kernel from userspace or vice - * versa) we need to accept anything that's at least as large as the - * version 1 event size, but might be able to accept other sizes in - * the future. +/** + * DOC: Extensibility * - * One exception is the kernel -- we already have two event sizes in - * that we've made the 'hard' member optional since our only option - * is to ignore it anyway. + * Originally, we had planned to allow backward and forward compatible + * changes by just adding fields at the end of the structure that are + * then not reported on older kernels on read(), and not written to by + * older kernels on write(), with the kernel reporting the size it did + * accept as the result. + * + * This would have allowed userspace to detect on read() and write() + * which kernel structure version it was dealing with, and if was just + * recompiled it would have gotten the new fields, but obviously not + * accessed them, but things should've continued to work. + * + * Unfortunately, while actually exercising this mechanism to add the + * hard block reasons field, we found that userspace (notably systemd) + * did all kinds of fun things not in line with this scheme: + * + * 1. treat the (expected) short writes as an error; + * 2. ask to read sizeof(struct rfkill_event) but then compare the + * actual return value to RFKILL_EVENT_SIZE_V1 and treat any + * mismatch as an error. + * + * As a consequence, just recompiling with a new struct version caused + * things to no longer work correctly on old and new kernels. + * + * Hence, we've rolled back &struct rfkill_event to the original version + * and added &struct rfkill_event_ext. This effectively reverts to the + * old behaviour for all userspace, unless it explicitly opts in to the + * rules outlined here by using the new &struct rfkill_event_ext. + * + * Userspace using &struct rfkill_event_ext must adhere to the following + * rules + * + * 1. accept short writes, optionally using them to detect that it's + * running on an older kernel; + * 2. accept short reads, knowing that this means it's running on an + * older kernel; + * 3. treat reads that are as long as requested as acceptable, not + * checking against RFKILL_EVENT_SIZE_V1 or such. */ -#define RFKILL_EVENT_SIZE_V1 8 +#define RFKILL_EVENT_SIZE_V1 sizeof(struct rfkill_event) /* ioctl for turning off rfkill-input (if present) */ #define RFKILL_IOC_MAGIC 'R' diff --git a/net/rfkill/core.c b/net/rfkill/core.c index 68d6ef9e59fc..ac15a944573f 100644 --- a/net/rfkill/core.c +++ b/net/rfkill/core.c @@ -69,7 +69,7 @@ struct rfkill { struct rfkill_int_event { struct list_head list; - struct rfkill_event ev; + struct rfkill_event_ext ev; }; struct rfkill_data { @@ -253,7 +253,8 @@ static void rfkill_global_led_trigger_unregister(void) } #endif /* CONFIG_RFKILL_LEDS */ -static void rfkill_fill_event(struct rfkill_event *ev, struct rfkill *rfkill, +static void rfkill_fill_event(struct rfkill_event_ext *ev, + struct rfkill *rfkill, enum rfkill_operation op) { unsigned long flags; @@ -1237,7 +1238,7 @@ static ssize_t rfkill_fop_write(struct file *file, const char __user *buf, size_t count, loff_t *pos) { struct rfkill *rfkill; - struct rfkill_event ev; + struct rfkill_event_ext ev; int ret; /* we don't need the 'hard' variable but accept it */ From 1153a74768a9212daadbb50767aa400bc6a0c9b0 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Tue, 23 Mar 2021 21:05:01 +0100 Subject: [PATCH 0806/1091] mac80211: fix TXQ AC confusion MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Normally, TXQs have txq->tid = tid; txq->ac = ieee80211_ac_from_tid(tid); However, the special management TXQ actually has txq->tid = IEEE80211_NUM_TIDS; // 16 txq->ac = IEEE80211_AC_VO; This makes sense, but ieee80211_ac_from_tid(16) is the same as ieee80211_ac_from_tid(0) which is just IEEE80211_AC_BE. Now, normally this is fine. However, if the netdev queues were stopped, then the code in ieee80211_tx_dequeue() will propagate the stop from the interface (vif->txqs_stopped[]) if the AC 2 (ieee80211_ac_from_tid(txq->tid)) is marked as stopped. On wake, however, __ieee80211_wake_txqs() will wake the TXQ if AC 0 (txq->ac) is woken up. If a driver stops all queues with ieee80211_stop_tx_queues() and then wakes them again with ieee80211_wake_tx_queues(), the ieee80211_wake_txqs() tasklet will run to resync queue and TXQ state. If all queues were woken, then what'll happen is that _ieee80211_wake_txqs() will run in order of HW queues 0-3, typically (and certainly for iwlwifi) corresponding to ACs 0-3, so it'll call __ieee80211_wake_txqs() for each AC in order 0-3. When __ieee80211_wake_txqs() is called for AC 0 (VO) that'll wake up the management TXQ (remember its tid is 16), and the driver's wake_tx_queue() will be called. That tries to get a frame, which will immediately *stop* the TXQ again, because now we check against AC 2, and AC 2 hasn't yet been marked as woken up again in sdata->vif.txqs_stopped[] since we're only in the __ieee80211_wake_txqs() call for AC 0. Thus, the management TXQ will never be started again. Fix this by checking txq->ac directly instead of calculating the AC as ieee80211_ac_from_tid(txq->tid). Fixes: adf8ed01e4fd ("mac80211: add an optional TXQ for other PS-buffered frames") Acked-by: Toke Høiland-Jørgensen Link: https://lore.kernel.org/r/20210323210500.bf4d50afea4a.I136ffde910486301f8818f5442e3c9bf8670a9c4@changeid Signed-off-by: Johannes Berg --- net/mac80211/tx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index 5d06de61047a..3b3bcefbf657 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c @@ -3573,7 +3573,7 @@ begin: test_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags)) goto out; - if (vif->txqs_stopped[ieee80211_ac_from_tid(txq->tid)]) { + if (vif->txqs_stopped[txq->ac]) { set_bit(IEEE80211_TXQ_STOP_NETIF_TX, &txqi->flags); goto out; } From 7d73cd946d4bc7d44cdc5121b1c61d5d71425dea Mon Sep 17 00:00:00 2001 From: Ben Greear Date: Tue, 30 Mar 2021 16:07:49 -0700 Subject: [PATCH 0807/1091] mac80211: fix time-is-after bug in mlme The incorrect timeout check caused probing to happen when it did not need to happen. This in turn caused tx performance drop for around 5 seconds in ath10k-ct driver. Possibly that tx drop is due to a secondary issue, but fixing the probe to not happen when traffic is running fixes the symptom. Signed-off-by: Ben Greear Fixes: 9abf4e49830d ("mac80211: optimize station connection monitor") Acked-by: Felix Fietkau Link: https://lore.kernel.org/r/20210330230749.14097-1-greearb@candelatech.com Signed-off-by: Johannes Berg --- net/mac80211/mlme.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index ce4e3855fec1..96f487fc0071 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c @@ -4707,7 +4707,10 @@ static void ieee80211_sta_conn_mon_timer(struct timer_list *t) timeout = sta->rx_stats.last_rx; timeout += IEEE80211_CONNECTION_IDLE_TIME; - if (time_is_before_jiffies(timeout)) { + /* If timeout is after now, then update timer to fire at + * the later date, but do not actually probe at this time. + */ + if (time_is_after_jiffies(timeout)) { mod_timer(&ifmgd->conn_mon_timer, round_jiffies_up(timeout)); return; } From 1b5ab825d9acc0f27d2f25c6252f3526832a9626 Mon Sep 17 00:00:00 2001 From: Du Cheng Date: Thu, 8 Apr 2021 00:27:56 +0800 Subject: [PATCH 0808/1091] cfg80211: remove WARN_ON() in cfg80211_sme_connect A WARN_ON(wdev->conn) would trigger in cfg80211_sme_connect(), if multiple send_msg(NL80211_CMD_CONNECT) system calls are made from the userland, which should be anticipated and handled by the wireless driver. Remove this WARN_ON() to prevent kernel panic if kernel is configured to "panic_on_warn". Bug reported by syzbot. Reported-by: syzbot+5f9392825de654244975@syzkaller.appspotmail.com Signed-off-by: Du Cheng Link: https://lore.kernel.org/r/20210407162756.6101-1-ducheng2@gmail.com Signed-off-by: Johannes Berg --- net/wireless/sme.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/wireless/sme.c b/net/wireless/sme.c index 07756ca5e3b5..08a70b4f090c 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c @@ -529,7 +529,7 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev, cfg80211_sme_free(wdev); } - if (WARN_ON(wdev->conn)) + if (wdev->conn) return -EINPROGRESS; wdev->conn = kzalloc(sizeof(*wdev->conn), GFP_KERNEL); From b57aa17f07c9270e576ef7df09f142978b5a75f0 Mon Sep 17 00:00:00 2001 From: "A. Cody Schuffelen" Date: Thu, 18 Mar 2021 13:04:19 -0700 Subject: [PATCH 0809/1091] virt_wifi: Return micros for BSS TSF values cfg80211_inform_bss expects to receive a TSF value, but is given the time since boot in nanoseconds. TSF values are expected to be at microsecond scale rather than nanosecond scale. Signed-off-by: A. Cody Schuffelen Link: https://lore.kernel.org/r/20210318200419.1421034-1-schuffelen@google.com Signed-off-by: Johannes Berg --- drivers/net/wireless/virt_wifi.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/drivers/net/wireless/virt_wifi.c b/drivers/net/wireless/virt_wifi.c index c878097f0dda..1df959532c7d 100644 --- a/drivers/net/wireless/virt_wifi.c +++ b/drivers/net/wireless/virt_wifi.c @@ -12,6 +12,7 @@ #include #include #include +#include #include static struct wiphy *common_wiphy; @@ -168,11 +169,11 @@ static void virt_wifi_scan_result(struct work_struct *work) scan_result.work); struct wiphy *wiphy = priv_to_wiphy(priv); struct cfg80211_scan_info scan_info = { .aborted = false }; + u64 tsf = div_u64(ktime_get_boottime_ns(), 1000); informed_bss = cfg80211_inform_bss(wiphy, &channel_5ghz, CFG80211_BSS_FTYPE_PRESP, - fake_router_bssid, - ktime_get_boottime_ns(), + fake_router_bssid, tsf, WLAN_CAPABILITY_ESS, 0, (void *)&ssid, sizeof(ssid), DBM_TO_MBM(-50), GFP_KERNEL); From 315f02c60d9425b38eb8ad7f21b8a35e40db23f9 Mon Sep 17 00:00:00 2001 From: Paolo Bonzini Date: Tue, 6 Apr 2021 11:08:51 -0400 Subject: [PATCH 0810/1091] KVM: x86/mmu: preserve pending TLB flush across calls to kvm_tdp_mmu_zap_sp Right now, if a call to kvm_tdp_mmu_zap_sp returns false, the caller will skip the TLB flush, which is wrong. There are two ways to fix it: - since kvm_tdp_mmu_zap_sp will not yield and therefore will not flush the TLB itself, we could change the call to kvm_tdp_mmu_zap_sp to use "flush |= ..." - or we can chain the flush argument through kvm_tdp_mmu_zap_sp down to __kvm_tdp_mmu_zap_gfn_range. Note that kvm_tdp_mmu_zap_sp will neither yield nor flush, so flush would never go from true to false. This patch does the former to simplify application to stable kernels, and to make it further clearer that kvm_tdp_mmu_zap_sp will not flush. Cc: seanjc@google.com Fixes: 048f49809c526 ("KVM: x86/mmu: Ensure TLBs are flushed for TDP MMU during NX zapping") Cc: # 5.10.x: 048f49809c: KVM: x86/mmu: Ensure TLBs are flushed for TDP MMU during NX zapping Cc: # 5.10.x: 33a3164161: KVM: x86/mmu: Don't allow TDP MMU to yield when recovering NX pages Cc: Reviewed-by: Sean Christopherson Signed-off-by: Paolo Bonzini --- arch/x86/kvm/mmu/mmu.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/x86/kvm/mmu/mmu.c b/arch/x86/kvm/mmu/mmu.c index 486aa94ecf1d..951dae4e7175 100644 --- a/arch/x86/kvm/mmu/mmu.c +++ b/arch/x86/kvm/mmu/mmu.c @@ -5906,7 +5906,7 @@ static void kvm_recover_nx_lpages(struct kvm *kvm) lpage_disallowed_link); WARN_ON_ONCE(!sp->lpage_disallowed); if (is_tdp_mmu_page(sp)) { - flush = kvm_tdp_mmu_zap_sp(kvm, sp); + flush |= kvm_tdp_mmu_zap_sp(kvm, sp); } else { kvm_mmu_prepare_zap_page(kvm, sp, &invalid_list); WARN_ON_ONCE(sp->lpage_disallowed); From b5ac0146492fc5c199de767e492be8a66471011a Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 Apr 2021 14:28:27 +0200 Subject: [PATCH 0811/1091] cfg80211: check S1G beacon compat element length We need to check the length of this element so that we don't access data beyond its end. Fix that. Fixes: 9eaffe5078ca ("cfg80211: convert S1G beacon to scan results") Link: https://lore.kernel.org/r/20210408142826.f6f4525012de.I9fdeff0afdc683a6024e5ea49d2daa3cd2459d11@changeid Signed-off-by: Johannes Berg --- net/wireless/scan.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/net/wireless/scan.c b/net/wireless/scan.c index 019952d4fc7d..758eb7d2a706 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c @@ -2352,14 +2352,16 @@ cfg80211_inform_single_bss_frame_data(struct wiphy *wiphy, return NULL; if (ext) { - struct ieee80211_s1g_bcn_compat_ie *compat; - u8 *ie; + const struct ieee80211_s1g_bcn_compat_ie *compat; + const struct element *elem; - ie = (void *)cfg80211_find_ie(WLAN_EID_S1G_BCN_COMPAT, - variable, ielen); - if (!ie) + elem = cfg80211_find_elem(WLAN_EID_S1G_BCN_COMPAT, + variable, ielen); + if (!elem) return NULL; - compat = (void *)(ie + 2); + if (elem->datalen < sizeof(*compat)) + return NULL; + compat = (void *)elem->data; bssid = ext->u.s1g_beacon.sa; capability = le16_to_cpu(compat->compat_info); beacon_int = le16_to_cpu(compat->beacon_int); From abaf94ecc9c356d0b885a84edef4905cdd89cfdd Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 Apr 2021 14:28:34 +0200 Subject: [PATCH 0812/1091] nl80211: fix potential leak of ACL params In case nl80211_parse_unsol_bcast_probe_resp() results in an error, need to "goto out" instead of just returning to free possibly allocated data. Fixes: 7443dcd1f171 ("nl80211: Unsolicited broadcast probe response support") Link: https://lore.kernel.org/r/20210408142833.d8bc2e2e454a.If290b1ba85789726a671ff0b237726d4851b5b0f@changeid Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 034af85f79d8..0d34cca38702 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -5,7 +5,7 @@ * Copyright 2006-2010 Johannes Berg * Copyright 2013-2014 Intel Mobile Communications GmbH * Copyright 2015-2017 Intel Deutschland GmbH - * Copyright (C) 2018-2020 Intel Corporation + * Copyright (C) 2018-2021 Intel Corporation */ #include @@ -5485,7 +5485,7 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info) rdev, info->attrs[NL80211_ATTR_UNSOL_BCAST_PROBE_RESP], ¶ms); if (err) - return err; + goto out; } nl80211_calculate_ap_params(¶ms); From 35d65ab3fdba1bdecde9ac3424d6d634ea038729 Mon Sep 17 00:00:00 2001 From: Maxime Ripard Date: Thu, 18 Mar 2021 17:13:27 +0100 Subject: [PATCH 0813/1091] drm/vc4: plane: Remove redundant assignment The vc4_plane_atomic_async_update function assigns twice in a row the src_h field in the drm_plane_state structure to the same value. Remove the second one. Reviewed-by: Dave Stevenson Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20210318161328.1471556-2-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_plane.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/vc4/vc4_plane.c b/drivers/gpu/drm/vc4/vc4_plane.c index 7322169c0682..1e9c84cf614a 100644 --- a/drivers/gpu/drm/vc4/vc4_plane.c +++ b/drivers/gpu/drm/vc4/vc4_plane.c @@ -1146,7 +1146,6 @@ static void vc4_plane_atomic_async_update(struct drm_plane *plane, plane->state->src_y = state->src_y; plane->state->src_w = state->src_w; plane->state->src_h = state->src_h; - plane->state->src_h = state->src_h; plane->state->alpha = state->alpha; plane->state->pixel_blend_mode = state->pixel_blend_mode; plane->state->rotation = state->rotation; From eb9dfdd1ed40357b99a4201c8534c58c562e48c9 Mon Sep 17 00:00:00 2001 From: Dom Cobley Date: Thu, 18 Mar 2021 17:13:28 +0100 Subject: [PATCH 0814/1091] drm/vc4: crtc: Reduce PV fifo threshold on hvs4 Experimentally have found PV on hvs4 reports fifo full error with expected settings and does not with one less This appears as: [drm:drm_atomic_helper_wait_for_flip_done] *ERROR* [CRTC:82:crtc-3] flip_done timed out with bit 10 of PV_STAT set "HVS driving pixels when the PV FIFO is full" Fixes: c8b75bca92cb ("drm/vc4: Add KMS support for Raspberry Pi.") Signed-off-by: Dom Cobley Signed-off-by: Maxime Ripard Link: https://patchwork.freedesktop.org/patch/msgid/20210318161328.1471556-3-maxime@cerno.tech --- drivers/gpu/drm/vc4/vc4_crtc.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/drivers/gpu/drm/vc4/vc4_crtc.c b/drivers/gpu/drm/vc4/vc4_crtc.c index 269390bc586e..76657dcdf9b0 100644 --- a/drivers/gpu/drm/vc4/vc4_crtc.c +++ b/drivers/gpu/drm/vc4/vc4_crtc.c @@ -210,6 +210,7 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) { const struct vc4_crtc_data *crtc_data = vc4_crtc_to_vc4_crtc_data(vc4_crtc); const struct vc4_pv_data *pv_data = vc4_crtc_to_vc4_pv_data(vc4_crtc); + struct vc4_dev *vc4 = to_vc4_dev(vc4_crtc->base.dev); u32 fifo_len_bytes = pv_data->fifo_depth; /* @@ -238,6 +239,22 @@ static u32 vc4_get_fifo_full_level(struct vc4_crtc *vc4_crtc, u32 format) if (crtc_data->hvs_output == 5) return 32; + /* + * It looks like in some situations, we will overflow + * the PixelValve FIFO (with the bit 10 of PV stat being + * set) and stall the HVS / PV, eventually resulting in + * a page flip timeout. + * + * Displaying the video overlay during a playback with + * Kodi on an RPi3 seems to be a great solution with a + * failure rate around 50%. + * + * Removing 1 from the FIFO full level however + * seems to completely remove that issue. + */ + if (!vc4->hvs->hvs5) + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX - 1; + return fifo_len_bytes - 3 * HVS_FIFO_LATENCY_PIX; } } From 44de8d80dba4e65f4fe7c17ea4be75e3cf9a902c Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Thu, 8 Apr 2021 08:32:40 +0000 Subject: [PATCH 0815/1091] ASoC: rt1011: remove pack_id check in rt1011 For latest design, different package could use the same setting, therefore the check of pack_id will no longer be used. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/4cbe1cd3b8664140889132464c7dee7b@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1011.c | 16 ++-------------- sound/soc/codecs/rt1011.h | 1 - 2 files changed, 2 insertions(+), 15 deletions(-) diff --git a/sound/soc/codecs/rt1011.c b/sound/soc/codecs/rt1011.c index 098ecf13814d..bfe045367db3 100644 --- a/sound/soc/codecs/rt1011.c +++ b/sound/soc/codecs/rt1011.c @@ -2239,18 +2239,9 @@ static int rt1011_calibrate(struct rt1011_priv *rt1011, unsigned char cali_flag) dc_offset |= (value & 0xffff); dev_info(dev, "Gain1 offset=0x%x\n", dc_offset); - /* check the package info. */ - regmap_read(rt1011->regmap, RT1011_EFUSE_MATCH_DONE, &value); - if (value & 0x4) - rt1011->pack_id = 1; - if (cali_flag) { - if (rt1011->pack_id) - regmap_write(rt1011->regmap, RT1011_ADC_SET_1, 0x292c); - else - regmap_write(rt1011->regmap, RT1011_ADC_SET_1, 0x2925); - + regmap_write(rt1011->regmap, RT1011_ADC_SET_1, 0x2925); /* Class D on */ regmap_write(rt1011->regmap, RT1011_CLASS_D_POS, 0x010e); regmap_write(rt1011->regmap, @@ -2376,10 +2367,7 @@ static void rt1011_calibration_work(struct work_struct *work) rt1011_r0_load(rt1011); } - if (rt1011->pack_id) - snd_soc_component_write(component, RT1011_ADC_SET_1, 0x292c); - else - snd_soc_component_write(component, RT1011_ADC_SET_1, 0x2925); + snd_soc_component_write(component, RT1011_ADC_SET_1, 0x2925); } static int rt1011_parse_dp(struct rt1011_priv *rt1011, struct device *dev) diff --git a/sound/soc/codecs/rt1011.h b/sound/soc/codecs/rt1011.h index f3a9a96640f1..68fadc15fa8c 100644 --- a/sound/soc/codecs/rt1011.h +++ b/sound/soc/codecs/rt1011.h @@ -692,7 +692,6 @@ struct rt1011_priv { unsigned int r0_reg, cali_done; unsigned int r0_calib, temperature_calib; int recv_spk_mode; - unsigned int pack_id; /* 0: WLCSP; 1: QFN */ }; #endif /* end of _RT1011_H_ */ From 7b3f5b207da5116add56c335c5fb92cee140dc63 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Thu, 8 Apr 2021 14:40:34 +0800 Subject: [PATCH 0816/1091] ASoC: codecs: Fix runtime PM imbalance in tas2552_probe There is a rumtime PM imbalance between the error handling path after devm_snd_soc_register_component() and all other error handling paths. Add a PM runtime increment to balance refcount. Signed-off-by: Dinghao Liu Link: https://lore.kernel.org/r/20210408064036.6691-1-dinghao.liu@zju.edu.cn Signed-off-by: Mark Brown --- sound/soc/codecs/tas2552.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2552.c b/sound/soc/codecs/tas2552.c index bd00c35116cd..700baa6314aa 100644 --- a/sound/soc/codecs/tas2552.c +++ b/sound/soc/codecs/tas2552.c @@ -730,8 +730,10 @@ static int tas2552_probe(struct i2c_client *client, ret = devm_snd_soc_register_component(&client->dev, &soc_component_dev_tas2552, tas2552_dai, ARRAY_SIZE(tas2552_dai)); - if (ret < 0) + if (ret < 0) { dev_err(&client->dev, "Failed to register component: %d\n", ret); + pm_runtime_get_noresume(&client->dev); + } return ret; } From f2138aed231c88d5c4fa8d06aa15ad19685087c2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 1 Apr 2021 13:15:23 +0900 Subject: [PATCH 0817/1091] ASoC: simple-card-utils: enable flexible CPU/Codec/Platform Current simple-card / audio-graph are assuming fixed single-CPU/Codec/Platform. This patch prepares multi-CPU/Codec/Platform support. Note is that it is not yet full-multi-support. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v996od2c.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 8 +++ sound/soc/generic/audio-graph-card.c | 22 ++++++++ sound/soc/generic/simple-card-utils.c | 72 +++++++++++++++++++-------- sound/soc/generic/simple-card.c | 30 +++++++++++ 4 files changed, 110 insertions(+), 22 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 86e46cbf9e14..475f8cb14492 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -38,6 +38,12 @@ struct asoc_simple_jack { struct snd_soc_jack_gpio gpio; }; +struct prop_nums { + int cpus; + int codecs; + int platforms; +}; + struct asoc_simple_priv { struct snd_soc_card snd_card; struct simple_dai_props { @@ -48,6 +54,7 @@ struct asoc_simple_priv { struct snd_soc_dai_link_component *platforms; struct asoc_simple_data adata; struct snd_soc_codec_conf *codec_conf; + struct prop_nums num; unsigned int mclk_fs; } *dai_props; struct asoc_simple_jack hp_jack; @@ -71,6 +78,7 @@ struct link_info { int link; /* number of link */ int conf; /* number of codec_conf */ int cpu; /* turn for CPU / Codec */ + struct prop_nums num[SNDRV_MINOR_DEVICES]; }; int asoc_simple_parse_daifmt(struct device *dev, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 76036ea377a9..5fe53c5efcbf 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -628,6 +628,15 @@ static int graph_count_noml(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); + if (li->link >= SNDRV_MINOR_DEVICES) { + dev_err(dev, "too many links\n"); + return -EINVAL; + } + + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link += 1; /* 1xCPU-Codec */ li->dais += 2; /* 1xCPU + 1xCodec */ @@ -643,10 +652,23 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); + if (li->link >= SNDRV_MINOR_DEVICES) { + dev_err(dev, "too many links\n"); + return -EINVAL; + } + if (li->cpu) { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* 1xCPU-dummy */ li->dais++; /* 1xCPU */ } else { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* 1xdummy-Codec */ li->conf++; /* 1xdummy-Codec */ li->dais++; /* 1xCodec */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 3010ff63c71d..1606b9bc6b71 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -604,13 +604,27 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct asoc_simple_dai *dais; struct snd_soc_dai_link_component *dlcs; struct snd_soc_codec_conf *cconf = NULL; - int i; + int i, dai_num = 0, dlc_num = 0; dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL); dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL); - dais = devm_kcalloc(dev, li->dais, sizeof(*dais), GFP_KERNEL); - dlcs = devm_kcalloc(dev, li->link * 3, sizeof(*dai_props), GFP_KERNEL); - if (!dai_props || !dai_link || !dais || !dlcs) + if (!dai_props || !dai_link) + return -ENOMEM; + + /* + * dais (= CPU+Codec) + * dlcs (= CPU+Codec+Platform) + */ + for (i = 0; i < li->link; i++) { + int cc = li->num[i].cpus + li->num[i].codecs; + + dai_num += cc; + dlc_num += cc + li->num[i].platforms; + } + + dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); + dlcs = devm_kcalloc(dev, dlc_num, sizeof(*dai_props), GFP_KERNEL); + if (!dais || !dlcs) return -ENOMEM; if (li->conf) { @@ -619,24 +633,6 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, return -ENOMEM; } - /* - * "platform" might be removed - * see - * simple-card-utils.c :: asoc_simple_canonicalize_platform() - */ - for (i = 0; i < li->link; i++) { - dai_props[i].cpus = dlcs + (3 * i) + 0; - dai_props[i].codecs = dlcs + (3 * i) + 1; - dai_props[i].platforms = dlcs + (3 * i) + 2; - - dai_link[i].cpus = dai_props[i].cpus; - dai_link[i].num_cpus = 1; - dai_link[i].codecs = dai_props[i].codecs; - dai_link[i].num_codecs = 1; - dai_link[i].platforms = dai_props[i].platforms; - dai_link[i].num_platforms = 1; - } - priv->dai_props = dai_props; priv->dai_link = dai_link; priv->dais = dais; @@ -648,6 +644,38 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, card->codec_conf = cconf; card->num_configs = li->conf; + for (i = 0; i < li->link; i++) { + if (li->num[i].cpus) { + /* Normal CPU */ + dai_props[i].cpus = + dai_link[i].cpus = dlcs; + dai_props[i].num.cpus = + dai_link[i].num_cpus = li->num[i].cpus; + + dlcs += li->num[i].cpus; + } + + if (li->num[i].codecs) { + /* Normal Codec */ + dai_props[i].codecs = + dai_link[i].codecs = dlcs; + dai_props[i].num.codecs = + dai_link[i].num_codecs = li->num[i].codecs; + + dlcs += li->num[i].codecs; + } + + if (li->num[i].platforms) { + /* Have Platform */ + dai_props[i].platforms = + dai_link[i].platforms = dlcs; + dai_props[i].num.platforms = + dai_link[i].num_platforms = li->num[i].platforms; + + dlcs += li->num[i].platforms; + } + } + return 0; } EXPORT_SYMBOL_GPL(asoc_simple_init_priv); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9a05f44fc3a9..1fad570338b3 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -499,6 +499,17 @@ static int simple_count_noml(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { + if (li->link >= SNDRV_MINOR_DEVICES) { + struct device *dev = simple_priv_to_dev(priv); + + dev_err(dev, "too many links\n"); + return -EINVAL; + } + + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link += 1; li->dais += 2; @@ -510,10 +521,25 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { + if (li->link >= SNDRV_MINOR_DEVICES) { + struct device *dev = simple_priv_to_dev(priv); + + dev_err(dev, "too many links\n"); + return -EINVAL; + } + if (li->cpu) { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* CPU-dummy */ li->dais++; } else { + li->num[li->link].cpus = 1; + li->num[li->link].codecs = 1; + li->num[li->link].platforms = 1; + li->link++; /* dummy-Codec */ li->dais++; li->conf++; @@ -575,6 +601,10 @@ static void simple_get_dais_count(struct asoc_simple_priv *priv, * => 1 ccnf = 1xdummy-Codec */ if (!top) { + li->num[0].cpus = 1; + li->num[0].codecs = 1; + li->num[0].platforms = 1; + li->link = 1; li->dais = 2; li->conf = 0; From 205eb17eddb473c3159743c7d3aaf68db37b7231 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 1 Apr 2021 13:15:33 +0900 Subject: [PATCH 0818/1091] ASoC: simple-card-utils: share dummy DAI and reduce memory Current simple-card / audio-graph creates 1xCPU + 1xCodec + 1xPlatform for all dai_link, but some of them is not needed. For example Platform is not needed for DPCM BE case. Moreover, we can share snd-soc-dummy DAI for CPU-dummy / dummy-Codec in DPCM. This patch adds dummy DAI and share it when DPCM case, I beliave it can contribute to reduce memory. By this patch, CPU-dummy / dummy-CPU are set at asoc_simple_init_priv(), thus, its settings are no longer needed at DPCM detecting timing on simple-card / audio-graph. Moreover, we can remove triky Platform settings code for DPCM BE, because un-needed Platform is not created. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tuoqod22.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 1 + sound/soc/generic/audio-graph-card.c | 12 +---------- sound/soc/generic/simple-card-utils.c | 30 ++++++++++++++++++++------- sound/soc/generic/simple-card.c | 12 +---------- 4 files changed, 26 insertions(+), 29 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 475f8cb14492..6635283a8160 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -62,6 +62,7 @@ struct asoc_simple_priv { struct snd_soc_dai_link *dai_link; struct asoc_simple_dai *dais; struct snd_soc_dai_link_component *dlcs; + struct snd_soc_dai_link_component dummy; struct snd_soc_codec_conf *codec_conf; struct gpio_desc *pa_gpio; const struct snd_soc_ops *ops; diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 5fe53c5efcbf..7be2c2cb253e 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -240,9 +240,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, int is_single_links = 0; /* Codec is dummy */ - codecs->of_node = NULL; - codecs->dai_name = "snd-soc-dummy-dai"; - codecs->name = "snd-soc-dummy"; /* FE settings */ dai_link->dynamic = 1; @@ -281,13 +278,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, /* card->num_links includes Codec */ asoc_simple_canonicalize_cpu(dai_link, is_single_links); + asoc_simple_canonicalize_platform(dai_link); } else { struct snd_soc_codec_conf *cconf; /* CPU is dummy */ - cpus->of_node = NULL; - cpus->dai_name = "snd-soc-dummy-dai"; - cpus->name = "snd-soc-dummy"; /* BE settings */ dai_link->no_pcm = 1; @@ -328,8 +323,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, graph_parse_convert(dev, ep, &dai_props->adata); graph_parse_mclk_fs(top, ep, dai_props); - asoc_simple_canonicalize_platform(dai_link); - ret = asoc_simple_parse_tdm(ep, dai); if (ret) goto out_put_node; @@ -659,15 +652,12 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, if (li->cpu) { li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; li->link++; /* 1xCPU-dummy */ li->dais++; /* 1xCPU */ } else { - li->num[li->link].cpus = 1; li->num[li->link].codecs = 1; - li->num[li->link].platforms = 1; li->link++; /* 1xdummy-Codec */ li->conf++; /* 1xdummy-Codec */ diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 1606b9bc6b71..64b1ff5bafda 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -404,13 +404,6 @@ void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) /* Assumes platform == cpu */ if (!dai_link->platforms->of_node) dai_link->platforms->of_node = dai_link->cpus->of_node; - - /* - * DPCM BE can be no platform. - * Alloced memory will be waste, but not leak. - */ - if (!dai_link->platforms->of_node) - dai_link->num_platforms = 0; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); @@ -633,6 +626,11 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, return -ENOMEM; } + /* dummy CPU/Codec */ + priv->dummy.of_node = NULL; + priv->dummy.dai_name = "snd-soc-dummy-dai"; + priv->dummy.name = "snd-soc-dummy"; + priv->dai_props = dai_props; priv->dai_link = dai_link; priv->dais = dais; @@ -653,6 +651,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].num_cpus = li->num[i].cpus; dlcs += li->num[i].cpus; + } else { + /* DPCM Be's CPU = dummy */ + dai_props[i].cpus = + dai_link[i].cpus = &priv->dummy; + dai_props[i].num.cpus = + dai_link[i].num_cpus = 1; } if (li->num[i].codecs) { @@ -663,6 +667,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].num_codecs = li->num[i].codecs; dlcs += li->num[i].codecs; + } else { + /* DPCM Fe's Codec = dummy */ + dai_props[i].codecs = + dai_link[i].codecs = &priv->dummy; + dai_props[i].num.codecs = + dai_link[i].num_codecs = 1; } if (li->num[i].platforms) { @@ -673,6 +683,12 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].num_platforms = li->num[i].platforms; dlcs += li->num[i].platforms; + } else { + /* Doesn't have Platform */ + dai_props[i].platforms = + dai_link[i].platforms = NULL; + dai_props[i].num.platforms = + dai_link[i].num_platforms = 0; } } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 1fad570338b3..9132c0ea05af 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -141,9 +141,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, int is_single_links = 0; /* Codec is dummy */ - codecs->of_node = NULL; - codecs->dai_name = "snd-soc-dummy-dai"; - codecs->name = "snd-soc-dummy"; /* FE settings */ dai_link->dynamic = 1; @@ -167,13 +164,11 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, goto out_put_node; asoc_simple_canonicalize_cpu(dai_link, is_single_links); + asoc_simple_canonicalize_platform(dai_link); } else { struct snd_soc_codec_conf *cconf; /* CPU is dummy */ - cpus->of_node = NULL; - cpus->dai_name = "snd-soc-dummy-dai"; - cpus->name = "snd-soc-dummy"; /* BE settings */ dai_link->no_pcm = 1; @@ -211,8 +206,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, simple_parse_convert(dev, np, &dai_props->adata); simple_parse_mclk_fs(top, np, codec, dai_props, prefix); - asoc_simple_canonicalize_platform(dai_link); - ret = asoc_simple_parse_tdm(np, dai); if (ret) goto out_put_node; @@ -530,15 +523,12 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, if (li->cpu) { li->num[li->link].cpus = 1; - li->num[li->link].codecs = 1; li->num[li->link].platforms = 1; li->link++; /* CPU-dummy */ li->dais++; } else { - li->num[li->link].cpus = 1; li->num[li->link].codecs = 1; - li->num[li->link].platforms = 1; li->link++; /* dummy-Codec */ li->dais++; From f985838003ee618daba7a38da3efe27c639575e2 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:27:00 +0800 Subject: [PATCH 0819/1091] ASoC: codecs: wsa881x: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062700.803792-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wsa881x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wsa881x.c b/sound/soc/codecs/wsa881x.c index db87e07b11c9..2da4a5fa7a18 100644 --- a/sound/soc/codecs/wsa881x.c +++ b/sound/soc/codecs/wsa881x.c @@ -1014,7 +1014,7 @@ static int wsa881x_digital_mute(struct snd_soc_dai *dai, int mute, int stream) return 0; } -static struct snd_soc_dai_ops wsa881x_dai_ops = { +static const struct snd_soc_dai_ops wsa881x_dai_ops = { .hw_params = wsa881x_hw_params, .hw_free = wsa881x_hw_free, .mute_stream = wsa881x_digital_mute, From a0bc855ffdb55cbb9fbf7fa9611d17f19db889a8 Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Thu, 8 Apr 2021 15:59:08 +0200 Subject: [PATCH 0820/1091] ASoC: codecs: tlv320aic3x: add AIC3106 In DT binding is mentioned that this driver is compatible with 3106. So added compatibility string and model number. Signed-off-by: Jiri Prchal Link: https://lore.kernel.org/r/20210408135908.125667-1-jiri.prchal@aksignal.cz Signed-off-by: Mark Brown --- sound/soc/codecs/tlv320aic3x-i2c.c | 2 ++ sound/soc/codecs/tlv320aic3x-spi.c | 2 ++ sound/soc/codecs/tlv320aic3x.c | 3 +++ sound/soc/codecs/tlv320aic3x.h | 1 + 4 files changed, 8 insertions(+) diff --git a/sound/soc/codecs/tlv320aic3x-i2c.c b/sound/soc/codecs/tlv320aic3x-i2c.c index 4535bb8dbadc..cd0558ed4dd4 100644 --- a/sound/soc/codecs/tlv320aic3x-i2c.c +++ b/sound/soc/codecs/tlv320aic3x-i2c.c @@ -40,6 +40,7 @@ static const struct i2c_device_id aic3x_i2c_id[] = { { "tlv320aic33", AIC3X_MODEL_33 }, { "tlv320aic3007", AIC3X_MODEL_3007 }, { "tlv320aic3104", AIC3X_MODEL_3104 }, + { "tlv320aic3106", AIC3X_MODEL_3106 }, { } }; MODULE_DEVICE_TABLE(i2c, aic3x_i2c_id); @@ -49,6 +50,7 @@ static const struct of_device_id aic3x_of_id[] = { { .compatible = "ti,tlv320aic33" }, { .compatible = "ti,tlv320aic3007" }, { .compatible = "ti,tlv320aic3104" }, + { .compatible = "ti,tlv320aic3106" }, {}, }; MODULE_DEVICE_TABLE(of, aic3x_of_id); diff --git a/sound/soc/codecs/tlv320aic3x-spi.c b/sound/soc/codecs/tlv320aic3x-spi.c index bd78ab0910da..8c7b6bb9223f 100644 --- a/sound/soc/codecs/tlv320aic3x-spi.c +++ b/sound/soc/codecs/tlv320aic3x-spi.c @@ -45,6 +45,7 @@ static const struct spi_device_id aic3x_spi_id[] = { { "tlv320aic33", AIC3X_MODEL_33 }, { "tlv320aic3007", AIC3X_MODEL_3007 }, { "tlv320aic3104", AIC3X_MODEL_3104 }, + { "tlv320aic3106", AIC3X_MODEL_3106 }, { } }; MODULE_DEVICE_TABLE(spi, aic3x_spi_id); @@ -54,6 +55,7 @@ static const struct of_device_id aic3x_of_id[] = { { .compatible = "ti,tlv320aic33" }, { .compatible = "ti,tlv320aic3007" }, { .compatible = "ti,tlv320aic3104" }, + { .compatible = "ti,tlv320aic3106" }, {}, }; MODULE_DEVICE_TABLE(of, aic3x_of_id); diff --git a/sound/soc/codecs/tlv320aic3x.c b/sound/soc/codecs/tlv320aic3x.c index 2f351747b714..7731593a5509 100644 --- a/sound/soc/codecs/tlv320aic3x.c +++ b/sound/soc/codecs/tlv320aic3x.c @@ -1003,6 +1003,7 @@ static int aic3x_add_widgets(struct snd_soc_component *component) switch (aic3x->model) { case AIC3X_MODEL_3X: case AIC3X_MODEL_33: + case AIC3X_MODEL_3106: snd_soc_dapm_new_controls(dapm, aic3x_extra_dapm_widgets, ARRAY_SIZE(aic3x_extra_dapm_widgets)); snd_soc_dapm_add_routes(dapm, intercon_extra, @@ -1580,6 +1581,7 @@ static int aic3x_init(struct snd_soc_component *component) switch (aic3x->model) { case AIC3X_MODEL_3X: case AIC3X_MODEL_33: + case AIC3X_MODEL_3106: aic3x_mono_init(component); break; case AIC3X_MODEL_3007: @@ -1646,6 +1648,7 @@ static int aic3x_component_probe(struct snd_soc_component *component) switch (aic3x->model) { case AIC3X_MODEL_3X: case AIC3X_MODEL_33: + case AIC3X_MODEL_3106: snd_soc_add_component_controls(component, aic3x_extra_snd_controls, ARRAY_SIZE(aic3x_extra_snd_controls)); snd_soc_add_component_controls(component, aic3x_mono_controls, diff --git a/sound/soc/codecs/tlv320aic3x.h b/sound/soc/codecs/tlv320aic3x.h index 00908f1734a7..7e0063913017 100644 --- a/sound/soc/codecs/tlv320aic3x.h +++ b/sound/soc/codecs/tlv320aic3x.h @@ -20,6 +20,7 @@ int aic3x_remove(struct device *dev); #define AIC3X_MODEL_33 1 #define AIC3X_MODEL_3007 2 #define AIC3X_MODEL_3104 3 +#define AIC3X_MODEL_3106 4 /* AIC3X register space */ #define AIC3X_CACHEREGNUM 110 From b186e7c17d9f2c2bc9cd0bd362402eddbea7749b Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:43 +0800 Subject: [PATCH 0821/1091] ASoC: tas2764: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062643.802908-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2764.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2764.c b/sound/soc/codecs/tas2764.c index 8ff4d9e8d568..9265af41c235 100644 --- a/sound/soc/codecs/tas2764.c +++ b/sound/soc/codecs/tas2764.c @@ -457,7 +457,7 @@ static int tas2764_set_dai_tdm_slot(struct snd_soc_dai *dai, return 0; } -static struct snd_soc_dai_ops tas2764_dai_ops = { +static const struct snd_soc_dai_ops tas2764_dai_ops = { .mute_stream = tas2764_mute, .hw_params = tas2764_hw_params, .set_fmt = tas2764_set_fmt, From 38ec3006eccb46a6db6f4a36536f78db8e9042ac Mon Sep 17 00:00:00 2001 From: Jiri Prchal Date: Thu, 8 Apr 2021 08:07:41 +0200 Subject: [PATCH 0822/1091] ASoC: codecs: tlv320aic3x: add SPI to the DT binding Added note and example of SPI support. Signed-off-by: Jiri Prchal Link: https://lore.kernel.org/r/20210408060741.6879-1-jiri.prchal@aksignal.cz Signed-off-by: Mark Brown --- .../devicetree/bindings/sound/tlv320aic3x.txt | 21 +++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt index 9796c4639262..20931a63fd64 100644 --- a/Documentation/devicetree/bindings/sound/tlv320aic3x.txt +++ b/Documentation/devicetree/bindings/sound/tlv320aic3x.txt @@ -1,6 +1,6 @@ Texas Instruments - tlv320aic3x Codec module -The tlv320aic3x serial control bus communicates through I2C protocols +The tlv320aic3x serial control bus communicates through both I2C and SPI bus protocols Required properties: @@ -63,7 +63,7 @@ CODEC input pins for other compatible codecs: The pins can be used in referring sound node's audio-routing property. -Example: +I2C example: #include @@ -78,3 +78,20 @@ tlv320aic3x: tlv320aic3x@1b { DRVDD-supply = <®ulator>; DVDD-supply = <®ulator>; }; + +SPI example: + +spi0: spi@f0000000 { + tlv320aic3x: codec@0 { + compatible = "ti,tlv320aic3x"; + reg = <0>; /* CS number */ + #sound-dai-cells = <0>; + spi-max-frequency = <1000000>; + + AVDD-supply = <®ulator>; + IOVDD-supply = <®ulator>; + DRVDD-supply = <®ulator>; + DVDD-supply = <®ulator>; + ai3x-ocmv = <0>; + }; +}; From a93799d55fd479f540ed97066e69114aa7709787 Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Wed, 7 Apr 2021 14:56:34 +0500 Subject: [PATCH 0823/1091] ASoC: fsl: sunxi: remove redundant dev_err call devm_ioremap_resource() prints error message in itself. Remove the dev_err call to avoid redundant error message. Signed-off-by: Muhammad Usama Anjum Link: https://lore.kernel.org/r/20210407095634.GA1379642@LEGION Signed-off-by: Mark Brown --- sound/soc/fsl/fsl_aud2htx.c | 4 +--- sound/soc/fsl/fsl_easrc.c | 4 +--- sound/soc/sunxi/sun4i-codec.c | 4 +--- 3 files changed, 3 insertions(+), 9 deletions(-) diff --git a/sound/soc/fsl/fsl_aud2htx.c b/sound/soc/fsl/fsl_aud2htx.c index d70d5e75a30c..a328697511f7 100644 --- a/sound/soc/fsl/fsl_aud2htx.c +++ b/sound/soc/fsl/fsl_aud2htx.c @@ -198,10 +198,8 @@ static int fsl_aud2htx_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(regs)) { - dev_err(&pdev->dev, "failed ioremap\n"); + if (IS_ERR(regs)) return PTR_ERR(regs); - } aud2htx->regmap = devm_regmap_init_mmio(&pdev->dev, regs, &fsl_aud2htx_regmap_config); diff --git a/sound/soc/fsl/fsl_easrc.c b/sound/soc/fsl/fsl_easrc.c index 5e33afe87c4a..b1765c7d3bcd 100644 --- a/sound/soc/fsl/fsl_easrc.c +++ b/sound/soc/fsl/fsl_easrc.c @@ -1889,10 +1889,8 @@ static int fsl_easrc_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); regs = devm_ioremap_resource(dev, res); - if (IS_ERR(regs)) { - dev_err(&pdev->dev, "failed ioremap\n"); + if (IS_ERR(regs)) return PTR_ERR(regs); - } easrc->paddr = res->start; diff --git a/sound/soc/sunxi/sun4i-codec.c b/sound/soc/sunxi/sun4i-codec.c index 6c13cc84b3fb..00b73b7444b7 100644 --- a/sound/soc/sunxi/sun4i-codec.c +++ b/sound/soc/sunxi/sun4i-codec.c @@ -1706,10 +1706,8 @@ static int sun4i_codec_probe(struct platform_device *pdev) res = platform_get_resource(pdev, IORESOURCE_MEM, 0); base = devm_ioremap_resource(&pdev->dev, res); - if (IS_ERR(base)) { - dev_err(&pdev->dev, "Failed to map the registers\n"); + if (IS_ERR(base)) return PTR_ERR(base); - } quirks = of_device_get_match_data(&pdev->dev); if (quirks == NULL) { From 5e71e9c14db4e49cca56354c95ce10e0e00214d1 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:27:01 +0800 Subject: [PATCH 0824/1091] ASoC: rt1019: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062701.803865-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1019.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index 5138f028d9f2..f64bb7302720 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -823,7 +823,7 @@ static int rt1019_probe(struct snd_soc_component *component) #define RT1019_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -static struct snd_soc_dai_ops rt1019_aif_dai_ops = { +static const struct snd_soc_dai_ops rt1019_aif_dai_ops = { .hw_params = rt1019_hw_params, .set_fmt = rt1019_set_dai_fmt, .set_sysclk = rt1019_set_dai_sysclk, From e9a216d8f14ac4d926078885e7e772db08e6aad9 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:56 +0800 Subject: [PATCH 0825/1091] ASoC: cx2072x: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062656.803606-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/cx2072x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cx2072x.c b/sound/soc/codecs/cx2072x.c index d924e3528029..1f5c57fab1d8 100644 --- a/sound/soc/codecs/cx2072x.c +++ b/sound/soc/codecs/cx2072x.c @@ -1532,7 +1532,7 @@ static const struct snd_soc_component_driver soc_codec_driver_cx2072x = { /* * DAI ops */ -static struct snd_soc_dai_ops cx2072x_dai_ops = { +static const struct snd_soc_dai_ops cx2072x_dai_ops = { .set_sysclk = cx2072x_set_dai_sysclk, .set_fmt = cx2072x_set_dai_fmt, .hw_params = cx2072x_hw_params, From f2ec1ebb257155fb534cad390575d696dfd567fb Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:46 +0800 Subject: [PATCH 0826/1091] ASoC: tas2770: Constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062646.803053-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/tas2770.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/tas2770.c b/sound/soc/codecs/tas2770.c index 781bf9cc4faa..172e79cbe0da 100644 --- a/sound/soc/codecs/tas2770.c +++ b/sound/soc/codecs/tas2770.c @@ -464,7 +464,7 @@ static int tas2770_set_dai_tdm_slot(struct snd_soc_dai *dai, return 0; } -static struct snd_soc_dai_ops tas2770_dai_ops = { +static const struct snd_soc_dai_ops tas2770_dai_ops = { .mute_stream = tas2770_mute, .hw_params = tas2770_hw_params, .set_fmt = tas2770_set_fmt, From e4d4d456436bfb2fe412ee2cd489f7658449b098 Mon Sep 17 00:00:00 2001 From: Piotr Krysiuk Date: Mon, 5 Apr 2021 22:52:15 +0100 Subject: [PATCH 0827/1091] bpf, x86: Validate computation of branch displacements for x86-64 The branch displacement logic in the BPF JIT compilers for x86 assumes that, for any generated branch instruction, the distance cannot increase between optimization passes. But this assumption can be violated due to how the distances are computed. Specifically, whenever a backward branch is processed in do_jit(), the distance is computed by subtracting the positions in the machine code from different optimization passes. This is because part of addrs[] is already updated for the current optimization pass, before the branch instruction is visited. And so the optimizer can expand blocks of machine code in some cases. This can confuse the optimizer logic, where it assumes that a fixed point has been reached for all machine code blocks once the total program size stops changing. And then the JIT compiler can output abnormal machine code containing incorrect branch displacements. To mitigate this issue, we assert that a fixed point is reached while populating the output image. This rejects any problematic programs. The issue affects both x86-32 and x86-64. We mitigate separately to ease backporting. Signed-off-by: Piotr Krysiuk Reviewed-by: Daniel Borkmann Signed-off-by: Daniel Borkmann --- arch/x86/net/bpf_jit_comp.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index b35fc8023884..7f1b3a862e14 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1689,7 +1689,16 @@ emit_jmp: } if (image) { - if (unlikely(proglen + ilen > oldproglen)) { + /* + * When populating the image, assert that: + * + * i) We do not write beyond the allocated space, and + * ii) addrs[i] did not change from the prior run, in order + * to validate assumptions made for computing branch + * displacements. + */ + if (unlikely(proglen + ilen > oldproglen || + proglen + ilen != addrs[i])) { pr_err("bpf_jit: fatal error\n"); return -EFAULT; } From 26f55a59dc65ff77cd1c4b37991e26497fc68049 Mon Sep 17 00:00:00 2001 From: Piotr Krysiuk Date: Tue, 6 Apr 2021 21:59:39 +0100 Subject: [PATCH 0828/1091] bpf, x86: Validate computation of branch displacements for x86-32 The branch displacement logic in the BPF JIT compilers for x86 assumes that, for any generated branch instruction, the distance cannot increase between optimization passes. But this assumption can be violated due to how the distances are computed. Specifically, whenever a backward branch is processed in do_jit(), the distance is computed by subtracting the positions in the machine code from different optimization passes. This is because part of addrs[] is already updated for the current optimization pass, before the branch instruction is visited. And so the optimizer can expand blocks of machine code in some cases. This can confuse the optimizer logic, where it assumes that a fixed point has been reached for all machine code blocks once the total program size stops changing. And then the JIT compiler can output abnormal machine code containing incorrect branch displacements. To mitigate this issue, we assert that a fixed point is reached while populating the output image. This rejects any problematic programs. The issue affects both x86-32 and x86-64. We mitigate separately to ease backporting. Signed-off-by: Piotr Krysiuk Reviewed-by: Daniel Borkmann Signed-off-by: Daniel Borkmann --- arch/x86/net/bpf_jit_comp32.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/x86/net/bpf_jit_comp32.c b/arch/x86/net/bpf_jit_comp32.c index d17b67c69f89..6a99def7d315 100644 --- a/arch/x86/net/bpf_jit_comp32.c +++ b/arch/x86/net/bpf_jit_comp32.c @@ -2276,7 +2276,16 @@ notyet: } if (image) { - if (unlikely(proglen + ilen > oldproglen)) { + /* + * When populating the image, assert that: + * + * i) We do not write beyond the allocated space, and + * ii) addrs[i] did not change from the prior run, in order + * to validate assumptions made for computing branch + * displacements. + */ + if (unlikely(proglen + ilen > oldproglen || + proglen + ilen != addrs[i])) { pr_err("bpf_jit: fatal error\n"); return -EFAULT; } From 9a6847ba1747858ccac53c5aba3e25c54fbdf846 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Thu, 8 Apr 2021 15:45:20 +0200 Subject: [PATCH 0829/1091] nl80211: fix beacon head validation If the beacon head attribute (NL80211_ATTR_BEACON_HEAD) is too short to even contain the frame control field, we access uninitialized data beyond the buffer. Fix this by checking the minimal required size first. We used to do this until S1G support was added, where the fixed data portion has a different size. Reported-and-tested-by: syzbot+72b99dcf4607e8c770f3@syzkaller.appspotmail.com Suggested-by: Eric Dumazet Fixes: 1d47f1198d58 ("nl80211: correctly validate S1G beacon head") Signed-off-by: Johannes Berg Link: https://lore.kernel.org/r/20210408154518.d9b06d39b4ee.Iff908997b2a4067e8d456b3cb96cab9771d252b8@changeid Signed-off-by: Johannes Berg --- net/wireless/nl80211.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 0d34cca38702..b1df42e4f1eb 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -229,9 +229,13 @@ static int validate_beacon_head(const struct nlattr *attr, unsigned int len = nla_len(attr); const struct element *elem; const struct ieee80211_mgmt *mgmt = (void *)data; - bool s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control); unsigned int fixedlen, hdrlen; + bool s1g_bcn; + if (len < offsetofend(typeof(*mgmt), frame_control)) + goto err; + + s1g_bcn = ieee80211_is_s1g_beacon(mgmt->frame_control); if (s1g_bcn) { fixedlen = offsetof(struct ieee80211_ext, u.s1g_beacon.variable); From b2d0efc4be7ed320e33eaa9b6dd6f3f6011ffb8e Mon Sep 17 00:00:00 2001 From: Grzegorz Siwik Date: Wed, 24 Mar 2021 09:58:27 +0100 Subject: [PATCH 0830/1091] i40e: Fix parameters in aq_get_phy_register() Change parameters order in aq_get_phy_register() due to wrong statistics in PHY reported by ethtool. Previously all PHY statistics were exactly the same for all interfaces Now statistics are reported correctly - different for different interfaces Fixes: 0514db37dd78 ("i40e: Extend PHY access with page change flag") Signed-off-by: Grzegorz Siwik Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_ethtool.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c index 96d5202a73e8..0e92668012e3 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_ethtool.c +++ b/drivers/net/ethernet/intel/i40e/i40e_ethtool.c @@ -5480,7 +5480,7 @@ static int i40e_get_module_eeprom(struct net_device *netdev, status = i40e_aq_get_phy_register(hw, I40E_AQ_PHY_REG_ACCESS_EXTERNAL_MODULE, - true, addr, offset, &value, NULL); + addr, true, offset, &value, NULL); if (status) return -EIO; data[i] = value; From 12738ac4754ec92a6a45bf3677d8da780a1412b3 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Fri, 26 Mar 2021 19:43:40 +0100 Subject: [PATCH 0831/1091] i40e: Fix sparse errors in i40e_txrx.c Remove error handling through pointers. Instead use plain int to return value from i40e_run_xdp(...). Previously: - sparse errors were produced during compilation: i40e_txrx.c:2338 i40e_run_xdp() error: (-2147483647) too low for ERR_PTR i40e_txrx.c:2558 i40e_clean_rx_irq() error: 'skb' dereferencing possible ERR_PTR() - sk_buff* was used to return value, but it has never had valid pointer to sk_buff. Returned value was always int handled as a pointer. Fixes: 0c8493d90b6b ("i40e: add XDP support for pass and drop actions") Fixes: 2e6893123830 ("i40e: split XDP_TX tail and XDP_REDIRECT map flushing") Signed-off-by: Aleksandr Loktionov Signed-off-by: Arkadiusz Kubalewski Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_txrx.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_txrx.c b/drivers/net/ethernet/intel/i40e/i40e_txrx.c index 5747a99122fb..06b4271219b1 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_txrx.c +++ b/drivers/net/ethernet/intel/i40e/i40e_txrx.c @@ -2295,8 +2295,7 @@ int i40e_xmit_xdp_tx_ring(struct xdp_buff *xdp, struct i40e_ring *xdp_ring) * @rx_ring: Rx ring being processed * @xdp: XDP buffer containing the frame **/ -static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring, - struct xdp_buff *xdp) +static int i40e_run_xdp(struct i40e_ring *rx_ring, struct xdp_buff *xdp) { int err, result = I40E_XDP_PASS; struct i40e_ring *xdp_ring; @@ -2335,7 +2334,7 @@ static struct sk_buff *i40e_run_xdp(struct i40e_ring *rx_ring, } xdp_out: rcu_read_unlock(); - return ERR_PTR(-result); + return result; } /** @@ -2448,6 +2447,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) unsigned int xdp_xmit = 0; bool failure = false; struct xdp_buff xdp; + int xdp_res = 0; #if (PAGE_SIZE < 8192) frame_sz = i40e_rx_frame_truesize(rx_ring, 0); @@ -2513,12 +2513,10 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget) /* At larger PAGE_SIZE, frame_sz depend on len size */ xdp.frame_sz = i40e_rx_frame_truesize(rx_ring, size); #endif - skb = i40e_run_xdp(rx_ring, &xdp); + xdp_res = i40e_run_xdp(rx_ring, &xdp); } - if (IS_ERR(skb)) { - unsigned int xdp_res = -PTR_ERR(skb); - + if (xdp_res) { if (xdp_res & (I40E_XDP_TX | I40E_XDP_REDIR)) { xdp_xmit |= xdp_res; i40e_rx_buffer_flip(rx_ring, rx_buffer, size); From d6d04ee6d2c9bb5084c8f6074195d6aa0024e825 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Fri, 26 Mar 2021 19:43:41 +0100 Subject: [PATCH 0832/1091] i40e: Fix sparse error: uninitialized symbol 'ring' Init pointer with NULL in default switch case statement. Previously the error was produced when compiling against sparse. i40e_debugfs.c:582 i40e_dbg_dump_desc() error: uninitialized symbol 'ring'. Fixes: 44ea803e2fa7 ("i40e: introduce new dump desc XDP command") Signed-off-by: Aleksandr Loktionov Signed-off-by: Arkadiusz Kubalewski Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_debugfs.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c index d7c13ca9be7d..d627b59ad446 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_debugfs.c +++ b/drivers/net/ethernet/intel/i40e/i40e_debugfs.c @@ -578,6 +578,9 @@ static void i40e_dbg_dump_desc(int cnt, int vsi_seid, int ring_id, int desc_n, case RING_TYPE_XDP: ring = kmemdup(vsi->xdp_rings[ring_id], sizeof(*ring), GFP_KERNEL); break; + default: + ring = NULL; + break; } if (!ring) return; From 6b5674fe6b9bf05394886ebcec62b2d7dae88c42 Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Fri, 26 Mar 2021 19:43:42 +0100 Subject: [PATCH 0833/1091] i40e: Fix sparse error: 'vsi->netdev' could be null Remove vsi->netdev->name from the trace. This is redundant information. With the devinfo trace, the adapter is already identifiable. Previously following error was produced when compiling against sparse. i40e_main.c:2571 i40e_sync_vsi_filters() error: we previously assumed 'vsi->netdev' could be null (see line 2323) Fixes: b603f9dc20af ("i40e: Log info when PF is entering and leaving Allmulti mode.") Signed-off-by: Aleksandr Loktionov Signed-off-by: Arkadiusz Kubalewski Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_main.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index af6c25fa493c..c0a4bc2caae9 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -2560,8 +2560,7 @@ int i40e_sync_vsi_filters(struct i40e_vsi *vsi) i40e_stat_str(hw, aq_ret), i40e_aq_str(hw, hw->aq.asq_last_status)); } else { - dev_info(&pf->pdev->dev, "%s is %s allmulti mode.\n", - vsi->netdev->name, + dev_info(&pf->pdev->dev, "%s allmulti mode.\n", cur_multipromisc ? "entering" : "leaving"); } } From 8a1e918d833ca5c391c4ded5dc006e2d1ce6d37c Mon Sep 17 00:00:00 2001 From: Arkadiusz Kubalewski Date: Fri, 26 Mar 2021 19:43:43 +0100 Subject: [PATCH 0834/1091] i40e: Fix sparse warning: missing error code 'err' Set proper return values inside error checking if-statements. Previously following warning was produced when compiling against sparse. i40e_main.c:15162 i40e_init_recovery_mode() warn: missing error code 'err' Fixes: 4ff0ee1af0169 ("i40e: Introduce recovery mode support") Signed-off-by: Aleksandr Loktionov Signed-off-by: Arkadiusz Kubalewski Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/i40e/i40e_main.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index c0a4bc2caae9..30ad7c08d0fb 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -15138,12 +15138,16 @@ static int i40e_init_recovery_mode(struct i40e_pf *pf, struct i40e_hw *hw) * in order to register the netdev */ v_idx = i40e_vsi_mem_alloc(pf, I40E_VSI_MAIN); - if (v_idx < 0) + if (v_idx < 0) { + err = v_idx; goto err_switch_setup; + } pf->lan_vsi = v_idx; vsi = pf->vsi[v_idx]; - if (!vsi) + if (!vsi) { + err = -EFAULT; goto err_switch_setup; + } vsi->alloc_queue_pairs = 1; err = i40e_config_netdev(vsi); if (err) From 1831da7ea5bdf5531d78bcf81f526faa4c4375fa Mon Sep 17 00:00:00 2001 From: Yongxin Liu Date: Thu, 1 Apr 2021 11:59:15 -0700 Subject: [PATCH 0835/1091] ice: fix memory leak of aRFS after resuming from suspend In ice_suspend(), ice_clear_interrupt_scheme() is called, and then irq_free_descs() will be eventually called to free irq and its descriptor. In ice_resume(), ice_init_interrupt_scheme() is called to allocate new irqs. However, in ice_rebuild_arfs(), struct irq_glue and struct cpu_rmap maybe cannot be freed, if the irqs that released in ice_suspend() were reassigned to other devices, which makes irq descriptor's affinity_notify lost. So call ice_free_cpu_rx_rmap() before ice_clear_interrupt_scheme(), which can make sure all irq_glue and cpu_rmap can be correctly released before corresponding irq and descriptor are released. Fix the following memory leak. unreferenced object 0xffff95bd951afc00 (size 512): comm "kworker/0:1", pid 134, jiffies 4294684283 (age 13051.958s) hex dump (first 32 bytes): 18 00 00 00 18 00 18 00 70 fc 1a 95 bd 95 ff ff ........p....... 00 00 ff ff 01 00 ff ff 02 00 ff ff 03 00 ff ff ................ backtrace: [<0000000072e4b914>] __kmalloc+0x336/0x540 [<0000000054642a87>] alloc_cpu_rmap+0x3b/0xb0 [<00000000f220deec>] ice_set_cpu_rx_rmap+0x6a/0x110 [ice] [<000000002370a632>] ice_probe+0x941/0x1180 [ice] [<00000000d692edba>] local_pci_probe+0x47/0xa0 [<00000000503934f0>] work_for_cpu_fn+0x1a/0x30 [<00000000555a9e4a>] process_one_work+0x1dd/0x410 [<000000002c4b414a>] worker_thread+0x221/0x3f0 [<00000000bb2b556b>] kthread+0x14c/0x170 [<00000000ad2cf1cd>] ret_from_fork+0x1f/0x30 unreferenced object 0xffff95bd81b0a2a0 (size 96): comm "kworker/0:1", pid 134, jiffies 4294684283 (age 13051.958s) hex dump (first 32 bytes): 38 00 00 00 01 00 00 00 e0 ff ff ff 0f 00 00 00 8............... b0 a2 b0 81 bd 95 ff ff b0 a2 b0 81 bd 95 ff ff ................ backtrace: [<00000000582dd5c5>] kmem_cache_alloc_trace+0x31f/0x4c0 [<000000002659850d>] irq_cpu_rmap_add+0x25/0xe0 [<00000000495a3055>] ice_set_cpu_rx_rmap+0xb4/0x110 [ice] [<000000002370a632>] ice_probe+0x941/0x1180 [ice] [<00000000d692edba>] local_pci_probe+0x47/0xa0 [<00000000503934f0>] work_for_cpu_fn+0x1a/0x30 [<00000000555a9e4a>] process_one_work+0x1dd/0x410 [<000000002c4b414a>] worker_thread+0x221/0x3f0 [<00000000bb2b556b>] kthread+0x14c/0x170 [<00000000ad2cf1cd>] ret_from_fork+0x1f/0x30 Fixes: 769c500dcc1e ("ice: Add advanced power mgmt for WoL") Signed-off-by: Yongxin Liu Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_main.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c index 9f1adff85be7..d821c687f239 100644 --- a/drivers/net/ethernet/intel/ice/ice_main.c +++ b/drivers/net/ethernet/intel/ice/ice_main.c @@ -4564,6 +4564,7 @@ static int __maybe_unused ice_suspend(struct device *dev) continue; ice_vsi_free_q_vectors(pf->vsi[v]); } + ice_free_cpu_rx_rmap(ice_get_main_vsi(pf)); ice_clear_interrupt_scheme(pf); pci_save_state(pdev); From d1c803a9ccd7bd3aff5e989ccfb39ed3b799b975 Mon Sep 17 00:00:00 2001 From: Leon Romanovsky Date: Mon, 5 Apr 2021 10:44:34 +0300 Subject: [PATCH 0836/1091] RDMA/addr: Be strict with gid size The nla_len() is less than or equal to 16. If it's less than 16 then end of the "gid" buffer is uninitialized. Fixes: ae43f8286730 ("IB/core: Add IP to GID netlink offload") Link: https://lore.kernel.org/r/20210405074434.264221-1-leon@kernel.org Reported-by: Dan Carpenter Signed-off-by: Mark Bloch Signed-off-by: Leon Romanovsky Signed-off-by: Jason Gunthorpe --- drivers/infiniband/core/addr.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/infiniband/core/addr.c b/drivers/infiniband/core/addr.c index 0abce004a959..65e3e7df8a4b 100644 --- a/drivers/infiniband/core/addr.c +++ b/drivers/infiniband/core/addr.c @@ -76,7 +76,9 @@ static struct workqueue_struct *addr_wq; static const struct nla_policy ib_nl_addr_policy[LS_NLA_TYPE_MAX] = { [LS_NLA_TYPE_DGID] = {.type = NLA_BINARY, - .len = sizeof(struct rdma_nla_ls_gid)}, + .len = sizeof(struct rdma_nla_ls_gid), + .validation_type = NLA_VALIDATE_MIN, + .min = sizeof(struct rdma_nla_ls_gid)}, }; static inline bool ib_nl_is_good_ip_resp(const struct nlmsghdr *nlh) From 9728463737db027557e8ba315cbbca6b81122c04 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 8 Apr 2021 19:28:03 +0100 Subject: [PATCH 0837/1091] io_uring: fix rw req completion WARNING: at fs/io_uring.c:8578 io_ring_exit_work.cold+0x0/0x18 As reissuing is now passed back by REQ_F_REISSUE and kiocb_done() internally uses __io_complete_rw(), it may stop after setting the flag so leaving a dangling request. There are tricky edge cases, e.g. reading beyound file, boundary, so the easiest way is to hand code reissue in kiocb_done() as __io_complete_rw() was doing for us before. Fixes: 230d50d448ac ("io_uring: move reissue into regular IO path") Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/f602250d292f8a84cca9a01d747744d1e797be26.1617842918.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- fs/io_uring.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/fs/io_uring.c b/fs/io_uring.c index f1881ac0744b..bd14327c8e7e 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -2762,6 +2762,7 @@ static void kiocb_done(struct kiocb *kiocb, ssize_t ret, { struct io_kiocb *req = container_of(kiocb, struct io_kiocb, rw.kiocb); struct io_async_rw *io = req->async_data; + bool check_reissue = kiocb->ki_complete == io_complete_rw; /* add previously done IO, if any */ if (io && io->bytes_done > 0) { @@ -2777,6 +2778,18 @@ static void kiocb_done(struct kiocb *kiocb, ssize_t ret, __io_complete_rw(req, ret, 0, issue_flags); else io_rw_done(kiocb, ret); + + if (check_reissue && req->flags & REQ_F_REISSUE) { + req->flags &= ~REQ_F_REISSUE; + if (!io_rw_reissue(req)) { + int cflags = 0; + + req_set_fail_links(req); + if (req->flags & REQ_F_BUFFER_SELECTED) + cflags = io_put_rw_kbuf(req); + __io_req_complete(req, issue_flags, ret, cflags); + } + } } static int io_import_fixed(struct io_kiocb *req, int rw, struct iov_iter *iter) From c60eb049f4a19ddddcd3ee97a9c79ab8066a6a03 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Thu, 8 Apr 2021 01:54:42 +0100 Subject: [PATCH 0838/1091] io-wq: cancel unbounded works on io-wq destroy WARNING: CPU: 5 PID: 227 at fs/io_uring.c:8578 io_ring_exit_work+0xe6/0x470 RIP: 0010:io_ring_exit_work+0xe6/0x470 Call Trace: process_one_work+0x206/0x400 worker_thread+0x4a/0x3d0 kthread+0x129/0x170 ret_from_fork+0x22/0x30 INFO: task lfs-openat:2359 blocked for more than 245 seconds. task:lfs-openat state:D stack: 0 pid: 2359 ppid: 1 flags:0x00000004 Call Trace: ... wait_for_completion+0x8b/0xf0 io_wq_destroy_manager+0x24/0x60 io_wq_put_and_exit+0x18/0x30 io_uring_clean_tctx+0x76/0xa0 __io_uring_files_cancel+0x1b9/0x2e0 do_exit+0xc0/0xb40 ... Even after io-wq destroy has been issued io-wq worker threads will continue executing all left work items as usual, and may hang waiting for I/O that won't ever complete (aka unbounded). [<0>] pipe_read+0x306/0x450 [<0>] io_iter_do_read+0x1e/0x40 [<0>] io_read+0xd5/0x330 [<0>] io_issue_sqe+0xd21/0x18a0 [<0>] io_wq_submit_work+0x6c/0x140 [<0>] io_worker_handle_work+0x17d/0x400 [<0>] io_wqe_worker+0x2c0/0x330 [<0>] ret_from_fork+0x22/0x30 Cancel all unbounded I/O instead of executing them. This changes the user visible behaviour, but that's inevitable as io-wq is not per task. Suggested-by: Jens Axboe Signed-off-by: Pavel Begunkov Link: https://lore.kernel.org/r/cd4b543154154cba055cf86f351441c2174d7f71.1617842918.git.asml.silence@gmail.com Signed-off-by: Jens Axboe --- fs/io-wq.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/fs/io-wq.c b/fs/io-wq.c index 433c4d3c3c1c..4eba531bea5a 100644 --- a/fs/io-wq.c +++ b/fs/io-wq.c @@ -415,6 +415,7 @@ static void io_worker_handle_work(struct io_worker *worker) { struct io_wqe *wqe = worker->wqe; struct io_wq *wq = wqe->wq; + bool do_kill = test_bit(IO_WQ_BIT_EXIT, &wq->state); do { struct io_wq_work *work; @@ -444,6 +445,9 @@ get_next: unsigned int hash = io_get_work_hash(work); next_hashed = wq_next_work(work); + + if (unlikely(do_kill) && (work->flags & IO_WQ_WORK_UNBOUND)) + work->flags |= IO_WQ_WORK_CANCEL; wq->do_work(work); io_assign_current_work(worker, NULL); From df8a39f2911a4c7769e0f760509f556a9e9d37af Mon Sep 17 00:00:00 2001 From: Wolfram Sang Date: Wed, 7 Apr 2021 20:35:32 +0200 Subject: [PATCH 0839/1091] i2c: imx: mention Oleksij as maintainer of the binding docs When I removed myself as a maintainer of the yaml file, I missed that some maintainer is required. Oleksij is already listed in MAINTAINERS for this file, so add him here as well. Fixes: 1ae6b3780848 ("i2c: imx: drop me as maintainer of binding docs") Reviewed-by: Oleksij Rempel Reviewed-by: Rob Herring Signed-off-by: Wolfram Sang --- Documentation/devicetree/bindings/i2c/i2c-imx.yaml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Documentation/devicetree/bindings/i2c/i2c-imx.yaml b/Documentation/devicetree/bindings/i2c/i2c-imx.yaml index f33c6b29966b..3592d49235e0 100644 --- a/Documentation/devicetree/bindings/i2c/i2c-imx.yaml +++ b/Documentation/devicetree/bindings/i2c/i2c-imx.yaml @@ -6,6 +6,9 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: Freescale Inter IC (I2C) and High Speed Inter IC (HS-I2C) for i.MX +maintainers: + - Oleksij Rempel + allOf: - $ref: /schemas/i2c/i2c-controller.yaml# From 4ba86128ba077fbb7d86516ae24ed642e6c3adef Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 7 Apr 2021 18:36:02 +0300 Subject: [PATCH 0840/1091] Revert "net: sched: bump refcount for new action in ACT replace mode" This reverts commit 6855e8213e06efcaf7c02a15e12b1ae64b9a7149. Following commit in series fixes the issue without introducing regression in error rollback of tcf_action_destroy(). Signed-off-by: Vlad Buslov Signed-off-by: David S. Miller --- net/sched/act_api.c | 3 --- 1 file changed, 3 deletions(-) diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 43cceb924976..b919826939e0 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -1042,9 +1042,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, if (err != ACT_P_CREATED) module_put(a_o->owner); - if (!bind && ovr && err == ACT_P_CREATED) - refcount_set(&a->tcfa_refcnt, 2); - return a; err_out: From 87c750e8c38bce706eb32e4d8f1e3402f2cebbd4 Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 7 Apr 2021 18:36:03 +0300 Subject: [PATCH 0841/1091] net: sched: fix action overwrite reference counting Action init code increments reference counter when it changes an action. This is the desired behavior for cls API which needs to obtain action reference for every classifier that points to action. However, act API just needs to change the action and releases the reference before returning. This sequence breaks when the requested action doesn't exist, which causes act API init code to create new action with specified index, but action is still released before returning and is deleted (unless it was referenced concurrently by cls API). Reproduction: $ sudo tc actions ls action gact $ sudo tc actions change action gact drop index 1 $ sudo tc actions ls action gact Extend tcf_action_init() to accept 'init_res' array and initialize it with action->ops->init() result. In tcf_action_add() remove pointers to created actions from actions array before passing it to tcf_action_put_many(). Fixes: cae422f379f3 ("net: sched: use reference counting action init") Reported-by: Kumar Kartikeya Dwivedi Signed-off-by: Vlad Buslov Signed-off-by: David S. Miller --- include/net/act_api.h | 5 +++-- net/sched/act_api.c | 22 +++++++++++++++------- net/sched/cls_api.c | 9 +++++---- 3 files changed, 23 insertions(+), 13 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 2bf3092ae7ec..312f0f6554a0 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -185,7 +185,7 @@ int tcf_action_exec(struct sk_buff *skb, struct tc_action **actions, int nr_actions, struct tcf_result *res); int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, struct nlattr *est, char *name, int ovr, int bind, - struct tc_action *actions[], size_t *attr_size, + struct tc_action *actions[], int init_res[], size_t *attr_size, bool rtnl_held, struct netlink_ext_ack *extack); struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, bool rtnl_held, @@ -193,7 +193,8 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, struct nlattr *nla, struct nlattr *est, char *name, int ovr, int bind, - struct tc_action_ops *ops, bool rtnl_held, + struct tc_action_ops *a_o, int *init_res, + bool rtnl_held, struct netlink_ext_ack *extack); int tcf_action_dump(struct sk_buff *skb, struct tc_action *actions[], int bind, int ref, bool terse); diff --git a/net/sched/act_api.c b/net/sched/act_api.c index b919826939e0..50854cfbfcdb 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -992,7 +992,8 @@ struct tc_action_ops *tc_action_load_ops(char *name, struct nlattr *nla, struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, struct nlattr *nla, struct nlattr *est, char *name, int ovr, int bind, - struct tc_action_ops *a_o, bool rtnl_held, + struct tc_action_ops *a_o, int *init_res, + bool rtnl_held, struct netlink_ext_ack *extack) { struct nla_bitfield32 flags = { 0, 0 }; @@ -1028,6 +1029,7 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, } if (err < 0) goto err_out; + *init_res = err; if (!name && tb[TCA_ACT_COOKIE]) tcf_set_action_cookie(&a->act_cookie, cookie); @@ -1056,7 +1058,7 @@ err_out: int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, struct nlattr *est, char *name, int ovr, int bind, - struct tc_action *actions[], size_t *attr_size, + struct tc_action *actions[], int init_res[], size_t *attr_size, bool rtnl_held, struct netlink_ext_ack *extack) { struct tc_action_ops *ops[TCA_ACT_MAX_PRIO] = {}; @@ -1084,7 +1086,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, for (i = 1; i <= TCA_ACT_MAX_PRIO && tb[i]; i++) { act = tcf_action_init_1(net, tp, tb[i], est, name, ovr, bind, - ops[i - 1], rtnl_held, extack); + ops[i - 1], &init_res[i - 1], rtnl_held, + extack); if (IS_ERR(act)) { err = PTR_ERR(act); goto err; @@ -1497,12 +1500,13 @@ static int tcf_action_add(struct net *net, struct nlattr *nla, struct netlink_ext_ack *extack) { size_t attr_size = 0; - int loop, ret; + int loop, ret, i; struct tc_action *actions[TCA_ACT_MAX_PRIO] = {}; + int init_res[TCA_ACT_MAX_PRIO] = {}; for (loop = 0; loop < 10; loop++) { ret = tcf_action_init(net, NULL, nla, NULL, NULL, ovr, 0, - actions, &attr_size, true, extack); + actions, init_res, &attr_size, true, extack); if (ret != -EAGAIN) break; } @@ -1510,8 +1514,12 @@ static int tcf_action_add(struct net *net, struct nlattr *nla, if (ret < 0) return ret; ret = tcf_add_notify(net, n, actions, portid, attr_size, extack); - if (ovr) - tcf_action_put_many(actions); + + /* only put existing actions */ + for (i = 0; i < TCA_ACT_MAX_PRIO; i++) + if (init_res[i] == ACT_P_CREATED) + actions[i] = NULL; + tcf_action_put_many(actions); return ret; } diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 9332ec6863e8..9ecb91ebf094 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3040,6 +3040,7 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, { #ifdef CONFIG_NET_CLS_ACT { + int init_res[TCA_ACT_MAX_PRIO] = {}; struct tc_action *act; size_t attr_size = 0; @@ -3051,8 +3052,8 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, return PTR_ERR(a_o); act = tcf_action_init_1(net, tp, tb[exts->police], rate_tlv, "police", ovr, - TCA_ACT_BIND, a_o, rtnl_held, - extack); + TCA_ACT_BIND, a_o, init_res, + rtnl_held, extack); if (IS_ERR(act)) { module_put(a_o->owner); return PTR_ERR(act); @@ -3067,8 +3068,8 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, err = tcf_action_init(net, tp, tb[exts->action], rate_tlv, NULL, ovr, TCA_ACT_BIND, - exts->actions, &attr_size, - rtnl_held, extack); + exts->actions, init_res, + &attr_size, rtnl_held, extack); if (err < 0) return err; exts->nr_actions = err; From b3650bf76a32380d4d80a3e21b5583e7303f216c Mon Sep 17 00:00:00 2001 From: Vlad Buslov Date: Wed, 7 Apr 2021 18:36:04 +0300 Subject: [PATCH 0842/1091] net: sched: fix err handler in tcf_action_init() With recent changes that separated action module load from action initialization tcf_action_init() function error handling code was modified to manually release the loaded modules if loading/initialization of any further action in same batch failed. For the case when all modules successfully loaded and some of the actions were initialized before one of them failed in init handler. In this case for all previous actions the module will be released twice by the error handler: First time by the loop that manually calls module_put() for all ops, and second time by the action destroy code that puts the module after destroying the action. Reproduction: $ sudo tc actions add action simple sdata \"2\" index 2 $ sudo tc actions add action simple sdata \"1\" index 1 \ action simple sdata \"2\" index 2 RTNETLINK answers: File exists We have an error talking to the kernel $ sudo tc actions ls action simple total acts 1 action order 0: Simple <"2"> index 2 ref 1 bind 0 $ sudo tc actions flush action simple $ sudo tc actions ls action simple $ sudo tc actions add action simple sdata \"2\" index 2 Error: Failed to load TC action module. We have an error talking to the kernel $ lsmod | grep simple act_simple 20480 -1 Fix the issue by modifying module reference counting handling in action initialization code: - Get module reference in tcf_idr_create() and put it in tcf_idr_release() instead of taking over the reference held by the caller. - Modify users of tcf_action_init_1() to always release the module reference which they obtain before calling init function instead of assuming that created action takes over the reference. - Finally, modify tcf_action_init_1() to not release the module reference when overwriting existing action as this is no longer necessary since both upper and lower layers obtain and manage their own module references independently. Fixes: d349f9976868 ("net_sched: fix RTNL deadlock again caused by request_module()") Suggested-by: Cong Wang Signed-off-by: Vlad Buslov Signed-off-by: David S. Miller --- include/net/act_api.h | 7 +------ net/sched/act_api.c | 26 ++++++++++++++++---------- net/sched/cls_api.c | 5 ++--- 3 files changed, 19 insertions(+), 19 deletions(-) diff --git a/include/net/act_api.h b/include/net/act_api.h index 312f0f6554a0..086b291e9530 100644 --- a/include/net/act_api.h +++ b/include/net/act_api.h @@ -170,12 +170,7 @@ void tcf_idr_insert_many(struct tc_action *actions[]); void tcf_idr_cleanup(struct tc_action_net *tn, u32 index); int tcf_idr_check_alloc(struct tc_action_net *tn, u32 *index, struct tc_action **a, int bind); -int __tcf_idr_release(struct tc_action *a, bool bind, bool strict); - -static inline int tcf_idr_release(struct tc_action *a, bool bind) -{ - return __tcf_idr_release(a, bind, false); -} +int tcf_idr_release(struct tc_action *a, bool bind); int tcf_register_action(struct tc_action_ops *a, struct pernet_operations *ops); int tcf_unregister_action(struct tc_action_ops *a, diff --git a/net/sched/act_api.c b/net/sched/act_api.c index 50854cfbfcdb..f6d5755d669e 100644 --- a/net/sched/act_api.c +++ b/net/sched/act_api.c @@ -158,7 +158,7 @@ static int __tcf_action_put(struct tc_action *p, bool bind) return 0; } -int __tcf_idr_release(struct tc_action *p, bool bind, bool strict) +static int __tcf_idr_release(struct tc_action *p, bool bind, bool strict) { int ret = 0; @@ -184,7 +184,18 @@ int __tcf_idr_release(struct tc_action *p, bool bind, bool strict) return ret; } -EXPORT_SYMBOL(__tcf_idr_release); + +int tcf_idr_release(struct tc_action *a, bool bind) +{ + const struct tc_action_ops *ops = a->ops; + int ret; + + ret = __tcf_idr_release(a, bind, false); + if (ret == ACT_P_DELETED) + module_put(ops->owner); + return ret; +} +EXPORT_SYMBOL(tcf_idr_release); static size_t tcf_action_shared_attrs_size(const struct tc_action *act) { @@ -493,6 +504,7 @@ int tcf_idr_create(struct tc_action_net *tn, u32 index, struct nlattr *est, } p->idrinfo = idrinfo; + __module_get(ops->owner); p->ops = ops; *a = p; return 0; @@ -1037,13 +1049,6 @@ struct tc_action *tcf_action_init_1(struct net *net, struct tcf_proto *tp, if (!name) a->hw_stats = hw_stats; - /* module count goes up only when brand new policy is created - * if it exists and is only bound to in a_o->init() then - * ACT_P_CREATED is not returned (a zero is). - */ - if (err != ACT_P_CREATED) - module_put(a_o->owner); - return a; err_out: @@ -1103,7 +1108,8 @@ int tcf_action_init(struct net *net, struct tcf_proto *tp, struct nlattr *nla, tcf_idr_insert_many(actions); *attr_size = tcf_action_full_attrs_size(sz); - return i - 1; + err = i - 1; + goto err_mod; err: tcf_action_destroy(actions, bind); diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index 9ecb91ebf094..340d5af86e87 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -3054,10 +3054,9 @@ int tcf_exts_validate(struct net *net, struct tcf_proto *tp, struct nlattr **tb, rate_tlv, "police", ovr, TCA_ACT_BIND, a_o, init_res, rtnl_held, extack); - if (IS_ERR(act)) { - module_put(a_o->owner); + module_put(a_o->owner); + if (IS_ERR(act)) return PTR_ERR(act); - } act->type = exts->type = TCA_OLD_COMPAT; exts->actions[0] = act; From 3583a4e8d77d44697a21437227dd53fc6e7b2cb5 Mon Sep 17 00:00:00 2001 From: Stephen Hemminger Date: Wed, 7 Apr 2021 08:59:12 -0700 Subject: [PATCH 0843/1091] ipv6: report errors for iftoken via netlink extack Setting iftoken can fail for several different reasons but there and there was no report to user as to the cause. Add netlink extended errors to the processing of the request. This requires adding additional argument through rtnl_af_ops set_link_af callback. Reported-by: Hongren Zheng Signed-off-by: Stephen Hemminger Reviewed-by: David Ahern Signed-off-by: David S. Miller --- include/net/rtnetlink.h | 4 ++-- net/core/rtnetlink.c | 2 +- net/ipv4/devinet.c | 3 ++- net/ipv6/addrconf.c | 32 ++++++++++++++++++++++++++------ 4 files changed, 31 insertions(+), 10 deletions(-) diff --git a/include/net/rtnetlink.h b/include/net/rtnetlink.h index 4da61c950e93..479f60ef54c0 100644 --- a/include/net/rtnetlink.h +++ b/include/net/rtnetlink.h @@ -147,8 +147,8 @@ struct rtnl_af_ops { int (*validate_link_af)(const struct net_device *dev, const struct nlattr *attr); int (*set_link_af)(struct net_device *dev, - const struct nlattr *attr); - + const struct nlattr *attr, + struct netlink_ext_ack *extack); int (*fill_stats_af)(struct sk_buff *skb, const struct net_device *dev); size_t (*get_stats_af_size)(const struct net_device *dev); diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 1bdcb33fb561..3485b16a7ff3 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -2863,7 +2863,7 @@ static int do_setlink(const struct sk_buff *skb, BUG_ON(!(af_ops = rtnl_af_lookup(nla_type(af)))); - err = af_ops->set_link_af(dev, af); + err = af_ops->set_link_af(dev, af, extack); if (err < 0) { rcu_read_unlock(); goto errout; diff --git a/net/ipv4/devinet.c b/net/ipv4/devinet.c index 75f67994fc85..2e35f68da40a 100644 --- a/net/ipv4/devinet.c +++ b/net/ipv4/devinet.c @@ -1978,7 +1978,8 @@ static int inet_validate_link_af(const struct net_device *dev, return 0; } -static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla) +static int inet_set_link_af(struct net_device *dev, const struct nlattr *nla, + struct netlink_ext_ack *extack) { struct in_device *in_dev = __in_dev_get_rcu(dev); struct nlattr *a, *tb[IFLA_INET_MAX+1]; diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index f2337fb756ac..a9e53f5942fa 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -5669,7 +5669,8 @@ static int inet6_fill_link_af(struct sk_buff *skb, const struct net_device *dev, return 0; } -static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) +static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token, + struct netlink_ext_ack *extack) { struct inet6_ifaddr *ifp; struct net_device *dev = idev->dev; @@ -5680,12 +5681,29 @@ static int inet6_set_iftoken(struct inet6_dev *idev, struct in6_addr *token) if (!token) return -EINVAL; - if (dev->flags & (IFF_LOOPBACK | IFF_NOARP)) + + if (dev->flags & IFF_LOOPBACK) { + NL_SET_ERR_MSG_MOD(extack, "Device is loopback"); return -EINVAL; - if (!ipv6_accept_ra(idev)) + } + + if (dev->flags & IFF_NOARP) { + NL_SET_ERR_MSG_MOD(extack, + "Device does not do neighbour discovery"); return -EINVAL; - if (idev->cnf.rtr_solicits == 0) + } + + if (!ipv6_accept_ra(idev)) { + NL_SET_ERR_MSG_MOD(extack, + "Router advertisement is disabled on device"); return -EINVAL; + } + + if (idev->cnf.rtr_solicits == 0) { + NL_SET_ERR_MSG(extack, + "Router solicitation is disabled on device"); + return -EINVAL; + } write_lock_bh(&idev->lock); @@ -5793,7 +5811,8 @@ static int inet6_validate_link_af(const struct net_device *dev, return 0; } -static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) +static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla, + struct netlink_ext_ack *extack) { struct inet6_dev *idev = __in6_dev_get(dev); struct nlattr *tb[IFLA_INET6_MAX + 1]; @@ -5806,7 +5825,8 @@ static int inet6_set_link_af(struct net_device *dev, const struct nlattr *nla) BUG(); if (tb[IFLA_INET6_TOKEN]) { - err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN])); + err = inet6_set_iftoken(idev, nla_data(tb[IFLA_INET6_TOKEN]), + extack); if (err) return err; } From 1ffbc7ea91606e4abd10eb60de5367f1c86daf5e Mon Sep 17 00:00:00 2001 From: Pavel Tikhomirov Date: Thu, 8 Apr 2021 18:14:31 +0300 Subject: [PATCH 0844/1091] net: sched: sch_teql: fix null-pointer dereference Reproduce: modprobe sch_teql tc qdisc add dev teql0 root teql0 This leads to (for instance in Centos 7 VM) OOPS: [ 532.366633] BUG: unable to handle kernel NULL pointer dereference at 00000000000000a8 [ 532.366733] IP: [] teql_destroy+0x18/0x100 [sch_teql] [ 532.366825] PGD 80000001376d5067 PUD 137e37067 PMD 0 [ 532.366906] Oops: 0000 [#1] SMP [ 532.366987] Modules linked in: sch_teql ... [ 532.367945] CPU: 1 PID: 3026 Comm: tc Kdump: loaded Tainted: G ------------ T 3.10.0-1062.7.1.el7.x86_64 #1 [ 532.368041] Hardware name: Virtuozzo KVM, BIOS 1.11.0-2.vz7.2 04/01/2014 [ 532.368125] task: ffff8b7d37d31070 ti: ffff8b7c9fdbc000 task.ti: ffff8b7c9fdbc000 [ 532.368224] RIP: 0010:[] [] teql_destroy+0x18/0x100 [sch_teql] [ 532.368320] RSP: 0018:ffff8b7c9fdbf8e0 EFLAGS: 00010286 [ 532.368394] RAX: ffffffffc0612490 RBX: ffff8b7cb1565e00 RCX: ffff8b7d35ba2000 [ 532.368476] RDX: ffff8b7d35ba2000 RSI: 0000000000000000 RDI: ffff8b7cb1565e00 [ 532.368557] RBP: ffff8b7c9fdbf8f8 R08: ffff8b7d3fd1f140 R09: ffff8b7d3b001600 [ 532.368638] R10: ffff8b7d3b001600 R11: ffffffff84c7d65b R12: 00000000ffffffd8 [ 532.368719] R13: 0000000000008000 R14: ffff8b7d35ba2000 R15: ffff8b7c9fdbf9a8 [ 532.368800] FS: 00007f6a4e872740(0000) GS:ffff8b7d3fd00000(0000) knlGS:0000000000000000 [ 532.368885] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 532.368961] CR2: 00000000000000a8 CR3: 00000001396ee000 CR4: 00000000000206e0 [ 532.369046] Call Trace: [ 532.369159] [] qdisc_create+0x36e/0x450 [ 532.369268] [] ? ns_capable+0x29/0x50 [ 532.369366] [] ? nla_parse+0x32/0x120 [ 532.369442] [] tc_modify_qdisc+0x13c/0x610 [ 532.371508] [] rtnetlink_rcv_msg+0xa7/0x260 [ 532.372668] [] ? sock_has_perm+0x75/0x90 [ 532.373790] [] ? rtnl_newlink+0x890/0x890 [ 532.374914] [] netlink_rcv_skb+0xab/0xc0 [ 532.376055] [] rtnetlink_rcv+0x28/0x30 [ 532.377204] [] netlink_unicast+0x170/0x210 [ 532.378333] [] netlink_sendmsg+0x308/0x420 [ 532.379465] [] sock_sendmsg+0xb6/0xf0 [ 532.380710] [] ? __xfs_filemap_fault+0x8e/0x1d0 [xfs] [ 532.381868] [] ? xfs_filemap_fault+0x2c/0x30 [xfs] [ 532.383037] [] ? __do_fault.isra.61+0x8a/0x100 [ 532.384144] [] ___sys_sendmsg+0x3e9/0x400 [ 532.385268] [] ? handle_mm_fault+0x39d/0x9b0 [ 532.386387] [] ? __do_page_fault+0x238/0x500 [ 532.387472] [] __sys_sendmsg+0x51/0x90 [ 532.388560] [] SyS_sendmsg+0x12/0x20 [ 532.389636] [] system_call_fastpath+0x25/0x2a [ 532.390704] [] ? system_call_after_swapgs+0xae/0x146 [ 532.391753] Code: 00 00 00 00 00 00 5b 5d c3 66 2e 0f 1f 84 00 00 00 00 00 66 66 66 66 90 55 48 89 e5 41 55 41 54 53 48 8b b7 48 01 00 00 48 89 fb <48> 8b 8e a8 00 00 00 48 85 c9 74 43 48 89 ca eb 0f 0f 1f 80 00 [ 532.394036] RIP [] teql_destroy+0x18/0x100 [sch_teql] [ 532.395127] RSP [ 532.396179] CR2: 00000000000000a8 Null pointer dereference happens on master->slaves dereference in teql_destroy() as master is null-pointer. When qdisc_create() calls teql_qdisc_init() it imediately fails after check "if (m->dev == dev)" because both devices are teql0, and it does not set qdisc_priv(sch)->m leaving it zero on error path, then qdisc_create() imediately calls teql_destroy() which does not expect zero master pointer and we get OOPS. Fixes: 87b60cfacf9f ("net_sched: fix error recovery at qdisc creation") Signed-off-by: Pavel Tikhomirov Reviewed-by: Eric Dumazet Signed-off-by: David S. Miller --- net/sched/sch_teql.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/net/sched/sch_teql.c b/net/sched/sch_teql.c index 2f1f0a378408..6af6b95bdb67 100644 --- a/net/sched/sch_teql.c +++ b/net/sched/sch_teql.c @@ -134,6 +134,9 @@ teql_destroy(struct Qdisc *sch) struct teql_sched_data *dat = qdisc_priv(sch); struct teql_master *master = dat->m; + if (!master) + return; + prev = master->slaves; if (prev) { do { From afd0be7299533bb2e2b09104399d8a467ecbd2c5 Mon Sep 17 00:00:00 2001 From: Ciara Loftus Date: Thu, 8 Apr 2021 05:20:09 +0000 Subject: [PATCH 0845/1091] libbpf: Fix potential NULL pointer dereference Wait until after the UMEM is checked for null to dereference it. Fixes: 43f1bc1efff1 ("libbpf: Restore umem state after socket create failure") Signed-off-by: Ciara Loftus Signed-off-by: Daniel Borkmann Link: https://lore.kernel.org/bpf/20210408052009.7844-1-ciara.loftus@intel.com --- tools/lib/bpf/xsk.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/tools/lib/bpf/xsk.c b/tools/lib/bpf/xsk.c index d24b5cc720ec..007fe5d59438 100644 --- a/tools/lib/bpf/xsk.c +++ b/tools/lib/bpf/xsk.c @@ -852,18 +852,19 @@ int xsk_socket__create_shared(struct xsk_socket **xsk_ptr, struct xsk_ring_cons *comp, const struct xsk_socket_config *usr_config) { + bool unmap, rx_setup_done = false, tx_setup_done = false; void *rx_map = NULL, *tx_map = NULL; struct sockaddr_xdp sxdp = {}; struct xdp_mmap_offsets off; struct xsk_socket *xsk; struct xsk_ctx *ctx; int err, ifindex; - bool unmap = umem->fill_save != fill; - bool rx_setup_done = false, tx_setup_done = false; if (!umem || !xsk_ptr || !(rx || tx)) return -EFAULT; + unmap = umem->fill_save != fill; + xsk = calloc(1, sizeof(*xsk)); if (!xsk) return -ENOMEM; From 48d499bd89191b359a6dbe44d32107e3021571c2 Mon Sep 17 00:00:00 2001 From: Frank Rowand Date: Thu, 8 Apr 2021 15:45:08 -0500 Subject: [PATCH 0846/1091] of: unittest: overlay: ensure proper alignment of copied FDT The Devicetree standard specifies an 8 byte alignment of the FDT. Code in libfdt expects this alignment for an FDT image in memory. kmemdup() returns 4 byte alignment on openrisc. Replace kmemdup() with kmalloc(), align pointer, memcpy() to get proper alignment. The 4 byte alignment exposed a related bug which triggered a crash on openrisc with: commit 79edff12060f ("scripts/dtc: Update to upstream version v1.6.0-51-g183df9e9c2b9") as reported in: https://lore.kernel.org/lkml/20210327224116.69309-1-linux@roeck-us.net/ Reported-by: Guenter Roeck Signed-off-by: Frank Rowand Link: https://lore.kernel.org/r/20210408204508.2276230-1-frowand.list@gmail.com Signed-off-by: Rob Herring --- drivers/of/of_private.h | 2 ++ drivers/of/overlay.c | 22 ++++++++++++++-------- drivers/of/unittest.c | 9 +++++++-- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/drivers/of/of_private.h b/drivers/of/of_private.h index d9e6a324de0a..d717efbd637d 100644 --- a/drivers/of/of_private.h +++ b/drivers/of/of_private.h @@ -8,6 +8,8 @@ * Copyright (C) 1996-2005 Paul Mackerras. */ +#define FDT_ALIGN_SIZE 8 + /** * struct alias_prop - Alias property in 'aliases' node * @link: List node to link the structure in aliases_lookup list diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c index e12c643b6ba8..23effe5e50ec 100644 --- a/drivers/of/overlay.c +++ b/drivers/of/overlay.c @@ -57,7 +57,7 @@ struct fragment { * struct overlay_changeset * @id: changeset identifier * @ovcs_list: list on which we are located - * @fdt: FDT that was unflattened to create @overlay_tree + * @fdt: base of memory allocated to hold aligned FDT that was unflattened to create @overlay_tree * @overlay_tree: expanded device tree that contains the fragment nodes * @count: count of fragment structures * @fragments: fragment nodes in the overlay expanded device tree @@ -719,8 +719,8 @@ static struct device_node *find_target(struct device_node *info_node) /** * init_overlay_changeset() - initialize overlay changeset from overlay tree * @ovcs: Overlay changeset to build - * @fdt: the FDT that was unflattened to create @tree - * @tree: Contains all the overlay fragments and overlay fixup nodes + * @fdt: base of memory allocated to hold aligned FDT that was unflattened to create @tree + * @tree: Contains the overlay fragments and overlay fixup nodes * * Initialize @ovcs. Populate @ovcs->fragments with node information from * the top level of @tree. The relevant top level nodes are the fragment @@ -873,7 +873,7 @@ static void free_overlay_changeset(struct overlay_changeset *ovcs) * internal documentation * * of_overlay_apply() - Create and apply an overlay changeset - * @fdt: the FDT that was unflattened to create @tree + * @fdt: base of memory allocated to hold the aligned FDT * @tree: Expanded overlay device tree * @ovcs_id: Pointer to overlay changeset id * @@ -953,7 +953,9 @@ static int of_overlay_apply(const void *fdt, struct device_node *tree, /* * after overlay_notify(), ovcs->overlay_tree related pointers may have * leaked to drivers, so can not kfree() tree, aka ovcs->overlay_tree; - * and can not free fdt, aka ovcs->fdt + * and can not free memory containing aligned fdt. The aligned fdt + * is contained within the memory at ovcs->fdt, possibly at an offset + * from ovcs->fdt. */ ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); if (ret) { @@ -1014,7 +1016,8 @@ out: int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, int *ovcs_id) { - const void *new_fdt; + void *new_fdt; + void *new_fdt_align; int ret; u32 size; struct device_node *overlay_root = NULL; @@ -1036,11 +1039,14 @@ int of_overlay_fdt_apply(const void *overlay_fdt, u32 overlay_fdt_size, * Must create permanent copy of FDT because of_fdt_unflatten_tree() * will create pointers to the passed in FDT in the unflattened tree. */ - new_fdt = kmemdup(overlay_fdt, size, GFP_KERNEL); + new_fdt = kmalloc(size + FDT_ALIGN_SIZE, GFP_KERNEL); if (!new_fdt) return -ENOMEM; - of_fdt_unflatten_tree(new_fdt, NULL, &overlay_root); + new_fdt_align = PTR_ALIGN(new_fdt, FDT_ALIGN_SIZE); + memcpy(new_fdt_align, overlay_fdt, size); + + of_fdt_unflatten_tree(new_fdt_align, NULL, &overlay_root); if (!overlay_root) { pr_err("unable to unflatten overlay_fdt\n"); ret = -EINVAL; diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index f9b5b698249f..819a20acaa93 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c @@ -22,6 +22,7 @@ #include #include #include +#include #include #include @@ -1408,6 +1409,7 @@ static void attach_node_and_children(struct device_node *np) static int __init unittest_data_add(void) { void *unittest_data; + void *unittest_data_align; struct device_node *unittest_data_node = NULL, *np; /* * __dtb_testcases_begin[] and __dtb_testcases_end[] are magically @@ -1425,11 +1427,14 @@ static int __init unittest_data_add(void) } /* creating copy */ - unittest_data = kmemdup(__dtb_testcases_begin, size, GFP_KERNEL); + unittest_data = kmalloc(size + FDT_ALIGN_SIZE, GFP_KERNEL); if (!unittest_data) return -ENOMEM; - ret = of_fdt_unflatten_tree(unittest_data, NULL, &unittest_data_node); + unittest_data_align = PTR_ALIGN(unittest_data, FDT_ALIGN_SIZE); + memcpy(unittest_data_align, __dtb_testcases_begin, size); + + ret = of_fdt_unflatten_tree(unittest_data_align, NULL, &unittest_data_node); if (!ret) { pr_warn("%s: unflatten testcases tree failed\n", __func__); kfree(unittest_data); From 3e9005be87777afc902b9f5497495898202d335d Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 8 Apr 2021 20:38:27 +0200 Subject: [PATCH 0847/1091] net: dsa: lantiq_gswip: Don't use PHY auto polling PHY auto polling on the GSWIP hardware can be used so link changes (speed, link up/down, etc.) can be detected automatically. Internally GSWIP reads the PHY's registers for this functionality. Based on this automatic detection GSWIP can also automatically re-configure it's port settings. Unfortunately this auto polling (and configuration) mechanism seems to cause various issues observed by different people on different devices: - FritzBox 7360v2: the two Gbit/s ports (connected to the two internal PHY11G instances) are working fine but the two Fast Ethernet ports (using an AR8030 RMII PHY) are completely dead (neither RX nor TX are received). It turns out that the AR8030 PHY sets the BMSR_ESTATEN bit as well as the ESTATUS_1000_TFULL and ESTATUS_1000_XFULL bits. This makes the PHY auto polling state machine (rightfully?) think that the established link speed (when the other side is Gbit/s capable) is 1Gbit/s. - None of the Ethernet ports on the Zyxel P-2812HNU-F1 (two are connected to the internal PHY11G GPHYs while the other three are external RGMII PHYs) are working. Neither RX nor TX traffic was observed. It is not clear which part of the PHY auto polling state- machine caused this. - FritzBox 7412 (only one LAN port which is connected to one of the internal GPHYs running in PHY22F / Fast Ethernet mode) was seeing random disconnects (link down events could be seen). Sometimes all traffic would stop after such disconnect. It is not clear which part of the PHY auto polling state-machine cauased this. - TP-Link TD-W9980 (two ports are connected to the internal GPHYs running in PHY11G / Gbit/s mode, the other two are external RGMII PHYs) was affected by similar issues as the FritzBox 7412 just without the "link down" events Switch to software based configuration instead of PHY auto polling (and letting the GSWIP hardware configure the ports automatically) for the following link parameters: - link up/down - link speed - full/half duplex - flow control (RX / TX pause) After a big round of manual testing by various people (who helped test this on OpenWrt) it turns out that this fixes all reported issues. Additionally it can be considered more future proof because any "quirk" which is implemented for a PHY on the driver side can now be used with the GSWIP hardware as well because Linux is in control of the link parameters. As a nice side-effect this also solves a problem where fixed-links were not supported previously because we were relying on the PHY auto polling mechanism, which cannot work for fixed-links as there's no PHY from where it can read the registers. Configuring the link settings on the GSWIP ports means that we now use the settings from device-tree also for ports with fixed-links. Fixes: 14fceff4771e51 ("net: dsa: Add Lantiq / Intel DSA driver for vrx200") Fixes: 3e6fdeb28f4c33 ("net: dsa: lantiq_gswip: Let GSWIP automatically set the xMII clock") Cc: stable@vger.kernel.org Acked-by: Hauke Mehrtens Reviewed-by: Andrew Lunn Signed-off-by: Martin Blumenstingl Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/lantiq_gswip.c | 183 ++++++++++++++++++++++++++++----- 1 file changed, 158 insertions(+), 25 deletions(-) diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 809dfa3be6bb..126d4ea868ba 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -190,6 +190,23 @@ #define GSWIP_PCE_DEFPVID(p) (0x486 + ((p) * 0xA)) #define GSWIP_MAC_FLEN 0x8C5 +#define GSWIP_MAC_CTRL_0p(p) (0x903 + ((p) * 0xC)) +#define GSWIP_MAC_CTRL_0_PADEN BIT(8) +#define GSWIP_MAC_CTRL_0_FCS_EN BIT(7) +#define GSWIP_MAC_CTRL_0_FCON_MASK 0x0070 +#define GSWIP_MAC_CTRL_0_FCON_AUTO 0x0000 +#define GSWIP_MAC_CTRL_0_FCON_RX 0x0010 +#define GSWIP_MAC_CTRL_0_FCON_TX 0x0020 +#define GSWIP_MAC_CTRL_0_FCON_RXTX 0x0030 +#define GSWIP_MAC_CTRL_0_FCON_NONE 0x0040 +#define GSWIP_MAC_CTRL_0_FDUP_MASK 0x000C +#define GSWIP_MAC_CTRL_0_FDUP_AUTO 0x0000 +#define GSWIP_MAC_CTRL_0_FDUP_EN 0x0004 +#define GSWIP_MAC_CTRL_0_FDUP_DIS 0x000C +#define GSWIP_MAC_CTRL_0_GMII_MASK 0x0003 +#define GSWIP_MAC_CTRL_0_GMII_AUTO 0x0000 +#define GSWIP_MAC_CTRL_0_GMII_MII 0x0001 +#define GSWIP_MAC_CTRL_0_GMII_RGMII 0x0002 #define GSWIP_MAC_CTRL_2p(p) (0x905 + ((p) * 0xC)) #define GSWIP_MAC_CTRL_2_MLEN BIT(3) /* Maximum Untagged Frame Lnegth */ @@ -653,16 +670,13 @@ static int gswip_port_enable(struct dsa_switch *ds, int port, GSWIP_SDMA_PCTRLp(port)); if (!dsa_is_cpu_port(ds, port)) { - u32 macconf = GSWIP_MDIO_PHY_LINK_AUTO | - GSWIP_MDIO_PHY_SPEED_AUTO | - GSWIP_MDIO_PHY_FDUP_AUTO | - GSWIP_MDIO_PHY_FCONTX_AUTO | - GSWIP_MDIO_PHY_FCONRX_AUTO | - (phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK); + u32 mdio_phy = 0; - gswip_mdio_w(priv, macconf, GSWIP_MDIO_PHYp(port)); - /* Activate MDIO auto polling */ - gswip_mdio_mask(priv, 0, BIT(port), GSWIP_MDIO_MDC_CFG0); + if (phydev) + mdio_phy = phydev->mdio.addr & GSWIP_MDIO_PHY_ADDR_MASK; + + gswip_mdio_mask(priv, GSWIP_MDIO_PHY_ADDR_MASK, mdio_phy, + GSWIP_MDIO_PHYp(port)); } return 0; @@ -675,14 +689,6 @@ static void gswip_port_disable(struct dsa_switch *ds, int port) if (!dsa_is_user_port(ds, port)) return; - if (!dsa_is_cpu_port(ds, port)) { - gswip_mdio_mask(priv, GSWIP_MDIO_PHY_LINK_DOWN, - GSWIP_MDIO_PHY_LINK_MASK, - GSWIP_MDIO_PHYp(port)); - /* Deactivate MDIO auto polling */ - gswip_mdio_mask(priv, BIT(port), 0, GSWIP_MDIO_MDC_CFG0); - } - gswip_switch_mask(priv, GSWIP_FDMA_PCTRL_EN, 0, GSWIP_FDMA_PCTRLp(port)); gswip_switch_mask(priv, GSWIP_SDMA_PCTRL_EN, 0, @@ -794,20 +800,31 @@ static int gswip_setup(struct dsa_switch *ds) gswip_switch_w(priv, BIT(cpu_port), GSWIP_PCE_PMAP2); gswip_switch_w(priv, BIT(cpu_port), GSWIP_PCE_PMAP3); - /* disable PHY auto polling */ + /* Deactivate MDIO PHY auto polling. Some PHYs as the AR8030 have an + * interoperability problem with this auto polling mechanism because + * their status registers think that the link is in a different state + * than it actually is. For the AR8030 it has the BMSR_ESTATEN bit set + * as well as ESTATUS_1000_TFULL and ESTATUS_1000_XFULL. This makes the + * auto polling state machine consider the link being negotiated with + * 1Gbit/s. Since the PHY itself is a Fast Ethernet RMII PHY this leads + * to the switch port being completely dead (RX and TX are both not + * working). + * Also with various other PHY / port combinations (PHY11G GPHY, PHY22F + * GPHY, external RGMII PEF7071/7072) any traffic would stop. Sometimes + * it would work fine for a few minutes to hours and then stop, on + * other device it would no traffic could be sent or received at all. + * Testing shows that when PHY auto polling is disabled these problems + * go away. + */ gswip_mdio_w(priv, 0x0, GSWIP_MDIO_MDC_CFG0); + /* Configure the MDIO Clock 2.5 MHz */ gswip_mdio_mask(priv, 0xff, 0x09, GSWIP_MDIO_MDC_CFG1); - for (i = 0; i < priv->hw_info->max_ports; i++) { - /* Disable the xMII link */ + /* Disable the xMII link */ + for (i = 0; i < priv->hw_info->max_ports; i++) gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, i); - /* Automatically select the xMII interface clock */ - gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_RATE_MASK, - GSWIP_MII_CFG_RATE_AUTO, i); - } - /* enable special tag insertion on cpu port */ gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN, GSWIP_FDMA_PCTRLp(cpu_port)); @@ -1455,6 +1472,112 @@ unsupported: return; } +static void gswip_port_set_link(struct gswip_priv *priv, int port, bool link) +{ + u32 mdio_phy; + + if (link) + mdio_phy = GSWIP_MDIO_PHY_LINK_UP; + else + mdio_phy = GSWIP_MDIO_PHY_LINK_DOWN; + + gswip_mdio_mask(priv, GSWIP_MDIO_PHY_LINK_MASK, mdio_phy, + GSWIP_MDIO_PHYp(port)); +} + +static void gswip_port_set_speed(struct gswip_priv *priv, int port, int speed, + phy_interface_t interface) +{ + u32 mdio_phy = 0, mii_cfg = 0, mac_ctrl_0 = 0; + + switch (speed) { + case SPEED_10: + mdio_phy = GSWIP_MDIO_PHY_SPEED_M10; + + if (interface == PHY_INTERFACE_MODE_RMII) + mii_cfg = GSWIP_MII_CFG_RATE_M50; + else + mii_cfg = GSWIP_MII_CFG_RATE_M2P5; + + mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_MII; + break; + + case SPEED_100: + mdio_phy = GSWIP_MDIO_PHY_SPEED_M100; + + if (interface == PHY_INTERFACE_MODE_RMII) + mii_cfg = GSWIP_MII_CFG_RATE_M50; + else + mii_cfg = GSWIP_MII_CFG_RATE_M25; + + mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_MII; + break; + + case SPEED_1000: + mdio_phy = GSWIP_MDIO_PHY_SPEED_G1; + + mii_cfg = GSWIP_MII_CFG_RATE_M125; + + mac_ctrl_0 = GSWIP_MAC_CTRL_0_GMII_RGMII; + break; + } + + gswip_mdio_mask(priv, GSWIP_MDIO_PHY_SPEED_MASK, mdio_phy, + GSWIP_MDIO_PHYp(port)); + gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_RATE_MASK, mii_cfg, port); + gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_GMII_MASK, mac_ctrl_0, + GSWIP_MAC_CTRL_0p(port)); +} + +static void gswip_port_set_duplex(struct gswip_priv *priv, int port, int duplex) +{ + u32 mac_ctrl_0, mdio_phy; + + if (duplex == DUPLEX_FULL) { + mac_ctrl_0 = GSWIP_MAC_CTRL_0_FDUP_EN; + mdio_phy = GSWIP_MDIO_PHY_FDUP_EN; + } else { + mac_ctrl_0 = GSWIP_MAC_CTRL_0_FDUP_DIS; + mdio_phy = GSWIP_MDIO_PHY_FDUP_DIS; + } + + gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_FDUP_MASK, mac_ctrl_0, + GSWIP_MAC_CTRL_0p(port)); + gswip_mdio_mask(priv, GSWIP_MDIO_PHY_FDUP_MASK, mdio_phy, + GSWIP_MDIO_PHYp(port)); +} + +static void gswip_port_set_pause(struct gswip_priv *priv, int port, + bool tx_pause, bool rx_pause) +{ + u32 mac_ctrl_0, mdio_phy; + + if (tx_pause && rx_pause) { + mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_RXTX; + mdio_phy = GSWIP_MDIO_PHY_FCONTX_EN | + GSWIP_MDIO_PHY_FCONRX_EN; + } else if (tx_pause) { + mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_TX; + mdio_phy = GSWIP_MDIO_PHY_FCONTX_EN | + GSWIP_MDIO_PHY_FCONRX_DIS; + } else if (rx_pause) { + mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_RX; + mdio_phy = GSWIP_MDIO_PHY_FCONTX_DIS | + GSWIP_MDIO_PHY_FCONRX_EN; + } else { + mac_ctrl_0 = GSWIP_MAC_CTRL_0_FCON_NONE; + mdio_phy = GSWIP_MDIO_PHY_FCONTX_DIS | + GSWIP_MDIO_PHY_FCONRX_DIS; + } + + gswip_switch_mask(priv, GSWIP_MAC_CTRL_0_FCON_MASK, + mac_ctrl_0, GSWIP_MAC_CTRL_0p(port)); + gswip_mdio_mask(priv, + GSWIP_MDIO_PHY_FCONTX_MASK | + GSWIP_MDIO_PHY_FCONRX_MASK, + mdio_phy, GSWIP_MDIO_PHYp(port)); +} + static void gswip_phylink_mac_config(struct dsa_switch *ds, int port, unsigned int mode, const struct phylink_link_state *state) @@ -1511,6 +1634,9 @@ static void gswip_phylink_mac_link_down(struct dsa_switch *ds, int port, struct gswip_priv *priv = ds->priv; gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, port); + + if (!dsa_is_cpu_port(ds, port)) + gswip_port_set_link(priv, port, false); } static void gswip_phylink_mac_link_up(struct dsa_switch *ds, int port, @@ -1522,6 +1648,13 @@ static void gswip_phylink_mac_link_up(struct dsa_switch *ds, int port, { struct gswip_priv *priv = ds->priv; + if (!dsa_is_cpu_port(ds, port)) { + gswip_port_set_link(priv, port, true); + gswip_port_set_speed(priv, port, speed, interface); + gswip_port_set_duplex(priv, port, duplex); + gswip_port_set_pause(priv, port, tx_pause, rx_pause); + } + gswip_mii_mask_cfg(priv, 0, GSWIP_MII_CFG_EN, port); } From 4b5923249b8fa427943b50b8f35265176472be38 Mon Sep 17 00:00:00 2001 From: Martin Blumenstingl Date: Thu, 8 Apr 2021 20:38:28 +0200 Subject: [PATCH 0848/1091] net: dsa: lantiq_gswip: Configure all remaining GSWIP_MII_CFG bits There are a few more bits in the GSWIP_MII_CFG register for which we did rely on the boot-loader (or the hardware defaults) to set them up properly. For some external RMII PHYs we need to select the GSWIP_MII_CFG_RMII_CLK bit and also we should un-set it for non-RMII PHYs. The GSWIP_MII_CFG_RMII_CLK bit is ignored for other PHY connection modes. The GSWIP IP also supports in-band auto-negotiation for RGMII PHYs when the GSWIP_MII_CFG_RGMII_IBS bit is set. Clear this bit always as there's no known hardware which uses this (so it is not tested yet). Clear the xMII isolation bit when set at initialization time if it was previously set by the bootloader. Not doing so could lead to no traffic (neither RX nor TX) on a port with this bit set. While here, also add the GSWIP_MII_CFG_RESET bit. We don't need to manage it because this bit is self-clearning when set. We still add it here to get a better overview of the GSWIP_MII_CFG register. Fixes: 14fceff4771e51 ("net: dsa: Add Lantiq / Intel DSA driver for vrx200") Cc: stable@vger.kernel.org Suggested-by: Hauke Mehrtens Acked-by: Hauke Mehrtens Signed-off-by: Martin Blumenstingl Reviewed-by: Florian Fainelli Signed-off-by: David S. Miller --- drivers/net/dsa/lantiq_gswip.c | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/lantiq_gswip.c b/drivers/net/dsa/lantiq_gswip.c index 126d4ea868ba..bf5c62e5c0b0 100644 --- a/drivers/net/dsa/lantiq_gswip.c +++ b/drivers/net/dsa/lantiq_gswip.c @@ -93,8 +93,12 @@ /* GSWIP MII Registers */ #define GSWIP_MII_CFGp(p) (0x2 * (p)) +#define GSWIP_MII_CFG_RESET BIT(15) #define GSWIP_MII_CFG_EN BIT(14) +#define GSWIP_MII_CFG_ISOLATE BIT(13) #define GSWIP_MII_CFG_LDCLKDIS BIT(12) +#define GSWIP_MII_CFG_RGMII_IBS BIT(8) +#define GSWIP_MII_CFG_RMII_CLK BIT(7) #define GSWIP_MII_CFG_MODE_MIIP 0x0 #define GSWIP_MII_CFG_MODE_MIIM 0x1 #define GSWIP_MII_CFG_MODE_RMIIP 0x2 @@ -821,9 +825,11 @@ static int gswip_setup(struct dsa_switch *ds) /* Configure the MDIO Clock 2.5 MHz */ gswip_mdio_mask(priv, 0xff, 0x09, GSWIP_MDIO_MDC_CFG1); - /* Disable the xMII link */ + /* Disable the xMII interface and clear it's isolation bit */ for (i = 0; i < priv->hw_info->max_ports; i++) - gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_EN, 0, i); + gswip_mii_mask_cfg(priv, + GSWIP_MII_CFG_EN | GSWIP_MII_CFG_ISOLATE, + 0, i); /* enable special tag insertion on cpu port */ gswip_switch_mask(priv, 0, GSWIP_FDMA_PCTRL_STEN, @@ -1597,6 +1603,9 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port, break; case PHY_INTERFACE_MODE_RMII: miicfg |= GSWIP_MII_CFG_MODE_RMIIM; + + /* Configure the RMII clock as output: */ + miicfg |= GSWIP_MII_CFG_RMII_CLK; break; case PHY_INTERFACE_MODE_RGMII: case PHY_INTERFACE_MODE_RGMII_ID: @@ -1609,7 +1618,11 @@ static void gswip_phylink_mac_config(struct dsa_switch *ds, int port, "Unsupported interface: %d\n", state->interface); return; } - gswip_mii_mask_cfg(priv, GSWIP_MII_CFG_MODE_MASK, miicfg, port); + + gswip_mii_mask_cfg(priv, + GSWIP_MII_CFG_MODE_MASK | GSWIP_MII_CFG_RMII_CLK | + GSWIP_MII_CFG_RGMII_IBS | GSWIP_MII_CFG_LDCLKDIS, + miicfg, port); switch (state->interface) { case PHY_INTERFACE_MODE_RGMII_ID: From 864db232dc7036aa2de19749c3d5be0143b24f8f Mon Sep 17 00:00:00 2001 From: Muhammad Usama Anjum Date: Fri, 9 Apr 2021 03:01:29 +0500 Subject: [PATCH 0849/1091] net: ipv6: check for validity before dereferencing cfg->fc_nlinfo.nlh nlh is being checked for validtity two times when it is dereferenced in this function. Check for validity again when updating the flags through nlh pointer to make the dereferencing safe. CC: Addresses-Coverity: ("NULL pointer dereference") Signed-off-by: Muhammad Usama Anjum Signed-off-by: David S. Miller --- net/ipv6/route.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/net/ipv6/route.c b/net/ipv6/route.c index 1056b0229ffd..373d48073106 100644 --- a/net/ipv6/route.c +++ b/net/ipv6/route.c @@ -5209,9 +5209,11 @@ static int ip6_route_multipath_add(struct fib6_config *cfg, * nexthops have been replaced by first new, the rest should * be added to it. */ - cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | - NLM_F_REPLACE); - cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE; + if (cfg->fc_nlinfo.nlh) { + cfg->fc_nlinfo.nlh->nlmsg_flags &= ~(NLM_F_EXCL | + NLM_F_REPLACE); + cfg->fc_nlinfo.nlh->nlmsg_flags |= NLM_F_CREATE; + } nhn++; } From 2361db89aaadfb671db6911b0063e01ec8922c28 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Tue, 9 Mar 2021 17:43:38 -0800 Subject: [PATCH 0850/1091] libnvdimm: Notify disk drivers to revalidate region read-only Previous kernels allowed the BLKROSET to override the disk's read-only status. With that situation fixed the pmem driver needs to rely on notification events to reevaluate the disk read-only status after the host region has been marked read-write. Recall that when libnvdimm determines that the persistent memory has lost persistence (for example lack of energy to flush from DRAM to FLASH on an NVDIMM-N device) it marks the region read-only, but that state can be overridden by the user via: echo 0 > /sys/bus/nd/devices/regionX/read_only ...to date there is no notification that the region has restored persistence, so the user override is the only recovery. Fixes: 52f019d43c22 ("block: add a hard-readonly flag to struct gendisk") Reported-by: kernel test robot Reported-by: Vishal Verma Tested-by: Vishal Verma Reviewed-by: Christoph Hellwig Cc: Christoph Hellwig Cc: Ming Lei Cc: Martin K. Petersen Cc: Hannes Reinecke Cc: Jens Axboe Link: https://lore.kernel.org/r/161534060720.528671.2341213328968989192.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams --- drivers/nvdimm/bus.c | 14 ++++++-------- drivers/nvdimm/pmem.c | 37 ++++++++++++++++++++++++++++++++---- drivers/nvdimm/region_devs.c | 7 +++++++ include/linux/nd.h | 1 + 4 files changed, 47 insertions(+), 12 deletions(-) diff --git a/drivers/nvdimm/bus.c b/drivers/nvdimm/bus.c index 48f0985ca8a0..3a777d0073b7 100644 --- a/drivers/nvdimm/bus.c +++ b/drivers/nvdimm/bus.c @@ -631,16 +631,14 @@ void nvdimm_check_and_set_ro(struct gendisk *disk) struct nd_region *nd_region = to_nd_region(dev->parent); int disk_ro = get_disk_ro(disk); - /* - * Upgrade to read-only if the region is read-only preserve as - * read-only if the disk is already read-only. - */ - if (disk_ro || nd_region->ro == disk_ro) + /* catch the disk up with the region ro state */ + if (disk_ro == nd_region->ro) return; - dev_info(dev, "%s read-only, marking %s read-only\n", - dev_name(&nd_region->dev), disk->disk_name); - set_disk_ro(disk, 1); + dev_info(dev, "%s read-%s, marking %s read-%s\n", + dev_name(&nd_region->dev), nd_region->ro ? "only" : "write", + disk->disk_name, nd_region->ro ? "only" : "write"); + set_disk_ro(disk, nd_region->ro); } EXPORT_SYMBOL(nvdimm_check_and_set_ro); diff --git a/drivers/nvdimm/pmem.c b/drivers/nvdimm/pmem.c index b8a85bfb2e95..7daac795db39 100644 --- a/drivers/nvdimm/pmem.c +++ b/drivers/nvdimm/pmem.c @@ -26,6 +26,7 @@ #include #include #include "pmem.h" +#include "btt.h" #include "pfn.h" #include "nd.h" @@ -585,7 +586,7 @@ static void nd_pmem_shutdown(struct device *dev) nvdimm_flush(to_nd_region(dev->parent), NULL); } -static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) +static void pmem_revalidate_poison(struct device *dev) { struct nd_region *nd_region; resource_size_t offset = 0, end_trunc = 0; @@ -595,9 +596,6 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) struct range range; struct kernfs_node *bb_state; - if (event != NVDIMM_REVALIDATE_POISON) - return; - if (is_nd_btt(dev)) { struct nd_btt *nd_btt = to_nd_btt(dev); @@ -635,6 +633,37 @@ static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) sysfs_notify_dirent(bb_state); } +static void pmem_revalidate_region(struct device *dev) +{ + struct pmem_device *pmem; + + if (is_nd_btt(dev)) { + struct nd_btt *nd_btt = to_nd_btt(dev); + struct btt *btt = nd_btt->btt; + + nvdimm_check_and_set_ro(btt->btt_disk); + return; + } + + pmem = dev_get_drvdata(dev); + nvdimm_check_and_set_ro(pmem->disk); +} + +static void nd_pmem_notify(struct device *dev, enum nvdimm_event event) +{ + switch (event) { + case NVDIMM_REVALIDATE_POISON: + pmem_revalidate_poison(dev); + break; + case NVDIMM_REVALIDATE_REGION: + pmem_revalidate_region(dev); + break; + default: + dev_WARN_ONCE(dev, 1, "notify: unknown event: %d\n", event); + break; + } +} + MODULE_ALIAS("pmem"); MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_IO); MODULE_ALIAS_ND_DEVICE(ND_DEVICE_NAMESPACE_PMEM); diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index ef23119db574..51870eb51da6 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -518,6 +518,12 @@ static ssize_t read_only_show(struct device *dev, return sprintf(buf, "%d\n", nd_region->ro); } +static int revalidate_read_only(struct device *dev, void *data) +{ + nd_device_notify(dev, NVDIMM_REVALIDATE_REGION); + return 0; +} + static ssize_t read_only_store(struct device *dev, struct device_attribute *attr, const char *buf, size_t len) { @@ -529,6 +535,7 @@ static ssize_t read_only_store(struct device *dev, return rc; nd_region->ro = ro; + device_for_each_child(dev, NULL, revalidate_read_only); return len; } static DEVICE_ATTR_RW(read_only); diff --git a/include/linux/nd.h b/include/linux/nd.h index cec526c8043d..ee9ad76afbba 100644 --- a/include/linux/nd.h +++ b/include/linux/nd.h @@ -11,6 +11,7 @@ enum nvdimm_event { NVDIMM_REVALIDATE_POISON, + NVDIMM_REVALIDATE_REGION, }; enum nvdimm_claim_class { From 632a1c209b8773cb0119fe3aada9f1db14fa357c Mon Sep 17 00:00:00 2001 From: Thomas Tai Date: Thu, 8 Apr 2021 13:28:33 -0400 Subject: [PATCH 0851/1091] x86/traps: Correct exc_general_protection() and math_error() return paths Commit 334872a09198 ("x86/traps: Attempt to fixup exceptions in vDSO before signaling") added return statements which bypass calling cond_local_irq_disable(). According to ca4c6a9858c2 ("x86/traps: Make interrupt enable/disable symmetric in C code"), cond_local_irq_disable() is needed because the asm return code no longer disables interrupts. Follow the existing code as an example to use "goto exit" instead of "return" statement. [ bp: Massage commit message. ] Fixes: 334872a09198 ("x86/traps: Attempt to fixup exceptions in vDSO before signaling") Signed-off-by: Thomas Tai Signed-off-by: Borislav Petkov Reviewed-by: Alexandre Chartre Link: https://lkml.kernel.org/r/1617902914-83245-1-git-send-email-thomas.tai@oracle.com --- arch/x86/kernel/traps.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index ac1874a2a70e..651e3e508959 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -556,7 +556,7 @@ DEFINE_IDTENTRY_ERRORCODE(exc_general_protection) tsk->thread.trap_nr = X86_TRAP_GP; if (fixup_vdso_exception(regs, X86_TRAP_GP, error_code, 0)) - return; + goto exit; show_signal(tsk, SIGSEGV, "", desc, regs, error_code); force_sig(SIGSEGV); @@ -1057,7 +1057,7 @@ static void math_error(struct pt_regs *regs, int trapnr) goto exit; if (fixup_vdso_exception(regs, trapnr, 0, 0)) - return; + goto exit; force_sig_fault(SIGFPE, si_code, (void __user *)uprobe_get_trap_addr(regs)); From 3e075e842899779bd321520a3524a278442467d0 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:51 +0800 Subject: [PATCH 0852/1091] ASoC: amd: raven: acp3x-i2s: Constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062651.803413-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-i2s.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index 5bc028692fcf..396cb7d619e2 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -249,7 +249,7 @@ static int acp3x_i2s_trigger(struct snd_pcm_substream *substream, return ret; } -static struct snd_soc_dai_ops acp3x_i2s_dai_ops = { +static const struct snd_soc_dai_ops acp3x_i2s_dai_ops = { .hw_params = acp3x_i2s_hwparams, .trigger = acp3x_i2s_trigger, .set_fmt = acp3x_i2s_set_fmt, From 45475bf60cc1d42da229a0aa757180c88bab8d22 Mon Sep 17 00:00:00 2001 From: Gyeongtaek Lee Date: Wed, 7 Apr 2021 13:14:04 +0900 Subject: [PATCH 0853/1091] ASoC: soc-compress: lock pcm_mutex to resolve lockdep error If panic_on_warn=1 is added in bootargs and compress offload playback with DPCM is started, kernel panic would be occurred because rtd->card->pcm_mutex isn't held in soc_compr_open_fe() and soc_compr_free_fe() and it generates lockdep warning in the following code. void snd_soc_runtime_action(struct snd_soc_pcm_runtime *rtd, int stream, int action) { struct snd_soc_dai *dai; int i; lockdep_assert_held(&rtd->card->pcm_mutex); To prevent lockdep warning but minimize side effect by adding mutex, pcm_mutex is held just before snd_soc_runtime_activate() and snd_soc_runtime_deactivate() and is released right after them. Signed-off-by: Gyeongtaek Lee Link: https://lore.kernel.org/r/1891546521.01617772502282.JavaMail.epsvc@epcpadp3 Signed-off-by: Mark Brown --- sound/soc/soc-compress.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/sound/soc/soc-compress.c b/sound/soc/soc-compress.c index 83b511f8b8c9..b4f59350a5a8 100644 --- a/sound/soc/soc-compress.c +++ b/sound/soc/soc-compress.c @@ -151,7 +151,9 @@ static int soc_compr_open_fe(struct snd_compr_stream *cstream) fe->dpcm[stream].state = SND_SOC_DPCM_STATE_OPEN; fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_NO; + mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); snd_soc_runtime_activate(fe, stream); + mutex_unlock(&fe->card->pcm_mutex); mutex_unlock(&fe->card->mutex); @@ -178,7 +180,9 @@ static int soc_compr_free_fe(struct snd_compr_stream *cstream) mutex_lock_nested(&fe->card->mutex, SND_SOC_CARD_CLASS_RUNTIME); + mutex_lock_nested(&fe->card->pcm_mutex, fe->card->pcm_subclass); snd_soc_runtime_deactivate(fe, stream); + mutex_unlock(&fe->card->pcm_mutex); fe->dpcm[stream].runtime_update = SND_SOC_DPCM_UPDATE_FE; From 857b602a3424a7d9ef875f8f137ddcb68de41c6f Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:50 +0800 Subject: [PATCH 0854/1091] ASoC: codecs: lpass-rx-macro: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062650.803309-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index c0f7b5ecbf9e..14c166506fb1 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -1767,7 +1767,7 @@ static int rx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) return 0; } -static struct snd_soc_dai_ops rx_macro_dai_ops = { +static const struct snd_soc_dai_ops rx_macro_dai_ops = { .hw_params = rx_macro_hw_params, .get_channel_map = rx_macro_get_channel_map, .mute_stream = rx_macro_digital_mute, From a457dd92d14acdf3dd64285f04ed9225d14d195a Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:53 +0800 Subject: [PATCH 0855/1091] ASoC: Intel: KMB: Constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062653.803478-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/intel/keembay/kmb_platform.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 0fd1e8f62c89..ef73392f8cff 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -729,7 +729,7 @@ static int kmb_dai_hw_free(struct snd_pcm_substream *substream, return 0; } -static struct snd_soc_dai_ops kmb_dai_ops = { +static const struct snd_soc_dai_ops kmb_dai_ops = { .startup = kmb_dai_startup, .trigger = kmb_dai_trigger, .hw_params = kmb_dai_hw_params, From 1f34084cc85d654a542c547df6714dae8a32d3c9 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:54 +0800 Subject: [PATCH 0856/1091] ASoC: rt715-sdca: Constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062654.803538-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715-sdca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt715-sdca.c b/sound/soc/codecs/rt715-sdca.c index 20528afbdc57..7db76c19e048 100644 --- a/sound/soc/codecs/rt715-sdca.c +++ b/sound/soc/codecs/rt715-sdca.c @@ -935,7 +935,7 @@ static int rt715_sdca_pcm_hw_free(struct snd_pcm_substream *substream, #define RT715_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE | SNDRV_PCM_FMTBIT_S8) -static struct snd_soc_dai_ops rt715_sdca_ops = { +static const struct snd_soc_dai_ops rt715_sdca_ops = { .hw_params = rt715_sdca_pcm_hw_params, .hw_free = rt715_sdca_pcm_hw_free, .set_sdw_stream = rt715_sdca_set_sdw_stream, From e994cf82689465ddae2dfa9c9bc69616a0003649 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:48 +0800 Subject: [PATCH 0857/1091] ASoC: wcd934x: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062648.803227-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 2c4818dc2e6d..5fe403307b72 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -1946,7 +1946,7 @@ static int wcd934x_get_channel_map(struct snd_soc_dai *dai, return 0; } -static struct snd_soc_dai_ops wcd934x_dai_ops = { +static const struct snd_soc_dai_ops wcd934x_dai_ops = { .hw_params = wcd934x_hw_params, .hw_free = wcd934x_hw_free, .trigger = wcd934x_trigger, From 3cab801e8b94280264ba23ab0683cd3a9c13ca9f Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:47 +0800 Subject: [PATCH 0858/1091] ASoC: rt711-sdca: Constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062647.803141-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 381893b640c6..bfb7f1c8ec8f 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -1268,7 +1268,7 @@ static int rt711_sdca_pcm_hw_free(struct snd_pcm_substream *substream, #define RT711_FORMATS (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S20_3LE | \ SNDRV_PCM_FMTBIT_S24_LE) -static struct snd_soc_dai_ops rt711_sdca_ops = { +static const struct snd_soc_dai_ops rt711_sdca_ops = { .hw_params = rt711_sdca_pcm_hw_params, .hw_free = rt711_sdca_pcm_hw_free, .set_sdw_stream = rt711_sdca_set_sdw_stream, From 4f3b0f8e364029f2674875396f0e65a98ef84498 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Fri, 9 Apr 2021 08:52:29 +0000 Subject: [PATCH 0859/1091] ASoC: rt1019: remove registers to sync with rt1019 datasheet Remove some registers to synchronize with the latest rt1019 datasheet. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/01e6409f0db0451aa1e45ca7d82cca9c@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1019.c | 334 +------------------------------------- sound/soc/codecs/rt1019.h | 162 ------------------ 2 files changed, 1 insertion(+), 495 deletions(-) diff --git a/sound/soc/codecs/rt1019.c b/sound/soc/codecs/rt1019.c index f64bb7302720..10656a5927f1 100644 --- a/sound/soc/codecs/rt1019.c +++ b/sound/soc/codecs/rt1019.c @@ -32,210 +32,40 @@ static const struct reg_default rt1019_reg[] = { { 0x0000, 0x00 }, - { 0x0002, 0x55 }, - { 0x0003, 0x55 }, - { 0x0005, 0x54 }, - { 0x0006, 0x05 }, - { 0x0007, 0x01 }, - { 0x0008, 0x70 }, - { 0x0009, 0x28 }, - { 0x000a, 0x7f }, { 0x0011, 0x04 }, { 0x0013, 0x00 }, - { 0x0015, 0x00 }, - { 0x0017, 0x00 }, { 0x0019, 0x30 }, { 0x001b, 0x01 }, - { 0x001d, 0x18 }, - { 0x001f, 0x29 }, - { 0x0021, 0x09 }, - { 0x0023, 0x02 }, - { 0x0025, 0x00 }, - { 0x0026, 0x00 }, - { 0x0028, 0x03 }, - { 0x0053, 0x00 }, - { 0x0055, 0x00 }, - { 0x0056, 0x00 }, - { 0x0057, 0x00 }, - { 0x0058, 0x00 }, - { 0x005a, 0x00 }, { 0x005c, 0x00 }, - { 0x005d, 0x00 }, { 0x005e, 0x10 }, { 0x005f, 0xec }, { 0x0061, 0x10 }, { 0x0062, 0x19 }, - { 0x0064, 0x00 }, { 0x0066, 0x08 }, - { 0x0068, 0x00 }, - { 0x006a, 0x00 }, - { 0x006c, 0x00 }, - { 0x006e, 0x00 }, { 0x0100, 0x80 }, { 0x0100, 0x51 }, { 0x0102, 0x23 }, - { 0x0102, 0x0f }, - { 0x0104, 0x6c }, - { 0x0105, 0xec }, - { 0x0106, 0x00 }, - { 0x0107, 0x00 }, - { 0x0108, 0x00 }, - { 0x0200, 0x40 }, - { 0x0201, 0x00 }, - { 0x0202, 0x00 }, - { 0x0203, 0x00 }, - { 0x0301, 0x02 }, - { 0x0302, 0xaa }, - { 0x0303, 0x2a }, - { 0x0304, 0x6a }, - { 0x0306, 0xb0 }, - { 0x0308, 0x48 }, - { 0x030a, 0x0a }, - { 0x030b, 0x4b }, - { 0x030d, 0x7d }, - { 0x030e, 0xef }, - { 0x030f, 0x5a }, { 0x0311, 0x00 }, { 0x0312, 0x3e }, { 0x0313, 0x86 }, - { 0x0315, 0xa8 }, - { 0x0318, 0x1b }, - { 0x031a, 0x3d }, - { 0x031c, 0x40 }, - { 0x031d, 0x40 }, - { 0x031e, 0x30 }, - { 0x031f, 0xbb }, - { 0x0320, 0xa5 }, - { 0x0321, 0xa5 }, - { 0x0323, 0x5a }, - { 0x0324, 0xaa }, - { 0x0325, 0x80 }, - { 0x0326, 0xaa }, - { 0x0327, 0x66 }, - { 0x0328, 0x94 }, - { 0x0329, 0x00 }, - { 0x0330, 0x00 }, - { 0x0331, 0x30 }, - { 0x0332, 0x05 }, { 0x0400, 0x03 }, { 0x0401, 0x02 }, { 0x0402, 0x01 }, - { 0x0403, 0x23 }, - { 0x0404, 0x45 }, - { 0x0405, 0x67 }, - { 0x0500, 0x80 }, - { 0x0501, 0x00 }, - { 0x0502, 0x00 }, - { 0x0503, 0x00 }, { 0x0504, 0xff }, { 0x0505, 0x24 }, - { 0x0600, 0x75 }, - { 0x0601, 0x41 }, - { 0x0602, 0x60 }, - { 0x0603, 0x7f }, - { 0x0604, 0x65 }, - { 0x0605, 0x43 }, - { 0x0606, 0x00 }, - { 0x0607, 0x00 }, - { 0x0608, 0x00 }, - { 0x0609, 0x00 }, - { 0x060a, 0x00 }, - { 0x060b, 0x00 }, - { 0x060c, 0x00 }, - { 0x060d, 0x00 }, - { 0x060e, 0x00 }, - { 0x060f, 0x00 }, - { 0x0700, 0x15 }, - { 0x0701, 0xc8 }, - { 0x0704, 0x02 }, - { 0x0705, 0x00 }, - { 0x0706, 0x00 }, - { 0x0707, 0x80 }, - { 0x0708, 0x08 }, - { 0x0709, 0x00 }, - { 0x0800, 0x00 }, - { 0x0801, 0x00 }, - { 0x0802, 0x09 }, - { 0x0803, 0x00 }, - { 0x0900, 0x87 }, - { 0x0a01, 0x99 }, - { 0x0a02, 0x40 }, - { 0x0a03, 0x10 }, { 0x0b00, 0x50 }, { 0x0b01, 0xc3 }, - { 0x0c00, 0x84 }, - { 0x0c01, 0x00 }, - { 0x0c02, 0xbb }, - { 0x0c03, 0x80 }, - { 0x0c04, 0x10 }, - { 0x0c05, 0x30 }, - { 0x0c06, 0x00 }, - { 0x0d00, 0x80 }, - { 0x0d01, 0xbb }, - { 0x0d02, 0x80 }, - { 0x0d03, 0x00 }, - { 0x0d04, 0x00 }, - { 0x0d05, 0x00 }, - { 0x0e00, 0x80 }, - { 0x0e01, 0xbb }, - { 0x0e02, 0x80 }, - { 0x0e03, 0x00 }, - { 0x0e04, 0x10 }, - { 0x0e05, 0x30 }, - { 0x0f00, 0x80 }, - { 0x0f01, 0xbb }, - { 0x0f02, 0x80 }, - { 0x0f03, 0x00 }, - { 0x0f04, 0x10 }, - { 0x0f05, 0x30 }, - { 0x0f06, 0x88 }, - { 0x0f07, 0x88 }, - { 0x0f08, 0x00 }, - { 0x0f09, 0x00 }, }; static bool rt1019_volatile_register(struct device *dev, unsigned int reg) { switch (reg) { - case RT1019_PWR_STRP_1: case RT1019_PWR_STRP_2: - case RT1019_SIL_DET_GAT: - case RT1019_PHASE_SYNC: - case RT1019_STAT_MACH_2: - case RT1019_FS_DET_1: - case RT1019_FS_DET_2: - case RT1019_FS_DET_3: - case RT1019_FS_DET_4: - case RT1019_FS_DET_5: - case RT1019_FS_DET_6: - case RT1019_FS_DET_7: - case RT1019_ANA_READ: case RT1019_VER_ID: - case RT1019_CUSTOM_ID: case RT1019_VEND_ID_1: case RT1019_VEND_ID_2: case RT1019_DEV_ID_1: case RT1019_DEV_ID_2: - case RT1019_CAL_TOP_3: - case RT1019_CAL_TOP_7: - case RT1019_CAL_TOP_17: - case RT1019_CAL_TOP_18: - case RT1019_CAL_TOP_19: - case RT1019_CAL_TOP_20: - case RT1019_CAL_TOP_21: - case RT1019_CAL_TOP_22: - case RT1019_MDRE_CTRL_2: - case RT1019_MDRE_CTRL_3: - case RT1019_MDRE_CTRL_4: - case RT1019_SIL_DET_2: - case RT1019_PWM_DC_DET_1: - case RT1019_PMC_8: - case RT1019_PMC_9: - case RT1019_SPKDRC_7: - case RT1019_HALF_FREQ_7: - case RT1019_CUR_CTRL_11: - case RT1019_CUR_CTRL_12: - case RT1019_CUR_CTRL_13: return true; default: @@ -247,191 +77,29 @@ static bool rt1019_readable_register(struct device *dev, unsigned int reg) { switch (reg) { case RT1019_RESET: - case RT1019_PAD_DRV_1: - case RT1019_PAD_DRV_2: - case RT1019_PAD_PULL_1: - case RT1019_PAD_PULL_2: - case RT1019_PAD_PULL_3: - case RT1019_I2C_CTRL_1: - case RT1019_I2C_CTRL_2: - case RT1019_I2C_CTRL_3: case RT1019_IDS_CTRL: case RT1019_ASEL_CTRL: - case RT1019_PLL_RESET: - case RT1019_PWR_STRP_1: case RT1019_PWR_STRP_2: case RT1019_BEEP_TONE: - case RT1019_SIL_DET_GAT: - case RT1019_CLASSD_TIME: - case RT1019_CLASSD_OCP: - case RT1019_PHASE_SYNC: - case RT1019_STAT_MACH_1: - case RT1019_STAT_MACH_2: - case RT1019_EFF_CTRL: - case RT1019_FS_DET_1: - case RT1019_FS_DET_2: - case RT1019_FS_DET_3: - case RT1019_FS_DET_4: - case RT1019_FS_DET_5: - case RT1019_FS_DET_6: - case RT1019_FS_DET_7: - case RT1019_ANA_CTRL: - case RT1019_DUMMY_A: - case RT1019_DUMMY_B: - case RT1019_DUMMY_C: - case RT1019_DUMMY_D: - case RT1019_ANA_READ: case RT1019_VER_ID: - case RT1019_CUSTOM_ID: case RT1019_VEND_ID_1: case RT1019_VEND_ID_2: case RT1019_DEV_ID_1: case RT1019_DEV_ID_2: - case RT1019_TEST_PAD: case RT1019_SDB_CTRL: - case RT1019_TEST_CTRL_1: - case RT1019_TEST_CTRL_2: - case RT1019_TEST_CTRL_3: - case RT1019_SCAN_MODE: case RT1019_CLK_TREE_1: case RT1019_CLK_TREE_2: case RT1019_CLK_TREE_3: - case RT1019_CLK_TREE_4: - case RT1019_CLK_TREE_5: - case RT1019_CLK_TREE_6: - case RT1019_CLK_TREE_7: - case RT1019_CLK_TREE_8: - case RT1019_CLK_TREE_9: - case RT1019_ASRC_1: - case RT1019_ASRC_2: - case RT1019_ASRC_3: - case RT1019_ASRC_4: - case RT1019_SYS_CLK: - case RT1019_BIAS_CUR_1: - case RT1019_BIAS_CUR_2: - case RT1019_BIAS_CUR_3: - case RT1019_BIAS_CUR_4: - case RT1019_CHOP_CLK_DAC: - case RT1019_CHOP_CLK_ADC: - case RT1019_LDO_CTRL_1: - case RT1019_LDO_CTRL_2: - case RT1019_PM_ANA_1: - case RT1019_PM_ANA_2: - case RT1019_PM_ANA_3: case RT1019_PLL_1: case RT1019_PLL_2: case RT1019_PLL_3: - case RT1019_PLL_INT_1: - case RT1019_PLL_INT_3: - case RT1019_MIXER: - case RT1019_CLD_OUT_1: - case RT1019_CLD_OUT_2: - case RT1019_CLD_OUT_3: - case RT1019_CLD_OUT_4: - case RT1019_CLD_OUT_5: - case RT1019_CLD_OUT_6: - case RT1019_CLS_INT_REG_1: - case RT1019_CLS_INT_REG_2: - case RT1019_CLS_INT_REG_3: - case RT1019_CLS_INT_REG_4: - case RT1019_CLS_INT_REG_5: - case RT1019_CLS_INT_REG_6: - case RT1019_CLS_INT_REG_7: - case RT1019_CLS_INT_REG_8: - case RT1019_CLS_INT_REG_9: - case RT1019_CLS_INT_REG_10: case RT1019_TDM_1: case RT1019_TDM_2: case RT1019_TDM_3: - case RT1019_TDM_4: - case RT1019_TDM_5: - case RT1019_TDM_6: - case RT1019_DVOL_1: - case RT1019_DVOL_2: - case RT1019_DVOL_3: - case RT1019_DVOL_4: case RT1019_DMIX_MONO_1: case RT1019_DMIX_MONO_2: - case RT1019_CAL_TOP_1: - case RT1019_CAL_TOP_2: - case RT1019_CAL_TOP_3: - case RT1019_CAL_TOP_4: - case RT1019_CAL_TOP_5: - case RT1019_CAL_TOP_6: - case RT1019_CAL_TOP_7: - case RT1019_CAL_TOP_8: - case RT1019_CAL_TOP_9: - case RT1019_CAL_TOP_10: - case RT1019_CAL_TOP_11: - case RT1019_CAL_TOP_12: - case RT1019_CAL_TOP_13: - case RT1019_CAL_TOP_14: - case RT1019_CAL_TOP_15: - case RT1019_CAL_TOP_16: - case RT1019_CAL_TOP_17: - case RT1019_CAL_TOP_18: - case RT1019_CAL_TOP_19: - case RT1019_CAL_TOP_20: - case RT1019_CAL_TOP_21: - case RT1019_CAL_TOP_22: - case RT1019_MDRE_CTRL_1: - case RT1019_MDRE_CTRL_2: - case RT1019_MDRE_CTRL_3: - case RT1019_MDRE_CTRL_4: - case RT1019_MDRE_CTRL_5: - case RT1019_MDRE_CTRL_6: - case RT1019_MDRE_CTRL_7: - case RT1019_MDRE_CTRL_8: - case RT1019_MDRE_CTRL_9: - case RT1019_MDRE_CTRL_10: - case RT1019_SCC_CTRL_1: - case RT1019_SCC_CTRL_2: - case RT1019_SCC_CTRL_3: - case RT1019_SCC_DUMMY: - case RT1019_SIL_DET_1: - case RT1019_SIL_DET_2: - case RT1019_PWM_DC_DET_1: - case RT1019_PWM_DC_DET_2: - case RT1019_PWM_DC_DET_3: - case RT1019_PWM_DC_DET_4: case RT1019_BEEP_1: case RT1019_BEEP_2: - case RT1019_PMC_1: - case RT1019_PMC_2: - case RT1019_PMC_3: - case RT1019_PMC_4: - case RT1019_PMC_5: - case RT1019_PMC_6: - case RT1019_PMC_7: - case RT1019_PMC_8: - case RT1019_PMC_9: - case RT1019_SPKDRC_1: - case RT1019_SPKDRC_2: - case RT1019_SPKDRC_3: - case RT1019_SPKDRC_4: - case RT1019_SPKDRC_5: - case RT1019_SPKDRC_6: - case RT1019_SPKDRC_7: - case RT1019_HALF_FREQ_1: - case RT1019_HALF_FREQ_2: - case RT1019_HALF_FREQ_3: - case RT1019_HALF_FREQ_4: - case RT1019_HALF_FREQ_5: - case RT1019_HALF_FREQ_6: - case RT1019_HALF_FREQ_7: - case RT1019_CUR_CTRL_1: - case RT1019_CUR_CTRL_2: - case RT1019_CUR_CTRL_3: - case RT1019_CUR_CTRL_4: - case RT1019_CUR_CTRL_5: - case RT1019_CUR_CTRL_6: - case RT1019_CUR_CTRL_7: - case RT1019_CUR_CTRL_8: - case RT1019_CUR_CTRL_9: - case RT1019_CUR_CTRL_10: - case RT1019_CUR_CTRL_11: - case RT1019_CUR_CTRL_12: - case RT1019_CUR_CTRL_13: return true; default: return false; @@ -861,7 +529,7 @@ static const struct regmap_config rt1019_regmap = { .val_bits = 8, .use_single_read = true, .use_single_write = true, - .max_register = RT1019_CUR_CTRL_13, + .max_register = RT1019_BEEP_2, .volatile_reg = rt1019_volatile_register, .readable_reg = rt1019_readable_register, .cache_type = REGCACHE_RBTREE, diff --git a/sound/soc/codecs/rt1019.h b/sound/soc/codecs/rt1019.h index 46973e71c963..64df831eeb72 100644 --- a/sound/soc/codecs/rt1019.h +++ b/sound/soc/codecs/rt1019.h @@ -12,191 +12,29 @@ #define RT1019_DEVICE_ID_VAL2 0x6731 #define RT1019_RESET 0x0000 -#define RT1019_PAD_DRV_1 0x0002 -#define RT1019_PAD_DRV_2 0x0003 -#define RT1019_PAD_PULL_1 0x0005 -#define RT1019_PAD_PULL_2 0x0006 -#define RT1019_PAD_PULL_3 0x0007 -#define RT1019_I2C_CTRL_1 0x0008 -#define RT1019_I2C_CTRL_2 0x0009 -#define RT1019_I2C_CTRL_3 0x000a #define RT1019_IDS_CTRL 0x0011 #define RT1019_ASEL_CTRL 0x0013 -#define RT1019_PLL_RESET 0x0015 -#define RT1019_PWR_STRP_1 0x0017 #define RT1019_PWR_STRP_2 0x0019 #define RT1019_BEEP_TONE 0x001b -#define RT1019_SIL_DET_GAT 0x001d -#define RT1019_CLASSD_TIME 0x001f -#define RT1019_CLASSD_OCP 0x0021 -#define RT1019_PHASE_SYNC 0x0023 -#define RT1019_STAT_MACH_1 0x0025 -#define RT1019_STAT_MACH_2 0x0026 -#define RT1019_EFF_CTRL 0x0028 -#define RT1019_FS_DET_1 0x002a -#define RT1019_FS_DET_2 0x002b -#define RT1019_FS_DET_3 0x002c -#define RT1019_FS_DET_4 0x002d -#define RT1019_FS_DET_5 0x002e -#define RT1019_FS_DET_6 0x002f -#define RT1019_FS_DET_7 0x0030 -#define RT1019_ANA_CTRL 0x0053 -#define RT1019_DUMMY_A 0x0055 -#define RT1019_DUMMY_B 0x0056 -#define RT1019_DUMMY_C 0x0057 -#define RT1019_DUMMY_D 0x0058 -#define RT1019_ANA_READ 0x005a #define RT1019_VER_ID 0x005c -#define RT1019_CUSTOM_ID 0x005d #define RT1019_VEND_ID_1 0x005e #define RT1019_VEND_ID_2 0x005f #define RT1019_DEV_ID_1 0x0061 #define RT1019_DEV_ID_2 0x0062 -#define RT1019_TEST_PAD 0x0064 #define RT1019_SDB_CTRL 0x0066 -#define RT1019_TEST_CTRL_1 0x0068 -#define RT1019_TEST_CTRL_2 0x006a -#define RT1019_TEST_CTRL_3 0x006c -#define RT1019_SCAN_MODE 0x006e #define RT1019_CLK_TREE_1 0x0100 #define RT1019_CLK_TREE_2 0x0101 #define RT1019_CLK_TREE_3 0x0102 -#define RT1019_CLK_TREE_4 0x0103 -#define RT1019_CLK_TREE_5 0x0104 -#define RT1019_CLK_TREE_6 0x0105 -#define RT1019_CLK_TREE_7 0x0106 -#define RT1019_CLK_TREE_8 0x0107 -#define RT1019_CLK_TREE_9 0x0108 -#define RT1019_ASRC_1 0x0200 -#define RT1019_ASRC_2 0x0201 -#define RT1019_ASRC_3 0x0202 -#define RT1019_ASRC_4 0x0203 -#define RT1019_SYS_CLK 0x0300 -#define RT1019_BIAS_CUR_1 0x0301 -#define RT1019_BIAS_CUR_2 0x0302 -#define RT1019_BIAS_CUR_3 0x0303 -#define RT1019_BIAS_CUR_4 0x0304 -#define RT1019_CHOP_CLK_DAC 0x0306 -#define RT1019_CHOP_CLK_ADC 0x0308 -#define RT1019_LDO_CTRL_1 0x030a -#define RT1019_LDO_CTRL_2 0x030b -#define RT1019_PM_ANA_1 0x030d -#define RT1019_PM_ANA_2 0x030e -#define RT1019_PM_ANA_3 0x030f #define RT1019_PLL_1 0x0311 #define RT1019_PLL_2 0x0312 #define RT1019_PLL_3 0x0313 -#define RT1019_PLL_INT_1 0x0315 -#define RT1019_PLL_INT_3 0x0318 -#define RT1019_MIXER 0x031a -#define RT1019_CLD_OUT_1 0x031c -#define RT1019_CLD_OUT_2 0x031d -#define RT1019_CLD_OUT_3 0x031e -#define RT1019_CLD_OUT_4 0x031f -#define RT1019_CLD_OUT_5 0x0320 -#define RT1019_CLD_OUT_6 0x0321 -#define RT1019_CLS_INT_REG_1 0x0323 -#define RT1019_CLS_INT_REG_2 0x0324 -#define RT1019_CLS_INT_REG_3 0x0325 -#define RT1019_CLS_INT_REG_4 0x0326 -#define RT1019_CLS_INT_REG_5 0x0327 -#define RT1019_CLS_INT_REG_6 0x0328 -#define RT1019_CLS_INT_REG_7 0x0329 -#define RT1019_CLS_INT_REG_8 0x0330 -#define RT1019_CLS_INT_REG_9 0x0331 -#define RT1019_CLS_INT_REG_10 0x0332 #define RT1019_TDM_1 0x0400 #define RT1019_TDM_2 0x0401 #define RT1019_TDM_3 0x0402 -#define RT1019_TDM_4 0x0403 -#define RT1019_TDM_5 0x0404 -#define RT1019_TDM_6 0x0405 -#define RT1019_DVOL_1 0x0500 -#define RT1019_DVOL_2 0x0501 -#define RT1019_DVOL_3 0x0502 -#define RT1019_DVOL_4 0x0503 #define RT1019_DMIX_MONO_1 0x0504 #define RT1019_DMIX_MONO_2 0x0505 -#define RT1019_CAL_TOP_1 0x0600 -#define RT1019_CAL_TOP_2 0x0601 -#define RT1019_CAL_TOP_3 0x0602 -#define RT1019_CAL_TOP_4 0x0603 -#define RT1019_CAL_TOP_5 0x0604 -#define RT1019_CAL_TOP_6 0x0605 -#define RT1019_CAL_TOP_7 0x0606 -#define RT1019_CAL_TOP_8 0x0607 -#define RT1019_CAL_TOP_9 0x0608 -#define RT1019_CAL_TOP_10 0x0609 -#define RT1019_CAL_TOP_11 0x060a -#define RT1019_CAL_TOP_12 0x060b -#define RT1019_CAL_TOP_13 0x060c -#define RT1019_CAL_TOP_14 0x060d -#define RT1019_CAL_TOP_15 0x060e -#define RT1019_CAL_TOP_16 0x060f -#define RT1019_CAL_TOP_17 0x0610 -#define RT1019_CAL_TOP_18 0x0611 -#define RT1019_CAL_TOP_19 0x0612 -#define RT1019_CAL_TOP_20 0x0613 -#define RT1019_CAL_TOP_21 0x0614 -#define RT1019_CAL_TOP_22 0x0615 -#define RT1019_MDRE_CTRL_1 0x0700 -#define RT1019_MDRE_CTRL_2 0x0701 -#define RT1019_MDRE_CTRL_3 0x0702 -#define RT1019_MDRE_CTRL_4 0x0703 -#define RT1019_MDRE_CTRL_5 0x0704 -#define RT1019_MDRE_CTRL_6 0x0705 -#define RT1019_MDRE_CTRL_7 0x0706 -#define RT1019_MDRE_CTRL_8 0x0707 -#define RT1019_MDRE_CTRL_9 0x0708 -#define RT1019_MDRE_CTRL_10 0x0709 -#define RT1019_SCC_CTRL_1 0x0800 -#define RT1019_SCC_CTRL_2 0x0801 -#define RT1019_SCC_CTRL_3 0x0802 -#define RT1019_SCC_DUMMY 0x0803 -#define RT1019_SIL_DET_1 0x0900 -#define RT1019_SIL_DET_2 0x0901 -#define RT1019_PWM_DC_DET_1 0x0a00 -#define RT1019_PWM_DC_DET_2 0x0a01 -#define RT1019_PWM_DC_DET_3 0x0a02 -#define RT1019_PWM_DC_DET_4 0x0a03 #define RT1019_BEEP_1 0x0b00 #define RT1019_BEEP_2 0x0b01 -#define RT1019_PMC_1 0x0c00 -#define RT1019_PMC_2 0x0c01 -#define RT1019_PMC_3 0x0c02 -#define RT1019_PMC_4 0x0c03 -#define RT1019_PMC_5 0x0c04 -#define RT1019_PMC_6 0x0c05 -#define RT1019_PMC_7 0x0c06 -#define RT1019_PMC_8 0x0c07 -#define RT1019_PMC_9 0x0c08 -#define RT1019_SPKDRC_1 0x0d00 -#define RT1019_SPKDRC_2 0x0d01 -#define RT1019_SPKDRC_3 0x0d02 -#define RT1019_SPKDRC_4 0x0d03 -#define RT1019_SPKDRC_5 0x0d04 -#define RT1019_SPKDRC_6 0x0d05 -#define RT1019_SPKDRC_7 0x0d06 -#define RT1019_HALF_FREQ_1 0x0e00 -#define RT1019_HALF_FREQ_2 0x0e01 -#define RT1019_HALF_FREQ_3 0x0e02 -#define RT1019_HALF_FREQ_4 0x0e03 -#define RT1019_HALF_FREQ_5 0x0e04 -#define RT1019_HALF_FREQ_6 0x0e05 -#define RT1019_HALF_FREQ_7 0x0e06 -#define RT1019_CUR_CTRL_1 0x0f00 -#define RT1019_CUR_CTRL_2 0x0f01 -#define RT1019_CUR_CTRL_3 0x0f02 -#define RT1019_CUR_CTRL_4 0x0f03 -#define RT1019_CUR_CTRL_5 0x0f04 -#define RT1019_CUR_CTRL_6 0x0f05 -#define RT1019_CUR_CTRL_7 0x0f06 -#define RT1019_CUR_CTRL_8 0x0f07 -#define RT1019_CUR_CTRL_9 0x0f08 -#define RT1019_CUR_CTRL_10 0x0f09 -#define RT1019_CUR_CTRL_11 0x0f0a -#define RT1019_CUR_CTRL_12 0x0f0b -#define RT1019_CUR_CTRL_13 0x0f0c /* 0x0019 Power On Strap Control-2 */ #define RT1019_AUTO_BITS_SEL_MASK (0x1 << 5) From a893a666b5b9a8c9d331df4afa72f23f4d4f83fd Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:42 +0800 Subject: [PATCH 0860/1091] ASoC: codecs: lpass-wsa-macro: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062642.802846-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-wsa-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index e37c8148c0de..e79a70386b4b 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -1031,7 +1031,7 @@ static int wsa_macro_get_channel_map(struct snd_soc_dai *dai, return 0; } -static struct snd_soc_dai_ops wsa_macro_dai_ops = { +static const struct snd_soc_dai_ops wsa_macro_dai_ops = { .hw_params = wsa_macro_hw_params, .get_channel_map = wsa_macro_get_channel_map, }; From 4150cc7306fa84577dd0c33f158949b0f085aea0 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:58 +0800 Subject: [PATCH 0861/1091] ASoC: amd: renoir: acp3x-pdm-dma: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062658.803724-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/amd/renoir/acp3x-pdm-dma.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/amd/renoir/acp3x-pdm-dma.c b/sound/soc/amd/renoir/acp3x-pdm-dma.c index 1acd20439399..4c2810e58dce 100644 --- a/sound/soc/amd/renoir/acp3x-pdm-dma.c +++ b/sound/soc/amd/renoir/acp3x-pdm-dma.c @@ -356,7 +356,7 @@ static int acp_pdm_dai_trigger(struct snd_pcm_substream *substream, return ret; } -static struct snd_soc_dai_ops acp_pdm_dai_ops = { +static const struct snd_soc_dai_ops acp_pdm_dai_ops = { .trigger = acp_pdm_dai_trigger, }; From 81df40a0807fed36f0f1f1eaeef2a780773934c2 Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:57 +0800 Subject: [PATCH 0862/1091] ASoC: codecs: lpass-tx-macro: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062657.803668-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-tx-macro.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/lpass-tx-macro.c b/sound/soc/codecs/lpass-tx-macro.c index 36d7a6442cdb..4eede9ad57bf 100644 --- a/sound/soc/codecs/lpass-tx-macro.c +++ b/sound/soc/codecs/lpass-tx-macro.c @@ -1124,7 +1124,7 @@ static int tx_macro_digital_mute(struct snd_soc_dai *dai, int mute, int stream) return 0; } -static struct snd_soc_dai_ops tx_macro_dai_ops = { +static const struct snd_soc_dai_ops tx_macro_dai_ops = { .hw_params = tx_macro_hw_params, .get_channel_map = tx_macro_get_channel_map, .mute_stream = tx_macro_digital_mute, From 33e12dea130d4b0abbaa9ae944e696d1a9d5261b Mon Sep 17 00:00:00 2001 From: Ye Bin Date: Thu, 8 Apr 2021 14:26:44 +0800 Subject: [PATCH 0863/1091] ASoC: wcd9335: constify static struct snd_soc_dai_ops The snd_soc_dai_ops structures is only stored in the ops field of a snd_soc_dai_driver structure, so make the snd_soc_dai_ops structure const to allow the compiler to put it in read-only memory. Reported-by: Hulk Robot Signed-off-by: Ye Bin Link: https://lore.kernel.org/r/20210408062644.802988-1-yebin10@huawei.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd9335.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd9335.c b/sound/soc/codecs/wcd9335.c index adb325fac930..86c92e03ea5d 100644 --- a/sound/soc/codecs/wcd9335.c +++ b/sound/soc/codecs/wcd9335.c @@ -2058,7 +2058,7 @@ static int wcd9335_get_channel_map(struct snd_soc_dai *dai, return 0; } -static struct snd_soc_dai_ops wcd9335_dai_ops = { +static const struct snd_soc_dai_ops wcd9335_dai_ops = { .hw_params = wcd9335_hw_params, .trigger = wcd9335_trigger, .set_channel_map = wcd9335_set_channel_map, From 0760fa3d8f7fceeea508b98899f1c826e10ffe78 Mon Sep 17 00:00:00 2001 From: Roman Gushchin Date: Wed, 7 Apr 2021 20:57:33 -0700 Subject: [PATCH 0864/1091] percpu: make pcpu_nr_empty_pop_pages per chunk type nr_empty_pop_pages is used to guarantee that there are some free populated pages to satisfy atomic allocations. Accounted and non-accounted allocations are using separate sets of chunks, so both need to have a surplus of empty pages. This commit makes pcpu_nr_empty_pop_pages and the corresponding logic per chunk type. [Dennis] This issue came up as I was reviewing [1] and realized I missed this. Simultaneously, it was reported btrfs was seeing failed atomic allocations in fsstress tests [2] and [3]. [1] https://lore.kernel.org/linux-mm/20210324190626.564297-1-guro@fb.com/ [2] https://lore.kernel.org/linux-mm/20210401185158.3275.409509F4@e16-tech.com/ [3] https://lore.kernel.org/linux-mm/CAL3q7H5RNBjCi708GH7jnczAOe0BLnacT9C+OBgA-Dx9jhB6SQ@mail.gmail.com/ Fixes: 3c7be18ac9a0 ("mm: memcg/percpu: account percpu memory to memory cgroups") Cc: stable@vger.kernel.org # 5.9+ Signed-off-by: Roman Gushchin Tested-by: Filipe Manana Signed-off-by: Dennis Zhou --- mm/percpu-internal.h | 2 +- mm/percpu-stats.c | 9 +++++++-- mm/percpu.c | 14 +++++++------- 3 files changed, 15 insertions(+), 10 deletions(-) diff --git a/mm/percpu-internal.h b/mm/percpu-internal.h index 18b768ac7dca..095d7eaa0db4 100644 --- a/mm/percpu-internal.h +++ b/mm/percpu-internal.h @@ -87,7 +87,7 @@ extern spinlock_t pcpu_lock; extern struct list_head *pcpu_chunk_lists; extern int pcpu_nr_slots; -extern int pcpu_nr_empty_pop_pages; +extern int pcpu_nr_empty_pop_pages[]; extern struct pcpu_chunk *pcpu_first_chunk; extern struct pcpu_chunk *pcpu_reserved_chunk; diff --git a/mm/percpu-stats.c b/mm/percpu-stats.c index c8400a2adbc2..f6026dbcdf6b 100644 --- a/mm/percpu-stats.c +++ b/mm/percpu-stats.c @@ -145,6 +145,7 @@ static int percpu_stats_show(struct seq_file *m, void *v) int slot, max_nr_alloc; int *buffer; enum pcpu_chunk_type type; + int nr_empty_pop_pages; alloc_buffer: spin_lock_irq(&pcpu_lock); @@ -165,7 +166,11 @@ alloc_buffer: goto alloc_buffer; } -#define PL(X) \ + nr_empty_pop_pages = 0; + for (type = 0; type < PCPU_NR_CHUNK_TYPES; type++) + nr_empty_pop_pages += pcpu_nr_empty_pop_pages[type]; + +#define PL(X) \ seq_printf(m, " %-20s: %12lld\n", #X, (long long int)pcpu_stats_ai.X) seq_printf(m, @@ -196,7 +201,7 @@ alloc_buffer: PU(nr_max_chunks); PU(min_alloc_size); PU(max_alloc_size); - P("empty_pop_pages", pcpu_nr_empty_pop_pages); + P("empty_pop_pages", nr_empty_pop_pages); seq_putc(m, '\n'); #undef PU diff --git a/mm/percpu.c b/mm/percpu.c index 6596a0a4286e..23308113a5ff 100644 --- a/mm/percpu.c +++ b/mm/percpu.c @@ -173,10 +173,10 @@ struct list_head *pcpu_chunk_lists __ro_after_init; /* chunk list slots */ static LIST_HEAD(pcpu_map_extend_chunks); /* - * The number of empty populated pages, protected by pcpu_lock. The - * reserved chunk doesn't contribute to the count. + * The number of empty populated pages by chunk type, protected by pcpu_lock. + * The reserved chunk doesn't contribute to the count. */ -int pcpu_nr_empty_pop_pages; +int pcpu_nr_empty_pop_pages[PCPU_NR_CHUNK_TYPES]; /* * The number of populated pages in use by the allocator, protected by @@ -556,7 +556,7 @@ static inline void pcpu_update_empty_pages(struct pcpu_chunk *chunk, int nr) { chunk->nr_empty_pop_pages += nr; if (chunk != pcpu_reserved_chunk) - pcpu_nr_empty_pop_pages += nr; + pcpu_nr_empty_pop_pages[pcpu_chunk_type(chunk)] += nr; } /* @@ -1832,7 +1832,7 @@ area_found: mutex_unlock(&pcpu_alloc_mutex); } - if (pcpu_nr_empty_pop_pages < PCPU_EMPTY_POP_PAGES_LOW) + if (pcpu_nr_empty_pop_pages[type] < PCPU_EMPTY_POP_PAGES_LOW) pcpu_schedule_balance_work(); /* clear the areas and return address relative to base address */ @@ -2000,7 +2000,7 @@ retry_pop: pcpu_atomic_alloc_failed = false; } else { nr_to_pop = clamp(PCPU_EMPTY_POP_PAGES_HIGH - - pcpu_nr_empty_pop_pages, + pcpu_nr_empty_pop_pages[type], 0, PCPU_EMPTY_POP_PAGES_HIGH); } @@ -2580,7 +2580,7 @@ void __init pcpu_setup_first_chunk(const struct pcpu_alloc_info *ai, /* link the first chunk in */ pcpu_first_chunk = chunk; - pcpu_nr_empty_pop_pages = pcpu_first_chunk->nr_empty_pop_pages; + pcpu_nr_empty_pop_pages[PCPU_CHUNK_ROOT] = pcpu_first_chunk->nr_empty_pop_pages; pcpu_chunk_relocate(pcpu_first_chunk, -1); /* include all regions of the first chunk */ From 895915226a598394fe9bf57fe97612bdfcb2fb86 Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Fri, 9 Apr 2021 15:58:50 +0200 Subject: [PATCH 0865/1091] Bluetooth: btusb: Revert Fix the autosuspend enable and disable drivers/usb/core/hub.c: usb_new_device() contains the following: /* By default, forbid autosuspend for all devices. It will be * allowed for hubs during binding. */ usb_disable_autosuspend(udev); So for anything which is not a hub, such as btusb devices, autosuspend is disabled by default and we must call usb_enable_autosuspend(udev) to enable it. This means that the "Fix the autosuspend enable and disable" commit, which drops the usb_enable_autosuspend() call when the enable_autosuspend module option is true, is completely wrong, revert it. This reverts commit 7bd9fb058d77213130e4b3e594115c028b708e7e. Cc: Hui Wang Fixes: 7bd9fb058d77 ("Bluetooth: btusb: Fix the autosuspend enable and disable") Acked-by: Hui Wang Acked-by: Marcel Holtmann Signed-off-by: Hans de Goede Signed-off-by: Linus Torvalds --- drivers/bluetooth/btusb.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/drivers/bluetooth/btusb.c b/drivers/bluetooth/btusb.c index 52683fd22e05..5cbfbd948f67 100644 --- a/drivers/bluetooth/btusb.c +++ b/drivers/bluetooth/btusb.c @@ -4849,8 +4849,8 @@ static int btusb_probe(struct usb_interface *intf, data->diag = NULL; } - if (!enable_autosuspend) - usb_disable_autosuspend(data->udev); + if (enable_autosuspend) + usb_enable_autosuspend(data->udev); err = hci_register_dev(hdev); if (err < 0) @@ -4910,9 +4910,6 @@ static void btusb_disconnect(struct usb_interface *intf) gpiod_put(data->reset_gpio); hci_free_dev(hdev); - - if (!enable_autosuspend) - usb_enable_autosuspend(data->udev); } #ifdef CONFIG_PM From d084d996aaf53c0cc583dc75a4fc2a67fe485846 Mon Sep 17 00:00:00 2001 From: Si-Wei Liu Date: Thu, 8 Apr 2021 12:10:43 +0300 Subject: [PATCH 0866/1091] vdpa/mlx5: should exclude header length and fcs from mtu When feature VIRTIO_NET_F_MTU is negotiated on mlx5_vdpa, 22 extra bytes worth of MTU length is shown in guest. This is because the mlx5_query_port_max_mtu API returns the "hardware" MTU value, which does not just contain the Ethernet payload, but includes extra lengths starting from the Ethernet header up to the FCS altogether. Fix the MTU so packets won't get dropped silently. Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for supported mlx5 devices") Signed-off-by: Si-Wei Liu Acked-by: Jason Wang Acked-by: Eli Cohen Link: https://lore.kernel.org/r/20210408091047.4269-2-elic@nvidia.com Signed-off-by: Michael S. Tsirkin --- drivers/vdpa/mlx5/core/mlx5_vdpa.h | 4 ++++ drivers/vdpa/mlx5/net/mlx5_vnet.c | 15 ++++++++++++++- 2 files changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/core/mlx5_vdpa.h b/drivers/vdpa/mlx5/core/mlx5_vdpa.h index 08f742fd2409..b6cc53ba980c 100644 --- a/drivers/vdpa/mlx5/core/mlx5_vdpa.h +++ b/drivers/vdpa/mlx5/core/mlx5_vdpa.h @@ -4,9 +4,13 @@ #ifndef __MLX5_VDPA_H__ #define __MLX5_VDPA_H__ +#include +#include #include #include +#define MLX5V_ETH_HARD_MTU (ETH_HLEN + VLAN_HLEN + ETH_FCS_LEN) + struct mlx5_vdpa_direct_mr { u64 start; u64 end; diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 71397fdafa6a..a49ebb250253 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -1907,6 +1907,19 @@ static const struct vdpa_config_ops mlx5_vdpa_ops = { .free = mlx5_vdpa_free, }; +static int query_mtu(struct mlx5_core_dev *mdev, u16 *mtu) +{ + u16 hw_mtu; + int err; + + err = mlx5_query_nic_vport_mtu(mdev, &hw_mtu); + if (err) + return err; + + *mtu = hw_mtu - MLX5V_ETH_HARD_MTU; + return 0; +} + static int alloc_resources(struct mlx5_vdpa_net *ndev) { struct mlx5_vdpa_net_resources *res = &ndev->res; @@ -1992,7 +2005,7 @@ static int mlx5v_probe(struct auxiliary_device *adev, init_mvqs(ndev); mutex_init(&ndev->reslock); config = &ndev->config; - err = mlx5_query_nic_vport_mtu(mdev, &ndev->mtu); + err = query_mtu(mdev, &ndev->mtu); if (err) goto err_mtu; From d13a15d544ce51c0d83744ccb638c954e645feea Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Apr 2021 12:10:44 +0300 Subject: [PATCH 0867/1091] vdpa/mlx5: Use the correct dma device when registering memory In cases where the vdpa instance uses a SF (sub function), the DMA device is the parent device. Use a function to retrieve the correct DMA device. Fixes: 1958fc2f0712 ("net/mlx5: SF, Add auxiliary device driver") Signed-off-by: Eli Cohen Reviewed-by: Parav Pandit Link: https://lore.kernel.org/r/20210408091047.4269-3-elic@nvidia.com Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vdpa/mlx5/core/mr.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/vdpa/mlx5/core/mr.c b/drivers/vdpa/mlx5/core/mr.c index d300f799efcd..3908ff28eec0 100644 --- a/drivers/vdpa/mlx5/core/mr.c +++ b/drivers/vdpa/mlx5/core/mr.c @@ -219,6 +219,11 @@ static void destroy_indirect_key(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_m mlx5_vdpa_destroy_mkey(mvdev, &mkey->mkey); } +static struct device *get_dma_device(struct mlx5_vdpa_dev *mvdev) +{ + return &mvdev->mdev->pdev->dev; +} + static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr, struct vhost_iotlb *iotlb) { @@ -234,7 +239,7 @@ static int map_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr u64 pa; u64 paend; struct scatterlist *sg; - struct device *dma = mvdev->mdev->device; + struct device *dma = get_dma_device(mvdev); for (map = vhost_iotlb_itree_first(iotlb, mr->start, mr->end - 1); map; map = vhost_iotlb_itree_next(map, start, mr->end - 1)) { @@ -291,7 +296,7 @@ err_map: static void unmap_direct_mr(struct mlx5_vdpa_dev *mvdev, struct mlx5_vdpa_direct_mr *mr) { - struct device *dma = mvdev->mdev->device; + struct device *dma = get_dma_device(mvdev); destroy_direct_mr(mvdev, mr); dma_unmap_sg_attrs(dma, mr->sg_head.sgl, mr->nsg, DMA_BIDIRECTIONAL, 0); From b2ae0a2db8a2d42a643590c4935faf61fedf553b Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Apr 2021 12:10:45 +0300 Subject: [PATCH 0868/1091] vdpa/mlx5: Retrieve BAR address suitable any function struct mlx5_core_dev has a bar_addr field that contains the correct bar address for the function regardless of whether it is pci function or sub function. Use it. Fixes: 1958fc2f0712 ("net/mlx5: SF, Add auxiliary device driver") Signed-off-by: Eli Cohen Reviewed-by: Parav Pandit Link: https://lore.kernel.org/r/20210408091047.4269-4-elic@nvidia.com Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vdpa/mlx5/core/resources.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/drivers/vdpa/mlx5/core/resources.c b/drivers/vdpa/mlx5/core/resources.c index 96e6421c5d1c..6521cbd0f5c2 100644 --- a/drivers/vdpa/mlx5/core/resources.c +++ b/drivers/vdpa/mlx5/core/resources.c @@ -246,7 +246,8 @@ int mlx5_vdpa_alloc_resources(struct mlx5_vdpa_dev *mvdev) if (err) goto err_key; - kick_addr = pci_resource_start(mdev->pdev, 0) + offset; + kick_addr = mdev->bar_addr + offset; + res->kick_addr = ioremap(kick_addr, PAGE_SIZE); if (!res->kick_addr) { err = -ENOMEM; From 4b454a82418dd76d8c0590bb3f7a99a63ea57dc5 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Apr 2021 12:10:46 +0300 Subject: [PATCH 0869/1091] vdpa/mlx5: Fix wrong use of bit numbers VIRTIO_F_VERSION_1 is a bit number. Use BIT_ULL() with mask conditionals. Also, in mlx5_vdpa_is_little_endian() use BIT_ULL for consistency with the rest of the code. Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for supported mlx5 devices") Signed-off-by: Eli Cohen Link: https://lore.kernel.org/r/20210408091047.4269-5-elic@nvidia.com Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vdpa/mlx5/net/mlx5_vnet.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index a49ebb250253..6fe61fc57790 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -820,7 +820,7 @@ static int create_virtqueue(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtque MLX5_SET(virtio_q, vq_ctx, event_qpn_or_msix, mvq->fwqp.mqp.qpn); MLX5_SET(virtio_q, vq_ctx, queue_size, mvq->num_ent); MLX5_SET(virtio_q, vq_ctx, virtio_version_1_0, - !!(ndev->mvdev.actual_features & VIRTIO_F_VERSION_1)); + !!(ndev->mvdev.actual_features & BIT_ULL(VIRTIO_F_VERSION_1))); MLX5_SET64(virtio_q, vq_ctx, desc_addr, mvq->desc_addr); MLX5_SET64(virtio_q, vq_ctx, used_addr, mvq->device_addr); MLX5_SET64(virtio_q, vq_ctx, available_addr, mvq->driver_addr); @@ -1554,7 +1554,7 @@ static void clear_virtqueues(struct mlx5_vdpa_net *ndev) static inline bool mlx5_vdpa_is_little_endian(struct mlx5_vdpa_dev *mvdev) { return virtio_legacy_is_little_endian() || - (mvdev->actual_features & (1ULL << VIRTIO_F_VERSION_1)); + (mvdev->actual_features & BIT_ULL(VIRTIO_F_VERSION_1)); } static __virtio16 cpu_to_mlx5vdpa16(struct mlx5_vdpa_dev *mvdev, u16 val) From bc04d93ea30a0a8eb2a2648b848cef35d1f6f798 Mon Sep 17 00:00:00 2001 From: Eli Cohen Date: Thu, 8 Apr 2021 12:10:47 +0300 Subject: [PATCH 0870/1091] vdpa/mlx5: Fix suspend/resume index restoration When we suspend the VM, the VDPA interface will be reset. When the VM is resumed again, clear_virtqueues() will clear the available and used indices resulting in hardware virqtqueue objects becoming out of sync. We can avoid this function alltogether since qemu will clear them if required, e.g. when the VM went through a reboot. Moreover, since the hw available and used indices should always be identical on query and should be restored to the same value same value for virtqueues that complete in order, we set the single value provided by set_vq_state(). In get_vq_state() we return the value of hardware used index. Fixes: b35ccebe3ef7 ("vdpa/mlx5: Restore the hardware used index after change map") Fixes: 1a86b377aa21 ("vdpa/mlx5: Add VDPA driver for supported mlx5 devices") Signed-off-by: Eli Cohen Link: https://lore.kernel.org/r/20210408091047.4269-6-elic@nvidia.com Signed-off-by: Michael S. Tsirkin Acked-by: Jason Wang --- drivers/vdpa/mlx5/net/mlx5_vnet.c | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/drivers/vdpa/mlx5/net/mlx5_vnet.c b/drivers/vdpa/mlx5/net/mlx5_vnet.c index 6fe61fc57790..4d2809c7d4e3 100644 --- a/drivers/vdpa/mlx5/net/mlx5_vnet.c +++ b/drivers/vdpa/mlx5/net/mlx5_vnet.c @@ -1169,6 +1169,7 @@ static void suspend_vq(struct mlx5_vdpa_net *ndev, struct mlx5_vdpa_virtqueue *m return; } mvq->avail_idx = attr.available_index; + mvq->used_idx = attr.used_index; } static void suspend_vqs(struct mlx5_vdpa_net *ndev) @@ -1426,6 +1427,7 @@ static int mlx5_vdpa_set_vq_state(struct vdpa_device *vdev, u16 idx, return -EINVAL; } + mvq->used_idx = state->avail_index; mvq->avail_idx = state->avail_index; return 0; } @@ -1443,7 +1445,11 @@ static int mlx5_vdpa_get_vq_state(struct vdpa_device *vdev, u16 idx, struct vdpa * that cares about emulating the index after vq is stopped. */ if (!mvq->initialized) { - state->avail_index = mvq->avail_idx; + /* Firmware returns a wrong value for the available index. + * Since both values should be identical, we take the value of + * used_idx which is reported correctly. + */ + state->avail_index = mvq->used_idx; return 0; } @@ -1452,7 +1458,7 @@ static int mlx5_vdpa_get_vq_state(struct vdpa_device *vdev, u16 idx, struct vdpa mlx5_vdpa_warn(mvdev, "failed to query virtqueue\n"); return err; } - state->avail_index = attr.available_index; + state->avail_index = attr.used_index; return 0; } @@ -1540,16 +1546,6 @@ static void teardown_virtqueues(struct mlx5_vdpa_net *ndev) } } -static void clear_virtqueues(struct mlx5_vdpa_net *ndev) -{ - int i; - - for (i = ndev->mvdev.max_vqs - 1; i >= 0; i--) { - ndev->vqs[i].avail_idx = 0; - ndev->vqs[i].used_idx = 0; - } -} - /* TODO: cross-endian support */ static inline bool mlx5_vdpa_is_little_endian(struct mlx5_vdpa_dev *mvdev) { @@ -1785,7 +1781,6 @@ static void mlx5_vdpa_set_status(struct vdpa_device *vdev, u8 status) if (!status) { mlx5_vdpa_info(mvdev, "performing device reset\n"); teardown_driver(ndev); - clear_virtqueues(ndev); mlx5_vdpa_destroy_mr(&ndev->mvdev); ndev->mvdev.status = 0; ndev->mvdev.mlx_features = 0; From 26e33ed9f18475ebdc981d45150ac9a019e69f07 Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Thu, 8 Apr 2021 18:32:36 +0530 Subject: [PATCH 0871/1091] ASoC: amd: Add support for ALC1015P codec in acp3x machine driver Add ALC1015p codec support for acp3x machine driver. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/1617886984-9500-1-git-send-email-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/Kconfig | 1 + sound/soc/amd/acp3x-rt5682-max9836.c | 46 +++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/sound/soc/amd/Kconfig b/sound/soc/amd/Kconfig index 256c19275d45..ba5a85bf7412 100644 --- a/sound/soc/amd/Kconfig +++ b/sound/soc/amd/Kconfig @@ -35,6 +35,7 @@ config SND_SOC_AMD_RV_RT5682_MACH select SND_SOC_CROS_EC_CODEC select I2C_CROS_EC_TUNNEL select SND_SOC_RT1015 + select SND_SOC_RT1015P depends on SND_SOC_AMD_ACP3x && I2C && CROS_EC help This option enables machine driver for RT5682 and MAX9835. diff --git a/sound/soc/amd/acp3x-rt5682-max9836.c b/sound/soc/amd/acp3x-rt5682-max9836.c index cea320ad0e1c..d9980aba2910 100644 --- a/sound/soc/amd/acp3x-rt5682-max9836.c +++ b/sound/soc/amd/acp3x-rt5682-max9836.c @@ -275,6 +275,8 @@ SND_SOC_DAILINK_DEF(rt5682, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC5682:00", "rt5682-aif1"))); SND_SOC_DAILINK_DEF(max, DAILINK_COMP_ARRAY(COMP_CODEC("MX98357A:00", "HiFi"))); +SND_SOC_DAILINK_DEF(rt1015p, + DAILINK_COMP_ARRAY(COMP_CODEC("RTL1015:00", "HiFi"))); SND_SOC_DAILINK_DEF(rt1015, DAILINK_COMP_ARRAY(COMP_CODEC("i2c-10EC1015:00", "rt1015-aif"), COMP_CODEC("i2c-10EC1015:01", "rt1015-aif"))); @@ -419,6 +421,43 @@ static struct snd_soc_card acp3x_1015 = { .num_controls = ARRAY_SIZE(acp3x_mc_1015_controls), }; +static const struct snd_soc_dapm_widget acp3x_1015p_widgets[] = { + SND_SOC_DAPM_HP("Headphone Jack", NULL), + SND_SOC_DAPM_MIC("Headset Mic", NULL), + SND_SOC_DAPM_MUX("Dmic Mux", SND_SOC_NOPM, 0, 0, + &acp3x_dmic_mux_control), + SND_SOC_DAPM_SPK("Speakers", NULL), +}; + +static const struct snd_soc_dapm_route acp3x_1015p_route[] = { + {"Headphone Jack", NULL, "HPOL"}, + {"Headphone Jack", NULL, "HPOR"}, + {"IN1P", NULL, "Headset Mic"}, + {"Dmic Mux", "Front Mic", "DMIC"}, + {"Dmic Mux", "Rear Mic", "DMIC"}, + /* speaker */ + { "Speakers", NULL, "Speaker" }, +}; + +static const struct snd_kcontrol_new acp3x_mc_1015p_controls[] = { + SOC_DAPM_PIN_SWITCH("Speakers"), + SOC_DAPM_PIN_SWITCH("Headphone Jack"), + SOC_DAPM_PIN_SWITCH("Headset Mic"), +}; + +static struct snd_soc_card acp3x_1015p = { + .name = "acp3xalc56821015p", + .owner = THIS_MODULE, + .dai_link = acp3x_dai, + .num_links = ARRAY_SIZE(acp3x_dai), + .dapm_widgets = acp3x_1015p_widgets, + .num_dapm_widgets = ARRAY_SIZE(acp3x_1015p_widgets), + .dapm_routes = acp3x_1015p_route, + .num_dapm_routes = ARRAY_SIZE(acp3x_1015p_route), + .controls = acp3x_mc_1015p_controls, + .num_controls = ARRAY_SIZE(acp3x_mc_1015p_controls), +}; + void *soc_is_rltk_max(struct device *dev) { const struct acpi_device_id *match; @@ -435,6 +474,9 @@ static void card_spk_dai_link_present(struct snd_soc_dai_link *links, if (!strcmp(card_name, "acp3xalc56821015")) { links[1].codecs = rt1015; links[1].num_codecs = ARRAY_SIZE(rt1015); + } else if (!strcmp(card_name, "acp3xalc56821015p")) { + links[1].codecs = rt1015p; + links[1].num_codecs = ARRAY_SIZE(rt1015p); } else { links[1].codecs = max; links[1].num_codecs = ARRAY_SIZE(max); @@ -486,6 +528,7 @@ static int acp3x_probe(struct platform_device *pdev) static const struct acpi_device_id acp3x_audio_acpi_match[] = { { "AMDI5682", (unsigned long)&acp3x_5682}, { "AMDI1015", (unsigned long)&acp3x_1015}, + { "10021015", (unsigned long)&acp3x_1015p}, {}, }; MODULE_DEVICE_TABLE(acpi, acp3x_audio_acpi_match); @@ -503,5 +546,6 @@ module_platform_driver(acp3x_audio); MODULE_AUTHOR("akshu.agrawal@amd.com"); MODULE_AUTHOR("Vishnuvardhanrao.Ravulapati@amd.com"); -MODULE_DESCRIPTION("ALC5682 ALC1015 & MAX98357 audio support"); +MODULE_AUTHOR("Vijendar.Mukunda@amd.com"); +MODULE_DESCRIPTION("ALC5682 ALC1015, ALC1015P & MAX98357 audio support"); MODULE_LICENSE("GPL v2"); From f6d6c6993a30af46c3a2c323589611890c10ecda Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 9 Apr 2021 14:47:45 +0200 Subject: [PATCH 0872/1091] dt-bindings: don't use ../dir for doc references As documents have been renamed and moved around, their references will break, but this will be unnoticed, as the script which checks for it won't handle "../" references. So, replace them by the full patch. Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/68d3a1244119d1f2829c375b0ef554cf348bc89f.1617972339.git.mchehab+huawei@kernel.org Signed-off-by: Rob Herring --- .../input/touchscreen/resistive-adc-touch.txt | 2 +- .../devicetree/bindings/mfd/motorola-cpcap.txt | 16 ++++++++-------- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt index 51456c0e9a27..fee0da12474e 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt @@ -5,7 +5,7 @@ Required properties: - compatible: must be "resistive-adc-touch" The device must be connected to an ADC device that provides channels for position measurement and optional pressure. -Refer to ../iio/iio-bindings.txt for details +Refer to Documentation/devicetree/bindings/iio/iio-bindings.txt for details - iio-channels: must have at least two channels connected to an ADC device. These should correspond to the channels exposed by the ADC device and should have the right index as the ADC device registers them. These channels diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt index 5ddcc8f4febc..ebdccfb600b9 100644 --- a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt +++ b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt @@ -16,14 +16,14 @@ Optional subnodes: The sub-functions of CPCAP get their own node with their own compatible values, which are described in the following files: -- ../power/supply/cpcap-battery.txt -- ../power/supply/cpcap-charger.txt -- ../regulator/cpcap-regulator.txt -- ../phy/phy-cpcap-usb.txt -- ../input/cpcap-pwrbutton.txt -- ../rtc/cpcap-rtc.txt -- ../leds/leds-cpcap.txt -- ../iio/adc/cpcap-adc.txt +- Documentation/devicetree/bindings/power/supply/cpcap-battery.txt +- Documentation/devicetree/bindings/power/supply/cpcap-charger.txt +- Documentation/devicetree/bindings/regulator/cpcap-regulator.txt +- Documentation/devicetree/bindings/phy/phy-cpcap-usb.txt +- Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt +- Documentation/devicetree/bindings/rtc/cpcap-rtc.txt +- Documentation/devicetree/bindings/leds/leds-cpcap.txt +- Documentation/devicetree/bindings/iio/adc/cpcap-adc.txt The only exception is the audio codec. Instead of a compatible value its node must be named "audio-codec". From 8235ef155d00d903ff46df099175517ff08f34c9 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 9 Apr 2021 14:47:46 +0200 Subject: [PATCH 0873/1091] dt-bindings: fix references for iio-bindings.txt The iio-bindings.txt was converted into two files and merged at the dt-schema git tree at: https://github.com/devicetree-org/dt-schema Yet, some documents still refer to the old file. Fix their references, in order to point to the right URL. Fixes: dba91f82d580 ("dt-bindings:iio:iio-binding.txt Drop file as content now in dt-schema") Acked-by: Jonathan Cameron Acked-by: Guenter Roeck Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/4efd81eca266ca0875d3bf9d1672097444146c69.1617972339.git.mchehab+huawei@kernel.org Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt | 2 +- Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml | 5 +++-- Documentation/devicetree/bindings/input/adc-joystick.yaml | 4 +++- .../bindings/input/touchscreen/resistive-adc-touch.txt | 5 ++++- Documentation/devicetree/bindings/mfd/ab8500.txt | 4 +++- 5 files changed, 14 insertions(+), 6 deletions(-) diff --git a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt index 37f18d684f6a..4c5c3712970e 100644 --- a/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt +++ b/Documentation/devicetree/bindings/hwmon/ntc_thermistor.txt @@ -32,7 +32,7 @@ Optional node properties: - "#thermal-sensor-cells" Used to expose itself to thermal fw. Read more about iio bindings at - Documentation/devicetree/bindings/iio/iio-bindings.txt + https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/ Example: ncp15wb473@0 { diff --git a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml index 9f414dbdae86..433a3fb55a2e 100644 --- a/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml +++ b/Documentation/devicetree/bindings/iio/adc/ingenic,adc.yaml @@ -14,8 +14,9 @@ description: > Industrial I/O subsystem bindings for ADC controller found in Ingenic JZ47xx SoCs. - ADC clients must use the format described in iio-bindings.txt, giving - a phandle and IIO specifier pair ("io-channels") to the ADC controller. + ADC clients must use the format described in + https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml, + giving a phandle and IIO specifier pair ("io-channels") to the ADC controller. properties: compatible: diff --git a/Documentation/devicetree/bindings/input/adc-joystick.yaml b/Documentation/devicetree/bindings/input/adc-joystick.yaml index 054406bbd22b..721878d5b7af 100644 --- a/Documentation/devicetree/bindings/input/adc-joystick.yaml +++ b/Documentation/devicetree/bindings/input/adc-joystick.yaml @@ -24,7 +24,9 @@ properties: description: > List of phandle and IIO specifier pairs. Each pair defines one ADC channel to which a joystick axis is connected. - See Documentation/devicetree/bindings/iio/iio-bindings.txt for details. + See + https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml + for details. '#address-cells': const: 1 diff --git a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt index fee0da12474e..af5223bb5bdd 100644 --- a/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt +++ b/Documentation/devicetree/bindings/input/touchscreen/resistive-adc-touch.txt @@ -5,7 +5,10 @@ Required properties: - compatible: must be "resistive-adc-touch" The device must be connected to an ADC device that provides channels for position measurement and optional pressure. -Refer to Documentation/devicetree/bindings/iio/iio-bindings.txt for details +Refer to +https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml +for details + - iio-channels: must have at least two channels connected to an ADC device. These should correspond to the channels exposed by the ADC device and should have the right index as the ADC device registers them. These channels diff --git a/Documentation/devicetree/bindings/mfd/ab8500.txt b/Documentation/devicetree/bindings/mfd/ab8500.txt index d2a6e835c257..937b3e5505e0 100644 --- a/Documentation/devicetree/bindings/mfd/ab8500.txt +++ b/Documentation/devicetree/bindings/mfd/ab8500.txt @@ -72,7 +72,9 @@ Required child device properties: pwm|regulator|rtc|sysctrl|usb]"; A few child devices require ADC channels from the GPADC node. Those follow the - standard bindings from iio/iio-bindings.txt and iio/adc/adc.txt + standard bindings from + https://github.com/devicetree-org/dt-schema/blob/master/schemas/iio/iio-consumer.yaml + and Documentation/devicetree/bindings/iio/adc/adc.yaml abx500-temp : io-channels "aux1" and "aux2" for measuring external temperatures. From 21d6ff39e1692b1f8c0d17331b15f76b40a3c726 Mon Sep 17 00:00:00 2001 From: Mauro Carvalho Chehab Date: Fri, 9 Apr 2021 14:47:47 +0200 Subject: [PATCH 0874/1091] dt-bindings:iio:adc: update motorola,cpcap-adc.yaml reference Changeset 1ca9d1b1342d ("dt-bindings:iio:adc:motorola,cpcap-adc yaml conversion") renamed: Documentation/devicetree/bindings/iio/adc/cpcap-adc.txt to: Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml. Update its cross-reference accordingly. Fixes: 1ca9d1b1342d ("dt-bindings:iio:adc:motorola,cpcap-adc yaml conversion") Acked-by: Jonathan Cameron Signed-off-by: Mauro Carvalho Chehab Link: https://lore.kernel.org/r/3e205e5fa701e4bc15d39d6ac1f57717df2bb4c6.1617972339.git.mchehab+huawei@kernel.org Signed-off-by: Rob Herring --- Documentation/devicetree/bindings/mfd/motorola-cpcap.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt index ebdccfb600b9..b52e7a33f0f9 100644 --- a/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt +++ b/Documentation/devicetree/bindings/mfd/motorola-cpcap.txt @@ -23,7 +23,7 @@ which are described in the following files: - Documentation/devicetree/bindings/input/cpcap-pwrbutton.txt - Documentation/devicetree/bindings/rtc/cpcap-rtc.txt - Documentation/devicetree/bindings/leds/leds-cpcap.txt -- Documentation/devicetree/bindings/iio/adc/cpcap-adc.txt +- Documentation/devicetree/bindings/iio/adc/motorola,cpcap-adc.yaml The only exception is the audio codec. Instead of a compatible value its node must be named "audio-codec". From d473d32c2fbac2d1d7082c61899cfebd34eb267a Mon Sep 17 00:00:00 2001 From: Ilya Lipnitskiy Date: Mon, 5 Apr 2021 15:25:40 -0700 Subject: [PATCH 0875/1091] of: property: fw_devlink: do not link ".*,nr-gpios" [,]nr-gpios property is used by some GPIO drivers[0] to indicate the number of GPIOs present on a system, not define a GPIO. nr-gpios is not configured by #gpio-cells and can't be parsed along with other "*-gpios" properties. nr-gpios without the "," prefix is not allowed by the DT spec[1], so only add exception for the ",nr-gpios" suffix and let the error message continue being printed for non-compliant implementations. [0] nr-gpios is referenced in Documentation/devicetree/bindings/gpio: - gpio-adnp.txt - gpio-xgene-sb.txt - gpio-xlp.txt - snps,dw-apb-gpio.yaml [1] Link: https://github.com/devicetree-org/dt-schema/blob/cb53a16a1eb3e2169ce170c071e47940845ec26e/schemas/gpio/gpio-consumer.yaml#L20 Fixes errors such as: OF: /palmbus@300000/gpio@600: could not find phandle Fixes: 7f00be96f125 ("of: property: Add device link support for interrupt-parent, dmas and -gpio(s)") Signed-off-by: Ilya Lipnitskiy Cc: Saravana Kannan Cc: stable@vger.kernel.org # v5.5+ Link: https://lore.kernel.org/r/20210405222540.18145-1-ilya.lipnitskiy@gmail.com Signed-off-by: Rob Herring --- drivers/of/property.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/drivers/of/property.c b/drivers/of/property.c index 5f9eed79a8aa..6d8368bf88ca 100644 --- a/drivers/of/property.c +++ b/drivers/of/property.c @@ -1260,7 +1260,16 @@ DEFINE_SIMPLE_PROP(pinctrl7, "pinctrl-7", NULL) DEFINE_SIMPLE_PROP(pinctrl8, "pinctrl-8", NULL) DEFINE_SUFFIX_PROP(regulators, "-supply", NULL) DEFINE_SUFFIX_PROP(gpio, "-gpio", "#gpio-cells") -DEFINE_SUFFIX_PROP(gpios, "-gpios", "#gpio-cells") + +static struct device_node *parse_gpios(struct device_node *np, + const char *prop_name, int index) +{ + if (!strcmp_suffix(prop_name, ",nr-gpios")) + return NULL; + + return parse_suffix_prop_cells(np, prop_name, index, "-gpios", + "#gpio-cells"); +} static struct device_node *parse_iommu_maps(struct device_node *np, const char *prop_name, int index) From 3bc41d6d2721d5168a8f7fea34028a5332068f5e Mon Sep 17 00:00:00 2001 From: Sven Van Asbroeck Date: Thu, 8 Apr 2021 20:39:04 -0400 Subject: [PATCH 0876/1091] lan743x: fix ethernet frame cutoff issue The ethernet frame length is calculated incorrectly. Depending on the value of RX_HEAD_PADDING, this may result in ethernet frames that are too short (cut off at the end), or too long (garbage added to the end). Fix by calculating the ethernet frame length correctly. For added clarity, use the ETH_FCS_LEN constant in the calculation. Many thanks to Heiner Kallweit for suggesting this solution. Suggested-by: Heiner Kallweit Fixes: 3e21a10fdea3 ("lan743x: trim all 4 bytes of the FCS; not just 2") Link: https://lore.kernel.org/lkml/20210408172353.21143-1-TheSven73@gmail.com/ Signed-off-by: Sven Van Asbroeck Reviewed-by: George McCollister Tested-by: George McCollister Link: https://lore.kernel.org/r/20210409003904.8957-1-TheSven73@gmail.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/microchip/lan743x_main.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/microchip/lan743x_main.c b/drivers/net/ethernet/microchip/lan743x_main.c index 1c3e204d727c..7b6794aa8ea9 100644 --- a/drivers/net/ethernet/microchip/lan743x_main.c +++ b/drivers/net/ethernet/microchip/lan743x_main.c @@ -885,8 +885,8 @@ static int lan743x_mac_set_mtu(struct lan743x_adapter *adapter, int new_mtu) } mac_rx &= ~(MAC_RX_MAX_SIZE_MASK_); - mac_rx |= (((new_mtu + ETH_HLEN + 4) << MAC_RX_MAX_SIZE_SHIFT_) & - MAC_RX_MAX_SIZE_MASK_); + mac_rx |= (((new_mtu + ETH_HLEN + ETH_FCS_LEN) + << MAC_RX_MAX_SIZE_SHIFT_) & MAC_RX_MAX_SIZE_MASK_); lan743x_csr_write(adapter, MAC_RX, mac_rx); if (enabled) { @@ -1944,7 +1944,7 @@ static int lan743x_rx_init_ring_element(struct lan743x_rx *rx, int index) struct sk_buff *skb; dma_addr_t dma_ptr; - buffer_length = netdev->mtu + ETH_HLEN + 4 + RX_HEAD_PADDING; + buffer_length = netdev->mtu + ETH_HLEN + ETH_FCS_LEN + RX_HEAD_PADDING; descriptor = &rx->ring_cpu_ptr[index]; buffer_info = &rx->buffer_info[index]; @@ -2040,7 +2040,7 @@ lan743x_rx_trim_skb(struct sk_buff *skb, int frame_length) dev_kfree_skb_irq(skb); return NULL; } - frame_length = max_t(int, 0, frame_length - RX_HEAD_PADDING - 4); + frame_length = max_t(int, 0, frame_length - ETH_FCS_LEN); if (skb->len > frame_length) { skb->tail -= skb->len - frame_length; skb->len = frame_length; From cd7e963d2f0875789ddb5c3746b628716bd0a8c9 Mon Sep 17 00:00:00 2001 From: Salil Mehta Date: Fri, 9 Apr 2021 08:42:23 +0100 Subject: [PATCH 0877/1091] net: hns3: Trivial spell fix in hns3 driver Some trivial spelling mistakes which caught my eye during the review of the code. Signed-off-by: Salil Mehta Link: https://lore.kernel.org/r/20210409074223.32480-1-salil.mehta@huawei.com Signed-off-by: Jakub Kicinski --- drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c | 2 +- drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index 2dd2af269b46..b0dbe6dcaa7b 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -11210,7 +11210,7 @@ static int hclge_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, if (ret) return ret; - /* RSS indirection table has been configuared by user */ + /* RSS indirection table has been configured by user */ if (rxfh_configured) goto out; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c index 14b83eca0a5e..e295d359e912 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3vf/hclgevf_main.c @@ -2193,7 +2193,7 @@ static void hclgevf_reset_service_task(struct hclgevf_dev *hdev) if (test_and_clear_bit(HCLGEVF_RESET_PENDING, &hdev->reset_state)) { - /* PF has initmated that it is about to reset the hardware. + /* PF has intimated that it is about to reset the hardware. * We now have to poll & check if hardware has actually * completed the reset sequence. On hardware reset completion, * VF needs to reset the client and ae device. @@ -3497,7 +3497,7 @@ static int hclgevf_set_channels(struct hnae3_handle *handle, u32 new_tqps_num, if (ret) return ret; - /* RSS indirection table has been configuared by user */ + /* RSS indirection table has been configured by user */ if (rxfh_configured) goto out; From 27f0ad71699de41bae013c367b95a6b319cc46a9 Mon Sep 17 00:00:00 2001 From: Paolo Abeni Date: Fri, 9 Apr 2021 17:24:17 +0200 Subject: [PATCH 0878/1091] net: fix hangup on napi_disable for threaded napi napi_disable() is subject to an hangup, when the threaded mode is enabled and the napi is under heavy traffic. If the relevant napi has been scheduled and the napi_disable() kicks in before the next napi_threaded_wait() completes - so that the latter quits due to the napi_disable_pending() condition, the existing code leaves the NAPI_STATE_SCHED bit set and the napi_disable() loop waiting for such bit will hang. This patch addresses the issue by dropping the NAPI_STATE_DISABLE bit test in napi_thread_wait(). The later napi_threaded_poll() iteration will take care of clearing the NAPI_STATE_SCHED. This also addresses a related problem reported by Jakub: before this patch a napi_disable()/napi_enable() pair killed the napi thread, effectively disabling the threaded mode. On the patched kernel napi_disable() simply stops scheduling the relevant thread. v1 -> v2: - let the main napi_thread_poll() loop clear the SCHED bit Reported-by: Jakub Kicinski Fixes: 29863d41bb6e ("net: implement threaded-able napi poll loop support") Signed-off-by: Paolo Abeni Reviewed-by: Eric Dumazet Link: https://lore.kernel.org/r/883923fa22745a9589e8610962b7dc59df09fb1f.1617981844.git.pabeni@redhat.com Signed-off-by: Jakub Kicinski --- net/core/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index 0f72ff5d34ba..af8c1ea040b9 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -6992,7 +6992,7 @@ static int napi_thread_wait(struct napi_struct *napi) set_current_state(TASK_INTERRUPTIBLE); - while (!kthread_should_stop() && !napi_disable_pending(napi)) { + while (!kthread_should_stop()) { /* Testing SCHED_THREADED bit here to make sure the current * kthread owns this napi and could poll on this napi. * Testing SCHED bit is not enough because SCHED bit might be @@ -7010,6 +7010,7 @@ static int napi_thread_wait(struct napi_struct *napi) set_current_state(TASK_INTERRUPTIBLE); } __set_current_state(TASK_RUNNING); + return -1; } From 4873d8cc141e76aa5f3e7ef6e98dfb3823fcbe6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Apr 2021 13:27:01 -0700 Subject: [PATCH 0879/1091] MAINTAINERS: update CZ.NIC's Turris information MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Add all the files maintained by Turris team, not only for MOX, but also for Omnia. Change website. Link: https://lkml.kernel.org/r/20210325171123.28093-1-kabel@kernel.org Signed-off-by: Marek Behún Cc: Pavel Machek Cc: Jassi Brar Cc: Linus Walleij Cc: Bartosz Golaszewski Cc: Greg Kroah-Hartman Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- MAINTAINERS | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/MAINTAINERS b/MAINTAINERS index c80ad735b384..2a6f7f5edd5a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1790,19 +1790,26 @@ F: drivers/net/ethernet/cortina/ F: drivers/pinctrl/pinctrl-gemini.c F: drivers/rtc/rtc-ftrtc010.c -ARM/CZ.NIC TURRIS MOX SUPPORT +ARM/CZ.NIC TURRIS SUPPORT M: Marek Behun S: Maintained -W: http://mox.turris.cz +W: https://www.turris.cz/ F: Documentation/ABI/testing/debugfs-moxtet F: Documentation/ABI/testing/sysfs-bus-moxtet-devices F: Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm F: Documentation/devicetree/bindings/bus/moxtet.txt F: Documentation/devicetree/bindings/firmware/cznic,turris-mox-rwtm.txt F: Documentation/devicetree/bindings/gpio/gpio-moxtet.txt +F: Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml +F: Documentation/devicetree/bindings/watchdog/armada-37xx-wdt.txt F: drivers/bus/moxtet.c F: drivers/firmware/turris-mox-rwtm.c +F: drivers/leds/leds-turris-omnia.c +F: drivers/mailbox/armada-37xx-rwtm-mailbox.c F: drivers/gpio/gpio-moxtet.c +F: drivers/watchdog/armada_37xx_wdt.c +F: include/dt-bindings/bus/moxtet.h +F: include/linux/armada-37xx-rwtm-mailbox.h F: include/linux/moxtet.h ARM/EZX SMARTPHONES (A780, A910, A1200, E680, ROKR E2 and ROKR E6) From b37c38484375f5a204500e0b10b40da268090995 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Fri, 9 Apr 2021 13:27:04 -0700 Subject: [PATCH 0880/1091] treewide: change my e-mail address, fix my name MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change my e-mail address to kabel@kernel.org, and fix my name in non-code parts (add diacritical mark). Link: https://lkml.kernel.org/r/20210325171123.28093-2-kabel@kernel.org Signed-off-by: Marek Behún Cc: Bartosz Golaszewski Cc: Greg Kroah-Hartman Cc: Jassi Brar Cc: Linus Walleij Cc: Pavel Machek Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- Documentation/ABI/testing/debugfs-moxtet | 4 ++-- Documentation/ABI/testing/debugfs-turris-mox-rwtm | 2 +- Documentation/ABI/testing/sysfs-bus-moxtet-devices | 6 +++--- .../ABI/testing/sysfs-class-led-driver-turris-omnia | 2 +- .../ABI/testing/sysfs-firmware-turris-mox-rwtm | 10 +++++----- .../bindings/leds/cznic,turris-omnia-leds.yaml | 2 +- MAINTAINERS | 2 +- arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts | 2 +- drivers/bus/moxtet.c | 4 ++-- drivers/firmware/turris-mox-rwtm.c | 4 ++-- drivers/gpio/gpio-moxtet.c | 4 ++-- drivers/leds/leds-turris-omnia.c | 4 ++-- drivers/mailbox/armada-37xx-rwtm-mailbox.c | 4 ++-- drivers/watchdog/armada_37xx_wdt.c | 4 ++-- include/dt-bindings/bus/moxtet.h | 2 +- include/linux/armada-37xx-rwtm-mailbox.h | 2 +- include/linux/moxtet.h | 2 +- 17 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Documentation/ABI/testing/debugfs-moxtet b/Documentation/ABI/testing/debugfs-moxtet index 6eee10c3d5a1..637d8587d03d 100644 --- a/Documentation/ABI/testing/debugfs-moxtet +++ b/Documentation/ABI/testing/debugfs-moxtet @@ -1,7 +1,7 @@ What: /sys/kernel/debug/moxtet/input Date: March 2019 KernelVersion: 5.3 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) Read input from the shift registers, in hexadecimal. Returns N+1 bytes, where N is the number of Moxtet connected modules. The first byte is from the CPU board itself. @@ -19,7 +19,7 @@ Description: (Read) Read input from the shift registers, in hexadecimal. What: /sys/kernel/debug/moxtet/output Date: March 2019 KernelVersion: 5.3 -Contact: Marek Behún +Contact: Marek Behún Description: (RW) Read last written value to the shift registers, in hexadecimal, or write values to the shift registers, also in hexadecimal. diff --git a/Documentation/ABI/testing/debugfs-turris-mox-rwtm b/Documentation/ABI/testing/debugfs-turris-mox-rwtm index 326df1b74707..813987d5de4e 100644 --- a/Documentation/ABI/testing/debugfs-turris-mox-rwtm +++ b/Documentation/ABI/testing/debugfs-turris-mox-rwtm @@ -1,7 +1,7 @@ What: /sys/kernel/debug/turris-mox-rwtm/do_sign Date: Jun 2020 KernelVersion: 5.8 -Contact: Marek Behún +Contact: Marek Behún Description: ======= =========================================================== diff --git a/Documentation/ABI/testing/sysfs-bus-moxtet-devices b/Documentation/ABI/testing/sysfs-bus-moxtet-devices index 4a6d61b44f3f..32dccc00d57d 100644 --- a/Documentation/ABI/testing/sysfs-bus-moxtet-devices +++ b/Documentation/ABI/testing/sysfs-bus-moxtet-devices @@ -1,17 +1,17 @@ What: /sys/bus/moxtet/devices/moxtet-./module_description Date: March 2019 KernelVersion: 5.3 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) Moxtet module description. Format: string What: /sys/bus/moxtet/devices/moxtet-./module_id Date: March 2019 KernelVersion: 5.3 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) Moxtet module ID. Format: %x What: /sys/bus/moxtet/devices/moxtet-./module_name Date: March 2019 KernelVersion: 5.3 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) Moxtet module name. Format: string diff --git a/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia b/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia index 795a5de12fc1..c4d46970c1cf 100644 --- a/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia +++ b/Documentation/ABI/testing/sysfs-class-led-driver-turris-omnia @@ -1,7 +1,7 @@ What: /sys/class/leds//device/brightness Date: July 2020 KernelVersion: 5.9 -Contact: Marek Behún +Contact: Marek Behún Description: (RW) On the front panel of the Turris Omnia router there is also a button which can be used to control the intensity of all the LEDs at once, so that if they are too bright, user can dim them. diff --git a/Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm b/Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm index b8631f5a29c4..ea5e5b489bc7 100644 --- a/Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm +++ b/Documentation/ABI/testing/sysfs-firmware-turris-mox-rwtm @@ -1,21 +1,21 @@ What: /sys/firmware/turris-mox-rwtm/board_version Date: August 2019 KernelVersion: 5.4 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) Board version burned into eFuses of this Turris Mox board. Format: %i What: /sys/firmware/turris-mox-rwtm/mac_address* Date: August 2019 KernelVersion: 5.4 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) MAC addresses burned into eFuses of this Turris Mox board. Format: %pM What: /sys/firmware/turris-mox-rwtm/pubkey Date: August 2019 KernelVersion: 5.4 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) ECDSA public key (in pubkey hex compressed form) computed as pair to the ECDSA private key burned into eFuses of this Turris Mox Board. @@ -24,7 +24,7 @@ Description: (Read) ECDSA public key (in pubkey hex compressed form) computed What: /sys/firmware/turris-mox-rwtm/ram_size Date: August 2019 KernelVersion: 5.4 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) RAM size in MiB of this Turris Mox board as was detected during manufacturing and burned into eFuses. Can be 512 or 1024. Format: %i @@ -32,6 +32,6 @@ Description: (Read) RAM size in MiB of this Turris Mox board as was detected What: /sys/firmware/turris-mox-rwtm/serial_number Date: August 2019 KernelVersion: 5.4 -Contact: Marek Behún +Contact: Marek Behún Description: (Read) Serial number burned into eFuses of this Turris Mox device. Format: %016X diff --git a/Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml b/Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml index fe7fa25877fd..c7ed2871da06 100644 --- a/Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml +++ b/Documentation/devicetree/bindings/leds/cznic,turris-omnia-leds.yaml @@ -7,7 +7,7 @@ $schema: http://devicetree.org/meta-schemas/core.yaml# title: CZ.NIC's Turris Omnia LEDs driver maintainers: - - Marek Behún + - Marek Behún description: This module adds support for the RGB LEDs found on the front panel of the diff --git a/MAINTAINERS b/MAINTAINERS index 2a6f7f5edd5a..ba5cd29d2a48 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1791,7 +1791,7 @@ F: drivers/pinctrl/pinctrl-gemini.c F: drivers/rtc/rtc-ftrtc010.c ARM/CZ.NIC TURRIS SUPPORT -M: Marek Behun +M: Marek Behun S: Maintained W: https://www.turris.cz/ F: Documentation/ABI/testing/debugfs-moxtet diff --git a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts index d239ab70ed99..53e817c5f6f3 100644 --- a/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts +++ b/arch/arm64/boot/dts/marvell/armada-3720-turris-mox.dts @@ -1,7 +1,7 @@ // SPDX-License-Identifier: (GPL-2.0+ OR MIT) /* * Device Tree file for CZ.NIC Turris Mox Board - * 2019 by Marek Behun + * 2019 by Marek Behún */ /dts-v1/; diff --git a/drivers/bus/moxtet.c b/drivers/bus/moxtet.c index b20fdcbd035b..fd87a59837fa 100644 --- a/drivers/bus/moxtet.c +++ b/drivers/bus/moxtet.c @@ -2,7 +2,7 @@ /* * Turris Mox module configuration bus driver * - * Copyright (C) 2019 Marek Behun + * Copyright (C) 2019 Marek Behún */ #include @@ -879,6 +879,6 @@ static void __exit moxtet_exit(void) } module_exit(moxtet_exit); -MODULE_AUTHOR("Marek Behun "); +MODULE_AUTHOR("Marek Behun "); MODULE_DESCRIPTION("CZ.NIC's Turris Mox module configuration bus"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/firmware/turris-mox-rwtm.c b/drivers/firmware/turris-mox-rwtm.c index 50bb2a6d6ccf..62f0d1a5dd32 100644 --- a/drivers/firmware/turris-mox-rwtm.c +++ b/drivers/firmware/turris-mox-rwtm.c @@ -2,7 +2,7 @@ /* * Turris Mox rWTM firmware driver * - * Copyright (C) 2019 Marek Behun + * Copyright (C) 2019 Marek Behún */ #include @@ -547,4 +547,4 @@ module_platform_driver(turris_mox_rwtm_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("Turris Mox rWTM firmware driver"); -MODULE_AUTHOR("Marek Behun "); +MODULE_AUTHOR("Marek Behun "); diff --git a/drivers/gpio/gpio-moxtet.c b/drivers/gpio/gpio-moxtet.c index 8299909318f4..61f9efd6c64f 100644 --- a/drivers/gpio/gpio-moxtet.c +++ b/drivers/gpio/gpio-moxtet.c @@ -2,7 +2,7 @@ /* * Turris Mox Moxtet GPIO expander * - * Copyright (C) 2018 Marek Behun + * Copyright (C) 2018 Marek Behún */ #include @@ -174,6 +174,6 @@ static struct moxtet_driver moxtet_gpio_driver = { }; module_moxtet_driver(moxtet_gpio_driver); -MODULE_AUTHOR("Marek Behun "); +MODULE_AUTHOR("Marek Behun "); MODULE_DESCRIPTION("Turris Mox Moxtet GPIO expander"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/leds/leds-turris-omnia.c b/drivers/leds/leds-turris-omnia.c index 7b2f4d0ae3fe..2f9a289ab245 100644 --- a/drivers/leds/leds-turris-omnia.c +++ b/drivers/leds/leds-turris-omnia.c @@ -2,7 +2,7 @@ /* * CZ.NIC's Turris Omnia LEDs driver * - * 2020 by Marek Behun + * 2020 by Marek Behún */ #include @@ -287,6 +287,6 @@ static struct i2c_driver omnia_leds_driver = { module_i2c_driver(omnia_leds_driver); -MODULE_AUTHOR("Marek Behun "); +MODULE_AUTHOR("Marek Behun "); MODULE_DESCRIPTION("CZ.NIC's Turris Omnia LEDs"); MODULE_LICENSE("GPL v2"); diff --git a/drivers/mailbox/armada-37xx-rwtm-mailbox.c b/drivers/mailbox/armada-37xx-rwtm-mailbox.c index 9f2ce7f03c67..456a117a65fd 100644 --- a/drivers/mailbox/armada-37xx-rwtm-mailbox.c +++ b/drivers/mailbox/armada-37xx-rwtm-mailbox.c @@ -2,7 +2,7 @@ /* * rWTM BIU Mailbox driver for Armada 37xx * - * Author: Marek Behun + * Author: Marek Behún */ #include @@ -203,4 +203,4 @@ module_platform_driver(armada_37xx_mbox_driver); MODULE_LICENSE("GPL v2"); MODULE_DESCRIPTION("rWTM BIU Mailbox driver for Armada 37xx"); -MODULE_AUTHOR("Marek Behun "); +MODULE_AUTHOR("Marek Behun "); diff --git a/drivers/watchdog/armada_37xx_wdt.c b/drivers/watchdog/armada_37xx_wdt.c index e5dcb26d85f0..1635f421ef2c 100644 --- a/drivers/watchdog/armada_37xx_wdt.c +++ b/drivers/watchdog/armada_37xx_wdt.c @@ -2,7 +2,7 @@ /* * Watchdog driver for Marvell Armada 37xx SoCs * - * Author: Marek Behun + * Author: Marek Behún */ #include @@ -366,7 +366,7 @@ static struct platform_driver armada_37xx_wdt_driver = { module_platform_driver(armada_37xx_wdt_driver); -MODULE_AUTHOR("Marek Behun "); +MODULE_AUTHOR("Marek Behun "); MODULE_DESCRIPTION("Armada 37xx CPU Watchdog"); MODULE_LICENSE("GPL v2"); diff --git a/include/dt-bindings/bus/moxtet.h b/include/dt-bindings/bus/moxtet.h index dc9345440ebe..10528de7b3ef 100644 --- a/include/dt-bindings/bus/moxtet.h +++ b/include/dt-bindings/bus/moxtet.h @@ -2,7 +2,7 @@ /* * Constant for device tree bindings for Turris Mox module configuration bus * - * Copyright (C) 2019 Marek Behun + * Copyright (C) 2019 Marek Behún */ #ifndef _DT_BINDINGS_BUS_MOXTET_H diff --git a/include/linux/armada-37xx-rwtm-mailbox.h b/include/linux/armada-37xx-rwtm-mailbox.h index 57bb54f6767a..ef4bd705eb65 100644 --- a/include/linux/armada-37xx-rwtm-mailbox.h +++ b/include/linux/armada-37xx-rwtm-mailbox.h @@ -2,7 +2,7 @@ /* * rWTM BIU Mailbox driver for Armada 37xx * - * Author: Marek Behun + * Author: Marek Behún */ #ifndef _LINUX_ARMADA_37XX_RWTM_MAILBOX_H_ diff --git a/include/linux/moxtet.h b/include/linux/moxtet.h index 490db6886dcc..79184948fab4 100644 --- a/include/linux/moxtet.h +++ b/include/linux/moxtet.h @@ -2,7 +2,7 @@ /* * Turris Mox module configuration bus driver * - * Copyright (C) 2019 Marek Behun + * Copyright (C) 2019 Marek Behún */ #ifndef __LINUX_MOXTET_H From 620ff418ef440f2d585d8c8b2e9396ccfacaacd7 Mon Sep 17 00:00:00 2001 From: Jordan Crouse Date: Fri, 9 Apr 2021 13:27:07 -0700 Subject: [PATCH 0881/1091] mailmap: update email address for Jordan Crouse jcrouse at codeaurora.org has started bouncing. Redirect to a more permanent address. Link: https://lkml.kernel.org/r/20210325143700.1490518-1-jordan@cosmicpenguin.net Signed-off-by: Jordan Crouse Cc: Alexander Lobakin Cc: Jonathan Corbet Cc: Kees Cook Cc: Miguel Ojeda Cc: Thomas Bogendoerfer Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 541635d2e02e..c5642d66ce72 100644 --- a/.mailmap +++ b/.mailmap @@ -168,6 +168,7 @@ Johan Hovold Johan Hovold John Paul Adrian Glaubitz John Stultz +Jordan Crouse From a5c5e441518f1f39da7ed3ef8e61361a9ea90c8b Mon Sep 17 00:00:00 2001 From: Matthew Wilcox Date: Fri, 9 Apr 2021 13:27:10 -0700 Subject: [PATCH 0882/1091] .mailmap: fix old email addresses Update Nick & Nadia's old addresses. Link: https://lkml.kernel.org/r/20210406134036.GQ2531743@casper.infradead.org Signed-off-by: Matthew Wilcox Cc: Nicholas Piggin Cc: Nadia Yvette Chambers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- .mailmap | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/.mailmap b/.mailmap index c5642d66ce72..2d93232ed72b 100644 --- a/.mailmap +++ b/.mailmap @@ -254,8 +254,14 @@ Morten Welinder Morten Welinder Morten Welinder Mythri P K +Nadia Yvette Chambers William Lee Irwin III Nathan Chancellor Nguyen Anh Quynh +Nicholas Piggin +Nicholas Piggin +Nicholas Piggin +Nicholas Piggin +Nicholas Piggin Nicolas Ferre Nicolas Pitre Nicolas Pitre From d3378e86d1822b6d0bebfbc18a8348691c05dfa0 Mon Sep 17 00:00:00 2001 From: Aili Yao Date: Fri, 9 Apr 2021 13:27:19 -0700 Subject: [PATCH 0883/1091] mm/gup: check page posion status for coredump. When we do coredump for user process signal, this may be an SIGBUS signal with BUS_MCEERR_AR or BUS_MCEERR_AO code, which means this signal is resulted from ECC memory fail like SRAR or SRAO, we expect the memory recovery work is finished correctly, then the get_dump_page() will not return the error page as its process pte is set invalid by memory_failure(). But memory_failure() may fail, and the process's related pte may not be correctly set invalid, for current code, we will return the poison page, get it dumped, and then lead to system panic as its in kernel code. So check the poison status in get_dump_page(), and if TRUE, return NULL. There maybe other scenario that is also better to check the posion status and not to panic, so make a wrapper for this check, Thanks to David's suggestion(). [akpm@linux-foundation.org: s/0/false/] [yaoaili@kingsoft.com: is_page_poisoned() arg cannot be null, per Matthew] Link: https://lkml.kernel.org/r/20210322115233.05e4e82a@alex-virtual-machine Link: https://lkml.kernel.org/r/20210319104437.6f30e80d@alex-virtual-machine Signed-off-by: Aili Yao Cc: David Hildenbrand Cc: Matthew Wilcox Cc: Naoya Horiguchi Cc: Oscar Salvador Cc: Mike Kravetz Cc: Aili Yao Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/gup.c | 4 ++++ mm/internal.h | 20 ++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/mm/gup.c b/mm/gup.c index e40579624f10..ef7d2da9f03f 100644 --- a/mm/gup.c +++ b/mm/gup.c @@ -1535,6 +1535,10 @@ struct page *get_dump_page(unsigned long addr) FOLL_FORCE | FOLL_DUMP | FOLL_GET); if (locked) mmap_read_unlock(mm); + + if (ret == 1 && is_page_poisoned(page)) + return NULL; + return (ret == 1) ? page : NULL; } #endif /* CONFIG_ELF_CORE */ diff --git a/mm/internal.h b/mm/internal.h index 1432feec62df..cb3c5e0a7799 100644 --- a/mm/internal.h +++ b/mm/internal.h @@ -97,6 +97,26 @@ static inline void set_page_refcounted(struct page *page) set_page_count(page, 1); } +/* + * When kernel touch the user page, the user page may be have been marked + * poison but still mapped in user space, if without this page, the kernel + * can guarantee the data integrity and operation success, the kernel is + * better to check the posion status and avoid touching it, be good not to + * panic, coredump for process fatal signal is a sample case matching this + * scenario. Or if kernel can't guarantee the data integrity, it's better + * not to call this function, let kernel touch the poison page and get to + * panic. + */ +static inline bool is_page_poisoned(struct page *page) +{ + if (PageHWPoison(page)) + return true; + else if (PageHuge(page) && PageHWPoison(compound_head(page))) + return true; + + return false; +} + extern unsigned long highest_memmap_pfn; /* From a3a8833dffb7e7329c2586b8bfc531adb503f123 Mon Sep 17 00:00:00 2001 From: Mike Rapoport Date: Fri, 9 Apr 2021 13:27:23 -0700 Subject: [PATCH 0884/1091] nds32: flush_dcache_page: use page_mapping_file to avoid races with swapoff Commit cb9f753a3731 ("mm: fix races between swapoff and flush dcache") updated flush_dcache_page implementations on several architectures to use page_mapping_file() in order to avoid races between page_mapping() and swapoff(). This update missed arch/nds32 and there is a possibility of a race there. Replace page_mapping() with page_mapping_file() in nds32 implementation of flush_dcache_page(). Link: https://lkml.kernel.org/r/20210330175126.26500-1-rppt@kernel.org Fixes: cb9f753a3731 ("mm: fix races between swapoff and flush dcache") Signed-off-by: Mike Rapoport Reviewed-by: Matthew Wilcox (Oracle) Acked-by: Greentime Hu Cc: Huang Ying Cc: Nick Hu Cc: Vincent Chen Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/nds32/mm/cacheflush.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/nds32/mm/cacheflush.c b/arch/nds32/mm/cacheflush.c index 6eb98a7ad27d..ad5344ef5d33 100644 --- a/arch/nds32/mm/cacheflush.c +++ b/arch/nds32/mm/cacheflush.c @@ -238,7 +238,7 @@ void flush_dcache_page(struct page *page) { struct address_space *mapping; - mapping = page_mapping(page); + mapping = page_mapping_file(page); if (mapping && !mapping_mapped(mapping)) set_bit(PG_dcache_dirty, &page->flags); else { From 9562fd132985ea9185388a112e50f2a51557827d Mon Sep 17 00:00:00 2001 From: Nick Desaulniers Date: Fri, 9 Apr 2021 13:27:26 -0700 Subject: [PATCH 0885/1091] gcov: re-fix clang-11+ support LLVM changed the expected function signature for llvm_gcda_emit_function() in the clang-11 release. Users of clang-11 or newer may have noticed their kernels producing invalid coverage information: $ llvm-cov gcov -a -c -u -f -b .gcda -- gcno=.gcno 1 : checksum mismatch, \ (, ) != (, ) 2 Invalid .gcda File! ... Fix up the function signatures so calling this function interprets its parameters correctly and computes the correct cfg checksum. In particular, in clang-11, the additional checksum is no longer optional. Link: https://reviews.llvm.org/rG25544ce2df0daa4304c07e64b9c8b0f7df60c11d Link: https://lkml.kernel.org/r/20210408184631.1156669-1-ndesaulniers@google.com Reported-by: Prasad Sodagudi Tested-by: Prasad Sodagudi Signed-off-by: Nick Desaulniers Reviewed-by: Nathan Chancellor Cc: [5.4+] Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/gcov/clang.c | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) diff --git a/kernel/gcov/clang.c b/kernel/gcov/clang.c index 8743150db2ac..c466c7fbdece 100644 --- a/kernel/gcov/clang.c +++ b/kernel/gcov/clang.c @@ -70,7 +70,9 @@ struct gcov_fn_info { u32 ident; u32 checksum; +#if CONFIG_CLANG_VERSION < 110000 u8 use_extra_checksum; +#endif u32 cfg_checksum; u32 num_counters; @@ -145,10 +147,8 @@ void llvm_gcda_emit_function(u32 ident, const char *function_name, list_add_tail(&info->head, ¤t_info->functions); } -EXPORT_SYMBOL(llvm_gcda_emit_function); #else -void llvm_gcda_emit_function(u32 ident, u32 func_checksum, - u8 use_extra_checksum, u32 cfg_checksum) +void llvm_gcda_emit_function(u32 ident, u32 func_checksum, u32 cfg_checksum) { struct gcov_fn_info *info = kzalloc(sizeof(*info), GFP_KERNEL); @@ -158,12 +158,11 @@ void llvm_gcda_emit_function(u32 ident, u32 func_checksum, INIT_LIST_HEAD(&info->head); info->ident = ident; info->checksum = func_checksum; - info->use_extra_checksum = use_extra_checksum; info->cfg_checksum = cfg_checksum; list_add_tail(&info->head, ¤t_info->functions); } -EXPORT_SYMBOL(llvm_gcda_emit_function); #endif +EXPORT_SYMBOL(llvm_gcda_emit_function); void llvm_gcda_emit_arcs(u32 num_counters, u64 *counters) { @@ -293,11 +292,16 @@ int gcov_info_is_compatible(struct gcov_info *info1, struct gcov_info *info2) !list_is_last(&fn_ptr2->head, &info2->functions)) { if (fn_ptr1->checksum != fn_ptr2->checksum) return false; +#if CONFIG_CLANG_VERSION < 110000 if (fn_ptr1->use_extra_checksum != fn_ptr2->use_extra_checksum) return false; if (fn_ptr1->use_extra_checksum && fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum) return false; +#else + if (fn_ptr1->cfg_checksum != fn_ptr2->cfg_checksum) + return false; +#endif fn_ptr1 = list_next_entry(fn_ptr1, head); fn_ptr2 = list_next_entry(fn_ptr2, head); } @@ -529,17 +533,22 @@ static size_t convert_to_gcda(char *buffer, struct gcov_info *info) list_for_each_entry(fi_ptr, &info->functions, head) { u32 i; - u32 len = 2; - - if (fi_ptr->use_extra_checksum) - len++; pos += store_gcov_u32(buffer, pos, GCOV_TAG_FUNCTION); - pos += store_gcov_u32(buffer, pos, len); +#if CONFIG_CLANG_VERSION < 110000 + pos += store_gcov_u32(buffer, pos, + fi_ptr->use_extra_checksum ? 3 : 2); +#else + pos += store_gcov_u32(buffer, pos, 3); +#endif pos += store_gcov_u32(buffer, pos, fi_ptr->ident); pos += store_gcov_u32(buffer, pos, fi_ptr->checksum); +#if CONFIG_CLANG_VERSION < 110000 if (fi_ptr->use_extra_checksum) pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum); +#else + pos += store_gcov_u32(buffer, pos, fi_ptr->cfg_checksum); +#endif pos += store_gcov_u32(buffer, pos, GCOV_TAG_COUNTER_BASE); pos += store_gcov_u32(buffer, pos, fi_ptr->num_counters * 2); From 90bd070aae6c4fb5d302f9c4b9c88be60c8197ec Mon Sep 17 00:00:00 2001 From: Wengang Wang Date: Fri, 9 Apr 2021 13:27:29 -0700 Subject: [PATCH 0886/1091] ocfs2: fix deadlock between setattr and dio_end_io_write The following deadlock is detected: truncate -> setattr path is waiting for pending direct IO to be done (inode->i_dio_count become zero) with inode->i_rwsem held (down_write). PID: 14827 TASK: ffff881686a9af80 CPU: 20 COMMAND: "ora_p005_hrltd9" #0 __schedule at ffffffff818667cc #1 schedule at ffffffff81866de6 #2 inode_dio_wait at ffffffff812a2d04 #3 ocfs2_setattr at ffffffffc05f322e [ocfs2] #4 notify_change at ffffffff812a5a09 #5 do_truncate at ffffffff812808f5 #6 do_sys_ftruncate.constprop.18 at ffffffff81280cf2 #7 sys_ftruncate at ffffffff81280d8e #8 do_syscall_64 at ffffffff81003949 #9 entry_SYSCALL_64_after_hwframe at ffffffff81a001ad dio completion path is going to complete one direct IO (decrement inode->i_dio_count), but before that it hung at locking inode->i_rwsem: #0 __schedule+700 at ffffffff818667cc #1 schedule+54 at ffffffff81866de6 #2 rwsem_down_write_failed+536 at ffffffff8186aa28 #3 call_rwsem_down_write_failed+23 at ffffffff8185a1b7 #4 down_write+45 at ffffffff81869c9d #5 ocfs2_dio_end_io_write+180 at ffffffffc05d5444 [ocfs2] #6 ocfs2_dio_end_io+85 at ffffffffc05d5a85 [ocfs2] #7 dio_complete+140 at ffffffff812c873c #8 dio_aio_complete_work+25 at ffffffff812c89f9 #9 process_one_work+361 at ffffffff810b1889 #10 worker_thread+77 at ffffffff810b233d #11 kthread+261 at ffffffff810b7fd5 #12 ret_from_fork+62 at ffffffff81a0035e Thus above forms ABBA deadlock. The same deadlock was mentioned in upstream commit 28f5a8a7c033 ("ocfs2: should wait dio before inode lock in ocfs2_setattr()"). It seems that that commit only removed the cluster lock (the victim of above dead lock) from the ABBA deadlock party. End-user visible effects: Process hang in truncate -> ocfs2_setattr path and other processes hang at ocfs2_dio_end_io_write path. This is to fix the deadlock itself. It removes inode_lock() call from dio completion path to remove the deadlock and add ip_alloc_sem lock in setattr path to synchronize the inode modifications. [wen.gang.wang@oracle.com: remove the "had_alloc_lock" as suggested] Link: https://lkml.kernel.org/r/20210402171344.1605-1-wen.gang.wang@oracle.com Link: https://lkml.kernel.org/r/20210331203654.3911-1-wen.gang.wang@oracle.com Signed-off-by: Wengang Wang Reviewed-by: Joseph Qi Cc: Mark Fasheh Cc: Joel Becker Cc: Junxiao Bi Cc: Changwei Ge Cc: Gang He Cc: Jun Piao Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/ocfs2/aops.c | 11 +---------- fs/ocfs2/file.c | 8 ++++++-- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/fs/ocfs2/aops.c b/fs/ocfs2/aops.c index 3bfb4147895a..ad20403b383f 100644 --- a/fs/ocfs2/aops.c +++ b/fs/ocfs2/aops.c @@ -2295,7 +2295,7 @@ static int ocfs2_dio_end_io_write(struct inode *inode, struct ocfs2_alloc_context *meta_ac = NULL; handle_t *handle = NULL; loff_t end = offset + bytes; - int ret = 0, credits = 0, locked = 0; + int ret = 0, credits = 0; ocfs2_init_dealloc_ctxt(&dealloc); @@ -2306,13 +2306,6 @@ static int ocfs2_dio_end_io_write(struct inode *inode, !dwc->dw_orphaned) goto out; - /* ocfs2_file_write_iter will get i_mutex, so we need not lock if we - * are in that context. */ - if (dwc->dw_writer_pid != task_pid_nr(current)) { - inode_lock(inode); - locked = 1; - } - ret = ocfs2_inode_lock(inode, &di_bh, 1); if (ret < 0) { mlog_errno(ret); @@ -2393,8 +2386,6 @@ out: if (meta_ac) ocfs2_free_alloc_context(meta_ac); ocfs2_run_deallocs(osb, &dealloc); - if (locked) - inode_unlock(inode); ocfs2_dio_free_write_ctx(inode, dwc); return ret; diff --git a/fs/ocfs2/file.c b/fs/ocfs2/file.c index 6611c64ca0be..5edc1d0cf115 100644 --- a/fs/ocfs2/file.c +++ b/fs/ocfs2/file.c @@ -1245,22 +1245,24 @@ int ocfs2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, goto bail_unlock; } } + down_write(&OCFS2_I(inode)->ip_alloc_sem); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS + 2 * ocfs2_quota_trans_credits(sb)); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); - goto bail_unlock; + goto bail_unlock_alloc; } status = __dquot_transfer(inode, transfer_to); if (status < 0) goto bail_commit; } else { + down_write(&OCFS2_I(inode)->ip_alloc_sem); handle = ocfs2_start_trans(osb, OCFS2_INODE_UPDATE_CREDITS); if (IS_ERR(handle)) { status = PTR_ERR(handle); mlog_errno(status); - goto bail_unlock; + goto bail_unlock_alloc; } } @@ -1273,6 +1275,8 @@ int ocfs2_setattr(struct user_namespace *mnt_userns, struct dentry *dentry, bail_commit: ocfs2_commit_trans(osb, handle); +bail_unlock_alloc: + up_write(&OCFS2_I(inode)->ip_alloc_sem); bail_unlock: if (status && inode_locked) { ocfs2_inode_unlock_tracker(inode, 1, &oh, had_lock); From 7ad1e366167837daeb93d0bacb57dee820b0b898 Mon Sep 17 00:00:00 2001 From: Sergei Trofimovich Date: Fri, 9 Apr 2021 13:27:32 -0700 Subject: [PATCH 0887/1091] ia64: fix user_stack_pointer() for ptrace() ia64 has two stacks: - memory stack (or stack), pointed at by by r12 - register backing store (register stack), pointed at by ar.bsp/ar.bspstore with complications around dirty register frame on CPU. In [1] Dmitry noticed that PTRACE_GET_SYSCALL_INFO returns the register stack instead memory stack. The bug comes from the fact that user_stack_pointer() and current_user_stack_pointer() don't return the same register: ulong user_stack_pointer(struct pt_regs *regs) { return regs->ar_bspstore; } #define current_user_stack_pointer() (current_pt_regs()->r12) The change gets both back in sync. I think ptrace(PTRACE_GET_SYSCALL_INFO) is the only affected user by this bug on ia64. The change fixes 'rt_sigreturn.gen.test' strace test where it was observed initially. Link: https://bugs.gentoo.org/769614 [1] Link: https://lkml.kernel.org/r/20210331084447.2561532-1-slyfox@gentoo.org Signed-off-by: Sergei Trofimovich Reported-by: Dmitry V. Levin Cc: Oleg Nesterov Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/include/asm/ptrace.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/arch/ia64/include/asm/ptrace.h b/arch/ia64/include/asm/ptrace.h index b3aa46090101..08179135905c 100644 --- a/arch/ia64/include/asm/ptrace.h +++ b/arch/ia64/include/asm/ptrace.h @@ -54,8 +54,7 @@ static inline unsigned long user_stack_pointer(struct pt_regs *regs) { - /* FIXME: should this be bspstore + nr_dirty regs? */ - return regs->ar_bspstore; + return regs->r12; } static inline int is_syscall_success(struct pt_regs *regs) @@ -79,11 +78,6 @@ static inline long regs_return_value(struct pt_regs *regs) unsigned long __ip = instruction_pointer(regs); \ (__ip & ~3UL) + ((__ip & 3UL) << 2); \ }) -/* - * Why not default? Because user_stack_pointer() on ia64 gives register - * stack backing store instead... - */ -#define current_user_stack_pointer() (current_pt_regs()->r12) /* given a pointer to a task_struct, return the user's pt_regs */ # define task_pt_regs(t) (((struct pt_regs *) ((char *) (t) + IA64_STK_OFFSET)) - 1) From df41872b68601059dd4a84858952dcae58acd331 Mon Sep 17 00:00:00 2001 From: Jack Qiu Date: Fri, 9 Apr 2021 13:27:35 -0700 Subject: [PATCH 0888/1091] fs: direct-io: fix missing sdio->boundary I encountered a hung task issue, but not a performance one. I run DIO on a device (need lba continuous, for example open channel ssd), maybe hungtask in below case: DIO: Checkpoint: get addr A(at boundary), merge into BIO, no submit because boundary missing flush dirty data(get addr A+1), wait IO(A+1) writeback timeout, because DIO(A) didn't submit get addr A+2 fail, because checkpoint is doing dio_send_cur_page() may clear sdio->boundary, so prevent it from missing a boundary. Link: https://lkml.kernel.org/r/20210322042253.38312-1-jack.qiu@huawei.com Fixes: b1058b981272 ("direct-io: submit bio after boundary buffer is added to it") Signed-off-by: Jack Qiu Reviewed-by: Jan Kara Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- fs/direct-io.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/fs/direct-io.c b/fs/direct-io.c index b61491bf3166..b2e86e739d7a 100644 --- a/fs/direct-io.c +++ b/fs/direct-io.c @@ -812,6 +812,7 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, struct buffer_head *map_bh) { int ret = 0; + int boundary = sdio->boundary; /* dio_send_cur_page may clear it */ if (dio->op == REQ_OP_WRITE) { /* @@ -850,10 +851,10 @@ submit_page_section(struct dio *dio, struct dio_submit *sdio, struct page *page, sdio->cur_page_fs_offset = sdio->block_in_file << sdio->blkbits; out: /* - * If sdio->boundary then we want to schedule the IO now to + * If boundary then we want to schedule the IO now to * avoid metadata seeks. */ - if (sdio->boundary) { + if (boundary) { ret = dio_send_cur_page(dio, sdio, map_bh); if (sdio->bio) dio_bio_submit(dio, sdio); From 06b1f85588948bd4c772845e5d6891b8f6082248 Mon Sep 17 00:00:00 2001 From: Andrey Konovalov Date: Fri, 9 Apr 2021 13:27:38 -0700 Subject: [PATCH 0889/1091] kasan: fix conflict with page poisoning When page poisoning is enabled, it accesses memory that is marked as poisoned by KASAN, which leas to false-positive KASAN reports. Suppress the reports by adding KASAN annotations to unpoison_page() (poison_page() already has them). Link: https://lkml.kernel.org/r/2dc799014d31ac13fd97bd906bad33e16376fc67.1617118501.git.andreyknvl@google.com Signed-off-by: Andrey Konovalov Cc: Alexander Potapenko Cc: Marco Elver Cc: Dmitry Vyukov Cc: Andrey Ryabinin Cc: Andrey Konovalov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/page_poison.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/mm/page_poison.c b/mm/page_poison.c index 65cdf844c8ad..655dc5895604 100644 --- a/mm/page_poison.c +++ b/mm/page_poison.c @@ -77,12 +77,14 @@ static void unpoison_page(struct page *page) void *addr; addr = kmap_atomic(page); + kasan_disable_current(); /* * Page poisoning when enabled poisons each and every page * that is freed to buddy. Thus no extra check is done to * see if a page was poisoned. */ - check_poison_mem(addr, PAGE_SIZE); + check_poison_mem(kasan_reset_tag(addr), PAGE_SIZE); + kasan_enable_current(); kunmap_atomic(addr); } From e156656717b810202914b77557de8112df4dad0d Mon Sep 17 00:00:00 2001 From: Andrew Morton Date: Fri, 9 Apr 2021 13:27:41 -0700 Subject: [PATCH 0890/1091] lib/test_kasan_module.c: suppress unused var warning Local `unused' is intentionally unused - it is there to suppress __must_check warnings. Reported-by: kernel test robot Link: https://lkml.kernel.org/r/202104050216.HflRxfJm-lkp@intel.com Cc: Marco Elver Cc: Alexander Potapenko Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/test_kasan_module.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/test_kasan_module.c b/lib/test_kasan_module.c index eee017ff8980..f1017f345d6c 100644 --- a/lib/test_kasan_module.c +++ b/lib/test_kasan_module.c @@ -22,7 +22,7 @@ static noinline void __init copy_user_test(void) char *kmem; char __user *usermem; size_t size = 10; - int unused; + int __maybe_unused unused; kmem = kmalloc(size, GFP_KERNEL); if (!kmem) From 6a77d38efcda40f555a920909eab22ee0917fd0d Mon Sep 17 00:00:00 2001 From: Marco Elver Date: Fri, 9 Apr 2021 13:27:44 -0700 Subject: [PATCH 0891/1091] kfence, x86: fix preemptible warning on KPTI-enabled systems On systems with KPTI enabled, we can currently observe the following warning: BUG: using smp_processor_id() in preemptible caller is invalidate_user_asid+0x13/0x50 CPU: 6 PID: 1075 Comm: dmesg Not tainted 5.12.0-rc4-gda4a2b1a5479-kfence_1+ #1 Hardware name: Hewlett-Packard HP Pro 3500 Series/2ABF, BIOS 8.11 10/24/2012 Call Trace: dump_stack+0x7f/0xad check_preemption_disabled+0xc8/0xd0 invalidate_user_asid+0x13/0x50 flush_tlb_one_kernel+0x5/0x20 kfence_protect+0x56/0x80 ... While it normally makes sense to require preemption to be off, so that the expected CPU's TLB is flushed and not another, in our case it really is best-effort (see comments in kfence_protect_page()). Avoid the warning by disabling preemption around flush_tlb_one_kernel(). Link: https://lore.kernel.org/lkml/YGIDBAboELGgMgXy@elver.google.com/ Link: https://lkml.kernel.org/r/20210330065737.652669-1-elver@google.com Signed-off-by: Marco Elver Reported-by: Tomi Sarvela Cc: Alexander Potapenko Cc: Dmitry Vyukov Cc: Andrey Konovalov Cc: Jann Horn Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/x86/include/asm/kfence.h | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/arch/x86/include/asm/kfence.h b/arch/x86/include/asm/kfence.h index 97bbb4a9083a..05b48b33baf0 100644 --- a/arch/x86/include/asm/kfence.h +++ b/arch/x86/include/asm/kfence.h @@ -56,8 +56,13 @@ static inline bool kfence_protect_page(unsigned long addr, bool protect) else set_pte(pte, __pte(pte_val(*pte) | _PAGE_PRESENT)); - /* Flush this CPU's TLB. */ + /* + * Flush this CPU's TLB, assuming whoever did the allocation/free is + * likely to continue running on this CPU. + */ + preempt_disable(); flush_tlb_one_kernel(addr); + preempt_enable(); return true; } From 7d37cb2c912dc5c25ffac784a4f9b98c06c6bd08 Mon Sep 17 00:00:00 2001 From: Julian Braha Date: Fri, 9 Apr 2021 13:27:47 -0700 Subject: [PATCH 0892/1091] lib: fix kconfig dependency on ARCH_WANT_FRAME_POINTERS When LATENCYTOP, LOCKDEP, or FAULT_INJECTION_STACKTRACE_FILTER is enabled and ARCH_WANT_FRAME_POINTERS is disabled, Kbuild gives a warning such as: WARNING: unmet direct dependencies detected for FRAME_POINTER Depends on [n]: DEBUG_KERNEL [=y] && (M68K || UML || SUPERH) || ARCH_WANT_FRAME_POINTERS [=n] || MCOUNT [=n] Selected by [y]: - LATENCYTOP [=y] && DEBUG_KERNEL [=y] && STACKTRACE_SUPPORT [=y] && PROC_FS [=y] && !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM && !ARC && !X86 Depending on ARCH_WANT_FRAME_POINTERS causes a recursive dependency error. ARCH_WANT_FRAME_POINTERS is to be selected by the architecture, and is not supposed to be overridden by other config options. Link: https://lkml.kernel.org/r/20210329165329.27994-1-julianbraha@gmail.com Signed-off-by: Julian Braha Cc: Andreas Schwab Cc: Geert Uytterhoeven Cc: Necip Fazil Yildiran Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/Kconfig.debug | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug index 2779c29d9981..417c3d3e521b 100644 --- a/lib/Kconfig.debug +++ b/lib/Kconfig.debug @@ -1363,7 +1363,7 @@ config LOCKDEP bool depends on DEBUG_KERNEL && LOCK_DEBUGGING_SUPPORT select STACKTRACE - select FRAME_POINTER if !MIPS && !PPC && !ARM && !S390 && !MICROBLAZE && !ARC && !X86 + depends on FRAME_POINTER || MIPS || PPC || S390 || MICROBLAZE || ARM || ARC || X86 select KALLSYMS select KALLSYMS_ALL @@ -1665,7 +1665,7 @@ config LATENCYTOP depends on DEBUG_KERNEL depends on STACKTRACE_SUPPORT depends on PROC_FS - select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM && !ARC && !X86 + depends on FRAME_POINTER || MIPS || PPC || S390 || MICROBLAZE || ARM || ARC || X86 select KALLSYMS select KALLSYMS_ALL select STACKTRACE @@ -1918,7 +1918,7 @@ config FAULT_INJECTION_STACKTRACE_FILTER depends on FAULT_INJECTION_DEBUG_FS && STACKTRACE_SUPPORT depends on !X86_64 select STACKTRACE - select FRAME_POINTER if !MIPS && !PPC && !S390 && !MICROBLAZE && !ARM && !ARC && !X86 + depends on FRAME_POINTER || MIPS || PPC || S390 || MICROBLAZE || ARM || ARC || X86 help Provide stacktrace filter for fault-injection capabilities From a2948b17f6b936fc52f86c0f92c46d2f91928b79 Mon Sep 17 00:00:00 2001 From: Vaibhav Jain Date: Fri, 2 Apr 2021 14:55:55 +0530 Subject: [PATCH 0893/1091] libnvdimm/region: Fix nvdimm_has_flush() to handle ND_REGION_ASYNC In case a platform doesn't provide explicit flush-hints but provides an explicit flush callback via ND_REGION_ASYNC region flag, then nvdimm_has_flush() still returns '0' indicating that writes do not require flushing. This happens on PPC64 with patch at [1] applied, where 'deep_flush' of a region was denied even though an explicit flush function was provided. Fix this by adding a condition to nvdimm_has_flush() to test for the ND_REGION_ASYNC flag on the region and see if a 'region->flush' callback is assigned. Link: http://lore.kernel.org/r/161703936121.36.7260632399582101498.stgit@e1fbed493c87 [1] Fixes: c5d4355d10d4 ("libnvdimm: nd_region flush callback support") Reported-by: Shivaprasad G Bhat Signed-off-by: Vaibhav Jain Link: https://lore.kernel.org/r/20210402092555.208590-1-vaibhav@linux.ibm.com Signed-off-by: Dan Williams --- drivers/nvdimm/region_devs.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/nvdimm/region_devs.c b/drivers/nvdimm/region_devs.c index 51870eb51da6..9ccf3d608799 100644 --- a/drivers/nvdimm/region_devs.c +++ b/drivers/nvdimm/region_devs.c @@ -1246,6 +1246,11 @@ int nvdimm_has_flush(struct nd_region *nd_region) || !IS_ENABLED(CONFIG_ARCH_HAS_PMEM_API)) return -ENXIO; + /* Test if an explicit flush function is defined */ + if (test_bit(ND_REGION_ASYNC, &nd_region->flags) && nd_region->flush) + return 1; + + /* Test if any flush hints for the region are available */ for (i = 0; i < nd_region->ndr_mappings; i++) { struct nd_mapping *nd_mapping = &nd_region->mapping[i]; struct nvdimm *nvdimm = nd_mapping->nvdimm; @@ -1256,8 +1261,8 @@ int nvdimm_has_flush(struct nd_region *nd_region) } /* - * The platform defines dimm devices without hints, assume - * platform persistence mechanism like ADR + * The platform defines dimm devices without hints nor explicit flush, + * assume platform persistence mechanism like ADR */ return 0; } From 53b74fa990bf76f290aa5930abfcf37424a1a865 Mon Sep 17 00:00:00 2001 From: Naohiro Aota Date: Thu, 8 Apr 2021 17:25:28 +0900 Subject: [PATCH 0894/1091] btrfs: zoned: move superblock logging zone location Moves the location of the superblock logging zones. The new locations of the logging zones are now determined based on fixed block addresses instead of on fixed zone numbers. The old placement method based on fixed zone numbers causes problems when one needs to inspect a file system image without access to the drive zone information. In such case, the super block locations cannot be reliably determined as the zone size is unknown. By locating the superblock logging zones using fixed addresses, we can scan a dumped file system image without the zone information since a super block copy will always be present at or after the fixed known locations. Introduce the following three pairs of zones containing fixed offset locations, regardless of the device zone size. - primary superblock: offset 0B (and the following zone) - first copy: offset 512G (and the following zone) - Second copy: offset 4T (4096G, and the following zone) If a logging zone is outside of the disk capacity, we do not record the superblock copy. The first copy position is much larger than for a non-zoned filesystem, which is at 64M. This is to avoid overlapping with the log zones for the primary superblock. This higher location is arbitrary but allows supporting devices with very large zone sizes, plus some space around in between. Such large zone size is unrealistic and very unlikely to ever be seen in real devices. Currently, SMR disks have a zone size of 256MB, and we are expecting ZNS drives to be in the 1-4GB range, so this limit gives us room to breathe. For now, we only allow zone sizes up to 8GB. The maximum zone size that would still fit in the space is 256G. The fixed location addresses are somewhat arbitrary, with the intent of maintaining superblock reliability for smaller and larger devices, with the preference for the latter. For this reason, there are two superblocks under the first 1T. This should cover use cases for physical devices and for emulated/device-mapper devices. The superblock logging zones are reserved for superblock logging and never used for data or metadata blocks. Note that we only reserve the two zones per primary/copy actually used for superblock logging. We do not reserve the ranges of zones possibly containing superblocks with the largest supported zone size (0-16GB, 512G-528GB, 4096G-4112G). The zones containing the fixed location offsets used to store superblocks on a non-zoned volume are also reserved to avoid confusion. Signed-off-by: Naohiro Aota Signed-off-by: David Sterba --- fs/btrfs/zoned.c | 53 ++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/fs/btrfs/zoned.c b/fs/btrfs/zoned.c index 43948bd40e02..ba7a303300a3 100644 --- a/fs/btrfs/zoned.c +++ b/fs/btrfs/zoned.c @@ -21,9 +21,30 @@ /* Pseudo write pointer value for conventional zone */ #define WP_CONVENTIONAL ((u64)-2) +/* + * Location of the first zone of superblock logging zone pairs. + * + * - primary superblock: 0B (zone 0) + * - first copy: 512G (zone starting at that offset) + * - second copy: 4T (zone starting at that offset) + */ +#define BTRFS_SB_LOG_PRIMARY_OFFSET (0ULL) +#define BTRFS_SB_LOG_FIRST_OFFSET (512ULL * SZ_1G) +#define BTRFS_SB_LOG_SECOND_OFFSET (4096ULL * SZ_1G) + +#define BTRFS_SB_LOG_FIRST_SHIFT const_ilog2(BTRFS_SB_LOG_FIRST_OFFSET) +#define BTRFS_SB_LOG_SECOND_SHIFT const_ilog2(BTRFS_SB_LOG_SECOND_OFFSET) + /* Number of superblock log zones */ #define BTRFS_NR_SB_LOG_ZONES 2 +/* + * Maximum supported zone size. Currently, SMR disks have a zone size of + * 256MiB, and we are expecting ZNS drives to be in the 1-4GiB range. We do not + * expect the zone size to become larger than 8GiB in the near future. + */ +#define BTRFS_MAX_ZONE_SIZE SZ_8G + static int copy_zone_info_cb(struct blk_zone *zone, unsigned int idx, void *data) { struct blk_zone *zones = data; @@ -111,23 +132,22 @@ static int sb_write_pointer(struct block_device *bdev, struct blk_zone *zones, } /* - * The following zones are reserved as the circular buffer on ZONED btrfs. - * - The primary superblock: zones 0 and 1 - * - The first copy: zones 16 and 17 - * - The second copy: zones 1024 or zone at 256GB which is minimum, and - * the following one + * Get the first zone number of the superblock mirror */ static inline u32 sb_zone_number(int shift, int mirror) { - ASSERT(mirror < BTRFS_SUPER_MIRROR_MAX); + u64 zone; + ASSERT(mirror < BTRFS_SUPER_MIRROR_MAX); switch (mirror) { - case 0: return 0; - case 1: return 16; - case 2: return min_t(u64, btrfs_sb_offset(mirror) >> shift, 1024); + case 0: zone = 0; break; + case 1: zone = 1ULL << (BTRFS_SB_LOG_FIRST_SHIFT - shift); break; + case 2: zone = 1ULL << (BTRFS_SB_LOG_SECOND_SHIFT - shift); break; } - return 0; + ASSERT(zone <= U32_MAX); + + return (u32)zone; } /* @@ -300,10 +320,21 @@ int btrfs_get_dev_zone_info(struct btrfs_device *device) zone_sectors = bdev_zone_sectors(bdev); } - nr_sectors = bdev_nr_sectors(bdev); /* Check if it's power of 2 (see is_power_of_2) */ ASSERT(zone_sectors != 0 && (zone_sectors & (zone_sectors - 1)) == 0); zone_info->zone_size = zone_sectors << SECTOR_SHIFT; + + /* We reject devices with a zone size larger than 8GB */ + if (zone_info->zone_size > BTRFS_MAX_ZONE_SIZE) { + btrfs_err_in_rcu(fs_info, + "zoned: %s: zone size %llu larger than supported maximum %llu", + rcu_str_deref(device->name), + zone_info->zone_size, BTRFS_MAX_ZONE_SIZE); + ret = -EINVAL; + goto out; + } + + nr_sectors = bdev_nr_sectors(bdev); zone_info->zone_size_shift = ilog2(zone_info->zone_size); zone_info->max_zone_append_size = (u64)queue_max_zone_append_sectors(queue) << SECTOR_SHIFT; From b895bdf5d643b6feb7c60856326dd4feb6981560 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Fri, 9 Apr 2021 08:49:39 -0700 Subject: [PATCH 0895/1091] netfilter: nft_limit: avoid possible divide error in nft_limit_init div_u64() divides u64 by u32. nft_limit_init() wants to divide u64 by u64, use the appropriate math function (div64_u64) divide error: 0000 [#1] PREEMPT SMP KASAN CPU: 1 PID: 8390 Comm: syz-executor188 Not tainted 5.12.0-rc4-syzkaller #0 Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 01/01/2011 RIP: 0010:div_u64_rem include/linux/math64.h:28 [inline] RIP: 0010:div_u64 include/linux/math64.h:127 [inline] RIP: 0010:nft_limit_init+0x2a2/0x5e0 net/netfilter/nft_limit.c:85 Code: ef 4c 01 eb 41 0f 92 c7 48 89 de e8 38 a5 22 fa 4d 85 ff 0f 85 97 02 00 00 e8 ea 9e 22 fa 4c 0f af f3 45 89 ed 31 d2 4c 89 f0 <49> f7 f5 49 89 c6 e8 d3 9e 22 fa 48 8d 7d 48 48 b8 00 00 00 00 00 RSP: 0018:ffffc90009447198 EFLAGS: 00010246 RAX: 0000000000000000 RBX: 0000200000000000 RCX: 0000000000000000 RDX: 0000000000000000 RSI: ffffffff875152e6 RDI: 0000000000000003 RBP: ffff888020f80908 R08: 0000200000000000 R09: 0000000000000000 R10: ffffffff875152d8 R11: 0000000000000000 R12: ffffc90009447270 R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000 FS: 000000000097a300(0000) GS:ffff8880b9d00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: 00000000200001c4 CR3: 0000000026a52000 CR4: 00000000001506e0 DR0: 0000000000000000 DR1: 0000000000000000 DR2: 0000000000000000 DR3: 0000000000000000 DR6: 00000000fffe0ff0 DR7: 0000000000000400 Call Trace: nf_tables_newexpr net/netfilter/nf_tables_api.c:2675 [inline] nft_expr_init+0x145/0x2d0 net/netfilter/nf_tables_api.c:2713 nft_set_elem_expr_alloc+0x27/0x280 net/netfilter/nf_tables_api.c:5160 nf_tables_newset+0x1997/0x3150 net/netfilter/nf_tables_api.c:4321 nfnetlink_rcv_batch+0x85a/0x21b0 net/netfilter/nfnetlink.c:456 nfnetlink_rcv_skb_batch net/netfilter/nfnetlink.c:580 [inline] nfnetlink_rcv+0x3af/0x420 net/netfilter/nfnetlink.c:598 netlink_unicast_kernel net/netlink/af_netlink.c:1312 [inline] netlink_unicast+0x533/0x7d0 net/netlink/af_netlink.c:1338 netlink_sendmsg+0x856/0xd90 net/netlink/af_netlink.c:1927 sock_sendmsg_nosec net/socket.c:654 [inline] sock_sendmsg+0xcf/0x120 net/socket.c:674 ____sys_sendmsg+0x6e8/0x810 net/socket.c:2350 ___sys_sendmsg+0xf3/0x170 net/socket.c:2404 __sys_sendmsg+0xe5/0x1b0 net/socket.c:2433 do_syscall_64+0x2d/0x70 arch/x86/entry/common.c:46 entry_SYSCALL_64_after_hwframe+0x44/0xae Fixes: c26844eda9d4 ("netfilter: nf_tables: Fix nft limit burst handling") Fixes: 3e0f64b7dd31 ("netfilter: nft_limit: fix packet ratelimiting") Signed-off-by: Eric Dumazet Diagnosed-by: Luigi Rizzo Reported-by: syzbot Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nft_limit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netfilter/nft_limit.c b/net/netfilter/nft_limit.c index 0e2c315c3b5e..82ec27bdf941 100644 --- a/net/netfilter/nft_limit.c +++ b/net/netfilter/nft_limit.c @@ -76,13 +76,13 @@ static int nft_limit_init(struct nft_limit *limit, return -EOVERFLOW; if (pkts) { - tokens = div_u64(limit->nsecs, limit->rate) * limit->burst; + tokens = div64_u64(limit->nsecs, limit->rate) * limit->burst; } else { /* The token bucket size limits the number of tokens can be * accumulated. tokens_max specifies the bucket size. * tokens_max = unit * (rate + burst) / rate. */ - tokens = div_u64(limit->nsecs * (limit->rate + limit->burst), + tokens = div64_u64(limit->nsecs * (limit->rate + limit->burst), limit->rate); } From 7ee3c61dcd28bf6e290e06ad382f13511dc790e9 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 7 Apr 2021 21:43:39 +0200 Subject: [PATCH 0896/1091] netfilter: bridge: add pre_exit hooks for ebtable unregistration Just like ip/ip6/arptables, the hooks have to be removed, then synchronize_rcu() has to be called to make sure no more packets are being processed before the ruleset data is released. Place the hook unregistration in the pre_exit hook, then call the new ebtables pre_exit function from there. Years ago, when first netns support got added for netfilter+ebtables, this used an older (now removed) netfilter hook unregister API, that did a unconditional synchronize_rcu(). Now that all is done with call_rcu, ebtable_{filter,nat,broute} pernet exit handlers may free the ebtable ruleset while packets are still in flight. This can only happens on module removal, not during netns exit. The new function expects the table name, not the table struct. This is because upcoming patch set (targeting -next) will remove all net->xt.{nat,filter,broute}_table instances, this makes it necessary to avoid external references to those member variables. The existing APIs will be converted, so follow the upcoming scheme of passing name + hook type instead. Fixes: aee12a0a3727e ("ebtables: remove nf_hook_register usage") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter_bridge/ebtables.h | 5 ++-- net/bridge/netfilter/ebtable_broute.c | 8 +++++- net/bridge/netfilter/ebtable_filter.c | 8 +++++- net/bridge/netfilter/ebtable_nat.c | 8 +++++- net/bridge/netfilter/ebtables.c | 30 ++++++++++++++++++++--- 5 files changed, 51 insertions(+), 8 deletions(-) diff --git a/include/linux/netfilter_bridge/ebtables.h b/include/linux/netfilter_bridge/ebtables.h index 2f5c4e6ecd8a..3a956145a25c 100644 --- a/include/linux/netfilter_bridge/ebtables.h +++ b/include/linux/netfilter_bridge/ebtables.h @@ -110,8 +110,9 @@ extern int ebt_register_table(struct net *net, const struct ebt_table *table, const struct nf_hook_ops *ops, struct ebt_table **res); -extern void ebt_unregister_table(struct net *net, struct ebt_table *table, - const struct nf_hook_ops *); +extern void ebt_unregister_table(struct net *net, struct ebt_table *table); +void ebt_unregister_table_pre_exit(struct net *net, const char *tablename, + const struct nf_hook_ops *ops); extern unsigned int ebt_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct ebt_table *table); diff --git a/net/bridge/netfilter/ebtable_broute.c b/net/bridge/netfilter/ebtable_broute.c index 66e7af165494..32bc2821027f 100644 --- a/net/bridge/netfilter/ebtable_broute.c +++ b/net/bridge/netfilter/ebtable_broute.c @@ -105,14 +105,20 @@ static int __net_init broute_net_init(struct net *net) &net->xt.broute_table); } +static void __net_exit broute_net_pre_exit(struct net *net) +{ + ebt_unregister_table_pre_exit(net, "broute", &ebt_ops_broute); +} + static void __net_exit broute_net_exit(struct net *net) { - ebt_unregister_table(net, net->xt.broute_table, &ebt_ops_broute); + ebt_unregister_table(net, net->xt.broute_table); } static struct pernet_operations broute_net_ops = { .init = broute_net_init, .exit = broute_net_exit, + .pre_exit = broute_net_pre_exit, }; static int __init ebtable_broute_init(void) diff --git a/net/bridge/netfilter/ebtable_filter.c b/net/bridge/netfilter/ebtable_filter.c index 78cb9b21022d..bcf982e12f16 100644 --- a/net/bridge/netfilter/ebtable_filter.c +++ b/net/bridge/netfilter/ebtable_filter.c @@ -99,14 +99,20 @@ static int __net_init frame_filter_net_init(struct net *net) &net->xt.frame_filter); } +static void __net_exit frame_filter_net_pre_exit(struct net *net) +{ + ebt_unregister_table_pre_exit(net, "filter", ebt_ops_filter); +} + static void __net_exit frame_filter_net_exit(struct net *net) { - ebt_unregister_table(net, net->xt.frame_filter, ebt_ops_filter); + ebt_unregister_table(net, net->xt.frame_filter); } static struct pernet_operations frame_filter_net_ops = { .init = frame_filter_net_init, .exit = frame_filter_net_exit, + .pre_exit = frame_filter_net_pre_exit, }; static int __init ebtable_filter_init(void) diff --git a/net/bridge/netfilter/ebtable_nat.c b/net/bridge/netfilter/ebtable_nat.c index 0888936ef853..0d092773f816 100644 --- a/net/bridge/netfilter/ebtable_nat.c +++ b/net/bridge/netfilter/ebtable_nat.c @@ -99,14 +99,20 @@ static int __net_init frame_nat_net_init(struct net *net) &net->xt.frame_nat); } +static void __net_exit frame_nat_net_pre_exit(struct net *net) +{ + ebt_unregister_table_pre_exit(net, "nat", ebt_ops_nat); +} + static void __net_exit frame_nat_net_exit(struct net *net) { - ebt_unregister_table(net, net->xt.frame_nat, ebt_ops_nat); + ebt_unregister_table(net, net->xt.frame_nat); } static struct pernet_operations frame_nat_net_ops = { .init = frame_nat_net_init, .exit = frame_nat_net_exit, + .pre_exit = frame_nat_net_pre_exit, }; static int __init ebtable_nat_init(void) diff --git a/net/bridge/netfilter/ebtables.c b/net/bridge/netfilter/ebtables.c index ebe33b60efd6..d481ff24a150 100644 --- a/net/bridge/netfilter/ebtables.c +++ b/net/bridge/netfilter/ebtables.c @@ -1232,10 +1232,34 @@ out: return ret; } -void ebt_unregister_table(struct net *net, struct ebt_table *table, - const struct nf_hook_ops *ops) +static struct ebt_table *__ebt_find_table(struct net *net, const char *name) +{ + struct ebt_table *t; + + mutex_lock(&ebt_mutex); + + list_for_each_entry(t, &net->xt.tables[NFPROTO_BRIDGE], list) { + if (strcmp(t->name, name) == 0) { + mutex_unlock(&ebt_mutex); + return t; + } + } + + mutex_unlock(&ebt_mutex); + return NULL; +} + +void ebt_unregister_table_pre_exit(struct net *net, const char *name, const struct nf_hook_ops *ops) +{ + struct ebt_table *table = __ebt_find_table(net, name); + + if (table) + nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); +} +EXPORT_SYMBOL(ebt_unregister_table_pre_exit); + +void ebt_unregister_table(struct net *net, struct ebt_table *table) { - nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); __ebt_unregister_table(net, table); } From d163a925ebbc6eb5b562b0f1d72c7e817aa75c40 Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 7 Apr 2021 21:43:40 +0200 Subject: [PATCH 0897/1091] netfilter: arp_tables: add pre_exit hook for table unregister Same problem that also existed in iptables/ip(6)tables, when arptable_filter is removed there is no longer a wait period before the table/ruleset is free'd. Unregister the hook in pre_exit, then remove the table in the exit function. This used to work correctly because the old nf_hook_unregister API did unconditional synchronize_net. The per-net hook unregister function uses call_rcu instead. Fixes: b9e69e127397 ("netfilter: xtables: don't hook tables by default") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- include/linux/netfilter_arp/arp_tables.h | 5 +++-- net/ipv4/netfilter/arp_tables.c | 9 +++++++-- net/ipv4/netfilter/arptable_filter.c | 10 +++++++++- 3 files changed, 19 insertions(+), 5 deletions(-) diff --git a/include/linux/netfilter_arp/arp_tables.h b/include/linux/netfilter_arp/arp_tables.h index 7d3537c40ec9..26a13294318c 100644 --- a/include/linux/netfilter_arp/arp_tables.h +++ b/include/linux/netfilter_arp/arp_tables.h @@ -52,8 +52,9 @@ extern void *arpt_alloc_initial_table(const struct xt_table *); int arpt_register_table(struct net *net, const struct xt_table *table, const struct arpt_replace *repl, const struct nf_hook_ops *ops, struct xt_table **res); -void arpt_unregister_table(struct net *net, struct xt_table *table, - const struct nf_hook_ops *ops); +void arpt_unregister_table(struct net *net, struct xt_table *table); +void arpt_unregister_table_pre_exit(struct net *net, struct xt_table *table, + const struct nf_hook_ops *ops); extern unsigned int arpt_do_table(struct sk_buff *skb, const struct nf_hook_state *state, struct xt_table *table); diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index d1e04d2b5170..6c26533480dd 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1539,10 +1539,15 @@ out_free: return ret; } -void arpt_unregister_table(struct net *net, struct xt_table *table, - const struct nf_hook_ops *ops) +void arpt_unregister_table_pre_exit(struct net *net, struct xt_table *table, + const struct nf_hook_ops *ops) { nf_unregister_net_hooks(net, ops, hweight32(table->valid_hooks)); +} +EXPORT_SYMBOL(arpt_unregister_table_pre_exit); + +void arpt_unregister_table(struct net *net, struct xt_table *table) +{ __arpt_unregister_table(net, table); } diff --git a/net/ipv4/netfilter/arptable_filter.c b/net/ipv4/netfilter/arptable_filter.c index c216b9ad3bb2..6c300ba5634e 100644 --- a/net/ipv4/netfilter/arptable_filter.c +++ b/net/ipv4/netfilter/arptable_filter.c @@ -56,16 +56,24 @@ static int __net_init arptable_filter_table_init(struct net *net) return err; } +static void __net_exit arptable_filter_net_pre_exit(struct net *net) +{ + if (net->ipv4.arptable_filter) + arpt_unregister_table_pre_exit(net, net->ipv4.arptable_filter, + arpfilter_ops); +} + static void __net_exit arptable_filter_net_exit(struct net *net) { if (!net->ipv4.arptable_filter) return; - arpt_unregister_table(net, net->ipv4.arptable_filter, arpfilter_ops); + arpt_unregister_table(net, net->ipv4.arptable_filter); net->ipv4.arptable_filter = NULL; } static struct pernet_operations arptable_filter_net_ops = { .exit = arptable_filter_net_exit, + .pre_exit = arptable_filter_net_pre_exit, }; static int __init arptable_filter_init(void) From d434405aaab7d0ebc516b68a8fc4100922d7f5ef Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 11 Apr 2021 15:16:13 -0700 Subject: [PATCH 0898/1091] Linux 5.12-rc7 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index cc77fd45ca64..4730cf156f6b 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 5 PATCHLEVEL = 12 SUBLEVEL = 0 -EXTRAVERSION = -rc6 +EXTRAVERSION = -rc7 NAME = Frozen Wasteland # *DOCUMENTATION* From d2bd44c4c05d043fb65cfdf26c54e6d8b94a4b41 Mon Sep 17 00:00:00 2001 From: Angelo Dureghello Date: Sun, 28 Feb 2021 20:08:28 +0100 Subject: [PATCH 0899/1091] m68k: fix flatmem memory model setup Detected a broken boot on mcf54415, likely introduced from commit 4bfc848e0981 ("m68k/mm: enable use of generic memory_model.h for !DISCONTIGMEM") Fix ARCH_PFN_OFFSET to be a pfn. Signed-off-by: Angelo Dureghello Acked-by: Mike Rapoport Signed-off-by: Greg Ungerer --- arch/m68k/include/asm/page_mm.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/m68k/include/asm/page_mm.h b/arch/m68k/include/asm/page_mm.h index 9e8f0cc30a2c..2411ea9ef578 100644 --- a/arch/m68k/include/asm/page_mm.h +++ b/arch/m68k/include/asm/page_mm.h @@ -167,7 +167,7 @@ static inline __attribute_const__ int __virt_to_node_shift(void) ((__p) - pgdat->node_mem_map) + pgdat->node_start_pfn; \ }) #else -#define ARCH_PFN_OFFSET (m68k_memory[0].addr) +#define ARCH_PFN_OFFSET (m68k_memory[0].addr >> PAGE_SHIFT) #include #endif From 4af2178ac605faf32ebe638f7ac17d841d40ea9b Mon Sep 17 00:00:00 2001 From: Joakim Zhang Date: Fri, 9 Apr 2021 17:11:45 +0800 Subject: [PATCH 0900/1091] MAINTAINERS: update maintainer entry for freescale fec driver Update maintainer entry for freescale fec driver. Suggested-by: Heiner Kallweit Signed-off-by: Joakim Zhang Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index ccd9228350cf..163264c282eb 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -7089,7 +7089,7 @@ S: Maintained F: drivers/i2c/busses/i2c-cpm.c FREESCALE IMX / MXC FEC DRIVER -M: Fugang Duan +M: Joakim Zhang L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/fsl-fec.txt From 31457db3750c0b0ed229d836f2609fdb8a5b790e Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 11 Apr 2021 11:02:08 +0200 Subject: [PATCH 0901/1091] net: davicom: Fix regulator not turned off on failed probe When the probe fails, we must disable the regulator that was previously enabled. This patch is a follow-up to commit ac88c531a5b3 ("net: davicom: Fix regulator not turned off on failed probe") which missed one case. Fixes: 7994fe55a4a2 ("dm9000: Add regulator and reset support to dm9000") Signed-off-by: Christophe JAILLET Signed-off-by: David S. Miller --- drivers/net/ethernet/davicom/dm9000.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 252adfa5d837..8a9096aa85cd 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1471,8 +1471,10 @@ dm9000_probe(struct platform_device *pdev) /* Init network device */ ndev = alloc_etherdev(sizeof(struct board_info)); - if (!ndev) - return -ENOMEM; + if (!ndev) { + ret = -ENOMEM; + goto out_regulator_disable; + } SET_NETDEV_DEV(ndev, &pdev->dev); From 6628ddfec7580882f11fdc5c194a8ea781fdadfa Mon Sep 17 00:00:00 2001 From: Phillip Potter Date: Sun, 11 Apr 2021 12:28:24 +0100 Subject: [PATCH 0902/1091] net: geneve: check skb is large enough for IPv4/IPv6 header Check within geneve_xmit_skb/geneve6_xmit_skb that sk_buff structure is large enough to include IPv4 or IPv6 header, and reject if not. The geneve_xmit_skb portion and overall idea was contributed by Eric Dumazet. Fixes a KMSAN-found uninit-value bug reported by syzbot at: https://syzkaller.appspot.com/bug?id=abe95dc3e3e9667fc23b8d81f29ecad95c6f106f Suggested-by: Eric Dumazet Reported-by: syzbot+2e406a9ac75bb71d4b7a@syzkaller.appspotmail.com Signed-off-by: Phillip Potter Signed-off-by: Eric Dumazet Signed-off-by: David S. Miller --- drivers/net/geneve.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index d5b1e48e0c09..42f31c681846 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -891,6 +891,9 @@ static int geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; + if (!pskb_network_may_pull(skb, sizeof(struct iphdr))) + return -EINVAL; + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); rt = geneve_get_v4_rt(skb, dev, gs4, &fl4, info, geneve->cfg.info.key.tp_dst, sport); @@ -985,6 +988,9 @@ static int geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev, __be16 sport; int err; + if (!pskb_network_may_pull(skb, sizeof(struct ipv6hdr))) + return -EINVAL; + sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true); dst = geneve_get_v6_dst(skb, dev, gs6, &fl6, info, geneve->cfg.info.key.tp_dst, sport); From ea941ac294d75d0ace50797aebf0056f6f8f7a7f Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Tue, 16 Feb 2021 17:13:42 -0700 Subject: [PATCH 0903/1091] dmaengine: idxd: Fix clobbering of SWERR overflow bit on writeback Current code blindly writes over the SWERR and the OVERFLOW bits. Write back the bits actually read instead so the driver avoids clobbering the OVERFLOW bit that comes after the register is read. Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Reported-by: Sanjay Kumar Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/161352082229.3511254.1002151220537623503.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/irq.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/dma/idxd/irq.c b/drivers/dma/idxd/irq.c index a60ca11a5784..f1463fc58112 100644 --- a/drivers/dma/idxd/irq.c +++ b/drivers/dma/idxd/irq.c @@ -124,7 +124,9 @@ static int process_misc_interrupts(struct idxd_device *idxd, u32 cause) for (i = 0; i < 4; i++) idxd->sw_err.bits[i] = ioread64(idxd->reg_base + IDXD_SWERR_OFFSET + i * sizeof(u64)); - iowrite64(IDXD_SWERR_ACK, idxd->reg_base + IDXD_SWERR_OFFSET); + + iowrite64(idxd->sw_err.bits[0] & IDXD_SWERR_ACK, + idxd->reg_base + IDXD_SWERR_OFFSET); if (idxd->sw_err.valid && idxd->sw_err.wq_idx_valid) { int id = idxd->sw_err.wq_idx; From 4ac823e9cd85f66da274c951d21bf9f6b714b729 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Mon, 22 Mar 2021 16:36:25 -0700 Subject: [PATCH 0904/1091] dmaengine: idxd: fix delta_rec and crc size field for completion record The delta_rec_size and crc_val in the completion record should be 32bits and not 16bits. Fixes: bfe1d56091c1 ("dmaengine: idxd: Init and probe for Intel data accelerators") Reported-by: Nikhil Rao Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/161645618572.2003490.14466173451736323035.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- include/uapi/linux/idxd.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/include/uapi/linux/idxd.h b/include/uapi/linux/idxd.h index 236d437947bc..e33997b4d750 100644 --- a/include/uapi/linux/idxd.h +++ b/include/uapi/linux/idxd.h @@ -247,8 +247,8 @@ struct dsa_completion_record { uint32_t rsvd2:8; }; - uint16_t delta_rec_size; - uint16_t crc_val; + uint32_t delta_rec_size; + uint32_t crc_val; /* DIF check & strip */ struct { From ea6a5735d2a61b938a302eb3629272342a9e7c46 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Mon, 22 Mar 2021 16:37:29 -0700 Subject: [PATCH 0905/1091] dmaengine: idxd: fix opcap sysfs attribute output The operation capability register is 256bits. The current output only prints out the first 64bits. Fix to output the entire 256bits. The current code omits operation caps from IAX devices. Fixes: c52ca478233c ("dmaengine: idxd: add configuration component of driver") Reported-by: Lucas Van Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/161645624963.2003736.829798666998490151.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/sysfs.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index 4dbb03c545e4..c27ca01cf8b2 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -1449,8 +1449,14 @@ static ssize_t op_cap_show(struct device *dev, { struct idxd_device *idxd = container_of(dev, struct idxd_device, conf_dev); + int i, rc = 0; - return sprintf(buf, "%#llx\n", idxd->hw.opcap.bits[0]); + for (i = 0; i < 4; i++) + rc += sysfs_emit_at(buf, rc, "%#llx ", idxd->hw.opcap.bits[i]); + + rc--; + rc += sysfs_emit_at(buf, rc, "\n"); + return rc; } static DEVICE_ATTR_RO(op_cap); From 0fff71c5a311e1264988179f7dcc217fda15fadd Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Wed, 7 Apr 2021 12:59:47 -0700 Subject: [PATCH 0906/1091] dmaengine: idxd: fix wq size store permission state WQ size can only be changed when the device is disabled. Current code allows change when device is enabled but wq is disabled. Change the check to detect device state. Fixes: c52ca478233c ("dmaengine: idxd: add configuration component of driver") Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/161782558755.107710.18138252584838406025.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/sysfs.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index c27ca01cf8b2..5f7bc4b1621a 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -989,7 +989,7 @@ static ssize_t wq_size_store(struct device *dev, if (!test_bit(IDXD_FLAG_CONFIGURABLE, &idxd->flags)) return -EPERM; - if (wq->state != IDXD_WQ_DISABLED) + if (idxd->state == IDXD_DEV_ENABLED) return -EPERM; if (size + total_claimed_wq_size(idxd) - wq->size > idxd->max_wq_size) From 88cd1d6191b13689094310c2405394e4ce36d061 Mon Sep 17 00:00:00 2001 From: Andy Shevchenko Date: Wed, 24 Mar 2021 16:17:57 +0200 Subject: [PATCH 0907/1091] dmaengine: dw: Make it dependent to HAS_IOMEM Some architectures do not provide devm_*() APIs. Hence make the driver dependent on HAVE_IOMEM. Fixes: dbde5c2934d1 ("dw_dmac: use devm_* functions to simplify code") Reported-by: kernel test robot Signed-off-by: Andy Shevchenko Acked-by: Viresh Kumar Link: https://lore.kernel.org/r/20210324141757.24710-1-andriy.shevchenko@linux.intel.com Signed-off-by: Vinod Koul --- drivers/dma/dw/Kconfig | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/dma/dw/Kconfig b/drivers/dma/dw/Kconfig index e5162690de8f..db25f9b7778c 100644 --- a/drivers/dma/dw/Kconfig +++ b/drivers/dma/dw/Kconfig @@ -10,6 +10,7 @@ config DW_DMAC_CORE config DW_DMAC tristate "Synopsys DesignWare AHB DMA platform driver" + depends on HAS_IOMEM select DW_DMAC_CORE help Support the Synopsys DesignWare AHB DMA controller. This @@ -18,6 +19,7 @@ config DW_DMAC config DW_DMAC_PCI tristate "Synopsys DesignWare AHB DMA PCI driver" depends on PCI + depends on HAS_IOMEM select DW_DMAC_CORE help Support the Synopsys DesignWare AHB DMA controller on the From ea45b6008f8095db0cc09ad6e03c7785c2986197 Mon Sep 17 00:00:00 2001 From: Lv Yunlong Date: Tue, 30 Mar 2021 18:44:58 -0700 Subject: [PATCH 0908/1091] dmaengine: Fix a double free in dma_async_device_register In the first list_for_each_entry() macro of dma_async_device_register, it gets the chan from list and calls __dma_async_device_channel_register (..,chan). We can see that chan->local is allocated by alloc_percpu() and it is freed chan->local by free_percpu(chan->local) when __dma_async_device_channel_register() failed. But after __dma_async_device_channel_register() failed, the caller will goto err_out and freed the chan->local in the second time by free_percpu(). The cause of this problem is forget to set chan->local to NULL when chan->local was freed in __dma_async_device_channel_register(). My patch sets chan->local to NULL when the callee failed to avoid double free. Fixes: d2fb0a0438384 ("dmaengine: break out channel registration") Signed-off-by: Lv Yunlong Reviewed-by: Dave Jiang Link: https://lore.kernel.org/r/20210331014458.3944-1-lyl2019@mail.ustc.edu.cn Signed-off-by: Vinod Koul --- drivers/dma/dmaengine.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c index fe6a460c4373..af3ee288bc11 100644 --- a/drivers/dma/dmaengine.c +++ b/drivers/dma/dmaengine.c @@ -1086,6 +1086,7 @@ static int __dma_async_device_channel_register(struct dma_device *device, kfree(chan->dev); err_free_local: free_percpu(chan->local); + chan->local = NULL; return rc; } From 917a3200b9f467a154999c7572af345f2470aaf4 Mon Sep 17 00:00:00 2001 From: Dinghao Liu Date: Fri, 9 Apr 2021 16:28:05 +0800 Subject: [PATCH 0909/1091] dmaengine: tegra20: Fix runtime PM imbalance on error pm_runtime_get_sync() will increase the runtime PM counter even it returns an error. Thus a pairing decrement is needed to prevent refcount leak. Fix this by replacing this API with pm_runtime_resume_and_get(), which will not change the runtime PM counter on error. Signed-off-by: Dinghao Liu Acked-by: Thierry Reding Link: https://lore.kernel.org/r/20210409082805.23643-1-dinghao.liu@zju.edu.cn Signed-off-by: Vinod Koul --- drivers/dma/tegra20-apb-dma.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/dma/tegra20-apb-dma.c b/drivers/dma/tegra20-apb-dma.c index 71827d9b0aa1..b7260749e8ee 100644 --- a/drivers/dma/tegra20-apb-dma.c +++ b/drivers/dma/tegra20-apb-dma.c @@ -723,7 +723,7 @@ static void tegra_dma_issue_pending(struct dma_chan *dc) goto end; } if (!tdc->busy) { - err = pm_runtime_get_sync(tdc->tdma->dev); + err = pm_runtime_resume_and_get(tdc->tdma->dev); if (err < 0) { dev_err(tdc2dev(tdc), "Failed to enable DMA\n"); goto end; @@ -818,7 +818,7 @@ static void tegra_dma_synchronize(struct dma_chan *dc) struct tegra_dma_channel *tdc = to_tegra_dma_chan(dc); int err; - err = pm_runtime_get_sync(tdc->tdma->dev); + err = pm_runtime_resume_and_get(tdc->tdma->dev); if (err < 0) { dev_err(tdc2dev(tdc), "Failed to synchronize DMA: %d\n", err); return; From 07503e6aefe4a6efd777062191944a14f03b3a18 Mon Sep 17 00:00:00 2001 From: Dan Carpenter Date: Tue, 23 Mar 2021 16:19:59 +0300 Subject: [PATCH 0910/1091] dmaengine: plx_dma: add a missing put_device() on error path Add a missing put_device(&pdev->dev) if the call to dma_async_device_register(dma); fails. Fixes: 905ca51e63be ("dmaengine: plx-dma: Introduce PLX DMA engine PCI driver skeleton") Signed-off-by: Dan Carpenter Reviewed-by: Logan Gunthorpe Link: https://lore.kernel.org/r/YFnq/0IQzixtAbC1@mwanda Signed-off-by: Vinod Koul --- drivers/dma/plx_dma.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/drivers/dma/plx_dma.c b/drivers/dma/plx_dma.c index f387c5bbc170..166934544161 100644 --- a/drivers/dma/plx_dma.c +++ b/drivers/dma/plx_dma.c @@ -507,10 +507,8 @@ static int plx_dma_create(struct pci_dev *pdev) rc = request_irq(pci_irq_vector(pdev, 0), plx_dma_isr, 0, KBUILD_MODNAME, plxdev); - if (rc) { - kfree(plxdev); - return rc; - } + if (rc) + goto free_plx; spin_lock_init(&plxdev->ring_lock); tasklet_setup(&plxdev->desc_task, plx_dma_desc_task); @@ -540,14 +538,20 @@ static int plx_dma_create(struct pci_dev *pdev) rc = dma_async_device_register(dma); if (rc) { pci_err(pdev, "Failed to register dma device: %d\n", rc); - free_irq(pci_irq_vector(pdev, 0), plxdev); - kfree(plxdev); - return rc; + goto put_device; } pci_set_drvdata(pdev, plxdev); return 0; + +put_device: + put_device(&pdev->dev); + free_irq(pci_irq_vector(pdev, 0), plxdev); +free_plx: + kfree(plxdev); + + return rc; } static int plx_dma_probe(struct pci_dev *pdev, From b74e409ea1b18128b877a50883d92a12eba83c33 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Fri, 9 Apr 2021 00:13:18 +0200 Subject: [PATCH 0911/1091] s390/entry: avoid setting up backchain in ext|io handlers Currently when interrupt arrives to cpu while in kernel context INT_HANDLER macro (used for ext_int_handler and io_int_handler) allocates new stack frame and pt_regs on the kernel stack and sets up the backchain to jump over the pt_regs to the frame which has been interrupted. This is not ideal to two reasons: 1. This hides the fact that kernel stack contains interrupt frame in it and hence breaks arch_stack_walk_reliable(), which needs to know that to guarantee "reliability" and checks that there are no pt_regs on the way. 2. It breaks the backchain unwinder logic, which assumes that the next stack frame after an interrupt frame is reliable, while it is not. In some cases (when r14 contains garbage) this leads to early unwinding termination with an error, instead of marking frame as unreliable and continuing. To address that, only set backchain to 0. Fixes: 56e62a737028 ("s390: convert to generic entry") Reviewed-by: Sven Schnelle Signed-off-by: Vasily Gorbik Signed-off-by: Heiko Carstens --- arch/s390/kernel/entry.S | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index c10b9f31eef7..235bf2ac3359 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -401,15 +401,13 @@ ENTRY(\name) brasl %r14,.Lcleanup_sie_int #endif 0: CHECK_STACK __LC_SAVE_AREA_ASYNC - lgr %r11,%r15 aghi %r15,-(STACK_FRAME_OVERHEAD + __PT_SIZE) - stg %r11,__SF_BACKCHAIN(%r15) j 2f 1: BPENTER __TI_flags(%r12),_TIF_ISOLATE_BP lctlg %c1,%c1,__LC_KERNEL_ASCE lg %r15,__LC_KERNEL_STACK - xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) -2: la %r11,STACK_FRAME_OVERHEAD(%r15) +2: xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15) + la %r11,STACK_FRAME_OVERHEAD(%r15) stmg %r0,%r7,__PT_R0(%r11) # clear user controlled registers to prevent speculative use xgr %r0,%r0 From a994eddb947ea9ebb7b14d9a1267001699f0a136 Mon Sep 17 00:00:00 2001 From: Vasily Gorbik Date: Fri, 9 Apr 2021 00:15:21 +0200 Subject: [PATCH 0912/1091] s390/entry: save the caller of psw_idle Currently psw_idle does not allocate a stack frame and does not save its r14 and r15 into the save area. Even though this is valid from call ABI point of view, because psw_idle does not make any calls explicitly, in reality psw_idle is an entry point for controlled transition into serving interrupts. So, in practice, psw_idle stack frame is analyzed during stack unwinding. Depending on build options that r14 slot in the save area of psw_idle might either contain a value saved by previous sibling call or complete garbage. [task 0000038000003c28] do_ext_irq+0xd6/0x160 [task 0000038000003c78] ext_int_handler+0xba/0xe8 [task *0000038000003dd8] psw_idle_exit+0x0/0x8 <-- pt_regs ([task 0000038000003dd8] 0x0) [task 0000038000003e10] default_idle_call+0x42/0x148 [task 0000038000003e30] do_idle+0xce/0x160 [task 0000038000003e70] cpu_startup_entry+0x36/0x40 [task 0000038000003ea0] arch_call_rest_init+0x76/0x80 So, to make a stacktrace nicer and actually point for the real caller of psw_idle in this frequently occurring case, make psw_idle save its r14. [task 0000038000003c28] do_ext_irq+0xd6/0x160 [task 0000038000003c78] ext_int_handler+0xba/0xe8 [task *0000038000003dd8] psw_idle_exit+0x0/0x6 <-- pt_regs ([task 0000038000003dd8] arch_cpu_idle+0x3c/0xd0) [task 0000038000003e10] default_idle_call+0x42/0x148 [task 0000038000003e30] do_idle+0xce/0x160 [task 0000038000003e70] cpu_startup_entry+0x36/0x40 [task 0000038000003ea0] arch_call_rest_init+0x76/0x80 Reviewed-by: Sven Schnelle Signed-off-by: Vasily Gorbik Signed-off-by: Heiko Carstens --- arch/s390/kernel/entry.S | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 235bf2ac3359..12de7a9c85b3 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -443,6 +443,7 @@ INT_HANDLER io_int_handler,__LC_IO_OLD_PSW,do_io_irq * Load idle PSW. */ ENTRY(psw_idle) + stg %r14,(__SF_GPRS+8*8)(%r15) stg %r3,__SF_EMPTY(%r15) larl %r1,psw_idle_exit stg %r1,__SF_EMPTY+8(%r15) From 11664169981a025b7f6072d136ac724294b7b65c Mon Sep 17 00:00:00 2001 From: Lyude Paul Date: Thu, 18 Mar 2021 13:02:02 -0400 Subject: [PATCH 0913/1091] drm/i915/dpcd_bl: Don't try vesa interface unless specified by VBT Looks like that there actually are another subset of laptops on the market that don't support the Intel HDR backlight interface, but do advertise support for the VESA DPCD backlight interface despite the fact it doesn't seem to work. Note though I'm not entirely clear on this - on one of the machines where this issue was observed, I also noticed that we appeared to be rejecting the VBT defined backlight frequency in intel_dp_aux_vesa_calc_max_backlight(). It's noted in this function that: /* Use highest possible value of Pn for more granularity of brightness * adjustment while satifying the conditions below. * ... * - FxP is within 25% of desired value. * Note: 25% is arbitrary value and may need some tweak. */ So it's possible that this value might just need to be tweaked, but for now let's just disable the VESA backlight interface unless it's specified in the VBT just to be safe. We might be able to try enabling this again by default in the future. Fixes: 2227816e647a ("drm/i915/dp: Allow forcing specific interfaces through enable_dpcd_backlight") Cc: Jani Nikula Cc: Rodrigo Vivi Bugzilla: https://gitlab.freedesktop.org/drm/intel/-/issues/3169 Signed-off-by: Lyude Paul Reviewed-by: Jani Nikula Link: https://patchwork.freedesktop.org/patch/msgid/20210318170204.513000-1-lyude@redhat.com (cherry picked from commit 9e2eb6d5380e9dadcd2baecb51f238e5eba94bee) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c | 1 - 1 file changed, 1 deletion(-) diff --git a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c index 651884390137..4f8337c7fd2e 100644 --- a/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c +++ b/drivers/gpu/drm/i915/display/intel_dp_aux_backlight.c @@ -646,7 +646,6 @@ int intel_dp_aux_init_backlight_funcs(struct intel_connector *connector) break; case INTEL_BACKLIGHT_DISPLAY_DDI: try_intel_interface = true; - try_vesa_interface = true; break; default: return -ENODEV; From bf52dc49ba0101f648b4c3ea26b812061406b0d4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ville=20Syrj=C3=A4l=C3=A4?= Date: Sat, 27 Mar 2021 02:59:45 +0200 Subject: [PATCH 0914/1091] drm/i915: Don't zero out the Y plane's watermarks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Don't zero out the watermarks for the Y plane since we've already computed them when computing the UV plane's watermarks (since the UV plane always appears before ethe Y plane when iterating through the planes). This leads to allocating no DDB for the Y plane since .min_ddb_alloc also gets zeroed. And that of course leads to underruns when scanning out planar formats. Cc: stable@vger.kernel.org Cc: Stanislav Lisovskiy Fixes: dbf71381d733 ("drm/i915: Nuke intel_atomic_crtc_state_for_each_plane_state() from skl+ wm code") Signed-off-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20210327005945.4929-1-ville.syrjala@linux.intel.com Reviewed-by: Stanislav Lisovskiy (cherry picked from commit f99b805fb9413ff007ca0b6add871737664117dd) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/intel_pm.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/intel_pm.c b/drivers/gpu/drm/i915/intel_pm.c index 97b57acc02e2..4b4d8d034782 100644 --- a/drivers/gpu/drm/i915/intel_pm.c +++ b/drivers/gpu/drm/i915/intel_pm.c @@ -5471,12 +5471,12 @@ static int icl_build_plane_wm(struct intel_crtc_state *crtc_state, struct skl_plane_wm *wm = &crtc_state->wm.skl.raw.planes[plane_id]; int ret; - memset(wm, 0, sizeof(*wm)); - /* Watermarks calculated in master */ if (plane_state->planar_slave) return 0; + memset(wm, 0, sizeof(*wm)); + if (plane_state->planar_linked_plane) { const struct drm_framebuffer *fb = plane_state->hw.fb; enum plane_id y_plane_id = plane_state->planar_linked_plane->id; From aee6f25e9c911323aa89a200e1bb160c1613ed3d Mon Sep 17 00:00:00 2001 From: Hans de Goede Date: Thu, 25 Mar 2021 12:48:22 +0100 Subject: [PATCH 0915/1091] drm/i915/display/vlv_dsi: Do not skip panel_pwr_cycle_delay when disabling the panel MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit After the recently added commit fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot"), the DSI panel on a Cherry Trail based Predia Basic tablet would no longer properly light up after reboot. I've managed to reproduce this without rebooting by doing: chvt 3; echo 1 > /sys/class/graphics/fb0/blank;\ echo 0 > /sys/class/graphics/fb0/blank Which rapidly turns the panel off and back on again. The vlv_dsi.c code uses an intel_dsi_msleep() helper for the various delays used for panel on/off, since starting with MIPI-sequences version >= 3 the delays are already included inside the MIPI-sequences. The problems exposed by the "Shut down displays gracefully on reboot" change, show that using this helper for the panel_pwr_cycle_delay is not the right thing to do. This has not been noticed until now because normally the panel never is cycled off and directly on again in quick succession. Change the msleep for the panel_pwr_cycle_delay to a normal msleep() call to avoid the panel staying black after a quick off + on cycle. Cc: Ville Syrjälä Fixes: fe0f1e3bfdfe ("drm/i915: Shut down displays gracefully on reboot") Signed-off-by: Hans de Goede Reviewed-by: Ville Syrjälä Link: https://patchwork.freedesktop.org/patch/msgid/20210325114823.44922-1-hdegoede@redhat.com (cherry picked from commit 2878b29fc25a0dac0e1c6c94177f07c7f94240f0) Signed-off-by: Rodrigo Vivi --- drivers/gpu/drm/i915/display/vlv_dsi.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/gpu/drm/i915/display/vlv_dsi.c b/drivers/gpu/drm/i915/display/vlv_dsi.c index f94025ec603a..a9a8ba1d3aba 100644 --- a/drivers/gpu/drm/i915/display/vlv_dsi.c +++ b/drivers/gpu/drm/i915/display/vlv_dsi.c @@ -992,14 +992,14 @@ static void intel_dsi_post_disable(struct intel_atomic_state *state, * FIXME As we do with eDP, just make a note of the time here * and perform the wait before the next panel power on. */ - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); + msleep(intel_dsi->panel_pwr_cycle_delay); } static void intel_dsi_shutdown(struct intel_encoder *encoder) { struct intel_dsi *intel_dsi = enc_to_intel_dsi(encoder); - intel_dsi_msleep(intel_dsi, intel_dsi->panel_pwr_cycle_delay); + msleep(intel_dsi->panel_pwr_cycle_delay); } static bool intel_dsi_get_hw_state(struct intel_encoder *encoder, From 2decad92f4731fac9755a083fcfefa66edb7d67d Mon Sep 17 00:00:00 2001 From: Catalin Marinas Date: Fri, 9 Apr 2021 18:37:10 +0100 Subject: [PATCH 0916/1091] arm64: mte: Ensure TIF_MTE_ASYNC_FAULT is set atomically The entry from EL0 code checks the TFSRE0_EL1 register for any asynchronous tag check faults in user space and sets the TIF_MTE_ASYNC_FAULT flag. This is not done atomically, potentially racing with another CPU calling set_tsk_thread_flag(). Replace the non-atomic ORR+STR with an STSET instruction. While STSET requires ARMv8.1 and an assembler that understands LSE atomics, the MTE feature is part of ARMv8.5 and already requires an updated assembler. Signed-off-by: Catalin Marinas Fixes: 637ec831ea4f ("arm64: mte: Handle synchronous and asynchronous tag check faults") Cc: # 5.10.x Reported-by: Will Deacon Cc: Will Deacon Cc: Vincenzo Frascino Cc: Mark Rutland Link: https://lore.kernel.org/r/20210409173710.18582-1-catalin.marinas@arm.com Signed-off-by: Will Deacon --- arch/arm64/Kconfig | 6 +++++- arch/arm64/kernel/entry.S | 10 ++++++---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index e4e1b6550115..dfdc3e0af5e1 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1406,10 +1406,13 @@ config ARM64_PAN config AS_HAS_LDAPR def_bool $(as-instr,.arch_extension rcpc) +config AS_HAS_LSE_ATOMICS + def_bool $(as-instr,.arch_extension lse) + config ARM64_LSE_ATOMICS bool default ARM64_USE_LSE_ATOMICS - depends on $(as-instr,.arch_extension lse) + depends on AS_HAS_LSE_ATOMICS config ARM64_USE_LSE_ATOMICS bool "Atomic instructions" @@ -1666,6 +1669,7 @@ config ARM64_MTE default y depends on ARM64_AS_HAS_MTE && ARM64_TAGGED_ADDR_ABI depends on AS_HAS_ARMV8_5 + depends on AS_HAS_LSE_ATOMICS # Required for tag checking in the uaccess routines depends on ARM64_PAN select ARCH_USES_HIGH_VMA_FLAGS diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S index a31a0a713c85..6acfc5e6b5e0 100644 --- a/arch/arm64/kernel/entry.S +++ b/arch/arm64/kernel/entry.S @@ -148,16 +148,18 @@ alternative_cb_end .endm /* Check for MTE asynchronous tag check faults */ - .macro check_mte_async_tcf, flgs, tmp + .macro check_mte_async_tcf, tmp, ti_flags #ifdef CONFIG_ARM64_MTE + .arch_extension lse alternative_if_not ARM64_MTE b 1f alternative_else_nop_endif mrs_s \tmp, SYS_TFSRE0_EL1 tbz \tmp, #SYS_TFSR_EL1_TF0_SHIFT, 1f /* Asynchronous TCF occurred for TTBR0 access, set the TI flag */ - orr \flgs, \flgs, #_TIF_MTE_ASYNC_FAULT - str \flgs, [tsk, #TSK_TI_FLAGS] + mov \tmp, #_TIF_MTE_ASYNC_FAULT + add \ti_flags, tsk, #TSK_TI_FLAGS + stset \tmp, [\ti_flags] msr_s SYS_TFSRE0_EL1, xzr 1: #endif @@ -244,7 +246,7 @@ alternative_else_nop_endif disable_step_tsk x19, x20 /* Check for asynchronous tag check faults in user space */ - check_mte_async_tcf x19, x22 + check_mte_async_tcf x22, x23 apply_ssbd 1, x22, x23 ptrauth_keys_install_kernel tsk, x20, x22, x23 From 3bcae98e101727457c727b354c95c3ea8f074dce Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 9 Apr 2021 15:09:58 -0700 Subject: [PATCH 0917/1091] ASoC: SOF: core: Add missing error prints to device probe operation Two error cases in snd_sof_device_probe() and sof_probe_continue() are missing error prints. If either of them happens it is not possible to identify the reason for the failure. Add dev_err() prints for the cases to aim debugging. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220959.1543456-2-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/core.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 495295a34c3a..f57e363b5974 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -232,8 +232,11 @@ static int sof_probe_continue(struct snd_sof_dev *sdev) } ret = snd_sof_machine_register(sdev, plat_data); - if (ret < 0) + if (ret < 0) { + dev_err(sdev->dev, + "error: failed to register machine driver %d\n", ret); goto fw_trace_err; + } /* * Some platforms in SOF, ex: BYT, may not have their platform PM @@ -309,8 +312,10 @@ int snd_sof_device_probe(struct device *dev, struct snd_sof_pdata *plat_data) !sof_ops(sdev)->block_read || !sof_ops(sdev)->block_write || !sof_ops(sdev)->send_msg || !sof_ops(sdev)->load_firmware || !sof_ops(sdev)->ipc_msg_data || !sof_ops(sdev)->ipc_pcm_params || - !sof_ops(sdev)->fw_ready) + !sof_ops(sdev)->fw_ready) { + dev_err(dev, "error: missing mandatory ops\n"); return -EINVAL; + } INIT_LIST_HEAD(&sdev->pcm_list); INIT_LIST_HEAD(&sdev->kcontrol_list); From 4d1284cd795296e4aa7be6db5fdce85f31374520 Mon Sep 17 00:00:00 2001 From: Peter Ujfalusi Date: Fri, 9 Apr 2021 15:09:59 -0700 Subject: [PATCH 0918/1091] ASoC: SOF: Simplify sof_probe_complete handling for acpi/pci/of Set the sof_data->sof_probe_complete callback unconditionally of CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE. The sof_probe_complete will be called when the sof_probe_continue() function is successfully executed, called either directly from snd_sof_device_probe() or from the scheduled work. Since all error cases within the call chain of snd_sof_device_probe() have error prints, there is no need to print again in the acpi/pci/of level. Signed-off-by: Peter Ujfalusi Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220959.1543456-3-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-acpi-dev.c | 18 +++--------------- sound/soc/sof/sof-of-dev.c | 18 +++--------------- sound/soc/sof/sof-pci-dev.c | 20 ++++---------------- 3 files changed, 10 insertions(+), 46 deletions(-) diff --git a/sound/soc/sof/sof-acpi-dev.c b/sound/soc/sof/sof-acpi-dev.c index 1fec0420f662..7fbf09f9f17e 100644 --- a/sound/soc/sof/sof-acpi-dev.c +++ b/sound/soc/sof/sof-acpi-dev.c @@ -61,7 +61,6 @@ int sof_acpi_probe(struct platform_device *pdev, const struct sof_dev_desc *desc struct device *dev = &pdev->dev; struct snd_sof_pdata *sof_pdata; const struct snd_sof_dsp_ops *ops; - int ret; dev_dbg(dev, "ACPI DSP detected"); @@ -93,22 +92,11 @@ int sof_acpi_probe(struct platform_device *pdev, const struct sof_dev_desc *desc sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) - /* set callback to enable runtime_pm */ + /* set callback to be called on successful device probe to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_acpi_probe_complete; -#endif + /* call sof helper for DSP hardware probe */ - ret = snd_sof_device_probe(dev, sof_pdata); - if (ret) { - dev_err(dev, "error: failed to probe DSP hardware!\n"); - return ret; - } - -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) - sof_acpi_probe_complete(dev); -#endif - - return ret; + return snd_sof_device_probe(dev, sof_pdata); } EXPORT_SYMBOL_NS(sof_acpi_probe, SND_SOC_SOF_ACPI_DEV); diff --git a/sound/soc/sof/sof-of-dev.c b/sound/soc/sof/sof-of-dev.c index 85ff0db88eb7..c9c70645b377 100644 --- a/sound/soc/sof/sof-of-dev.c +++ b/sound/soc/sof/sof-of-dev.c @@ -71,7 +71,6 @@ static int sof_of_probe(struct platform_device *pdev) const struct sof_dev_desc *desc; struct snd_sof_pdata *sof_pdata; const struct snd_sof_dsp_ops *ops; - int ret; dev_info(&pdev->dev, "DT DSP detected"); @@ -98,22 +97,11 @@ static int sof_of_probe(struct platform_device *pdev) sof_pdata->fw_filename_prefix = sof_pdata->desc->default_fw_path; sof_pdata->tplg_filename_prefix = sof_pdata->desc->default_tplg_path; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) - /* set callback to enable runtime_pm */ + /* set callback to be called on successful device probe to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_of_probe_complete; -#endif - /* call sof helper for DSP hardware probe */ - ret = snd_sof_device_probe(dev, sof_pdata); - if (ret) { - dev_err(dev, "error: failed to probe DSP hardware\n"); - return ret; - } -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) - sof_of_probe_complete(dev); -#endif - - return ret; + /* call sof helper for DSP hardware probe */ + return snd_sof_device_probe(dev, sof_pdata); } static int sof_of_remove(struct platform_device *pdev) diff --git a/sound/soc/sof/sof-pci-dev.c b/sound/soc/sof/sof-pci-dev.c index b842a414e1df..3489dc1b48f6 100644 --- a/sound/soc/sof/sof-pci-dev.c +++ b/sound/soc/sof/sof-pci-dev.c @@ -184,25 +184,13 @@ int sof_pci_probe(struct pci_dev *pci, const struct pci_device_id *pci_id) if (sof_override_tplg_name) sof_pdata->tplg_filename = sof_override_tplg_name; -#if IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) - /* set callback to enable runtime_pm */ + /* set callback to be called on successful device probe to enable runtime_pm */ sof_pdata->sof_probe_complete = sof_pci_probe_complete; -#endif + /* call sof helper for DSP hardware probe */ ret = snd_sof_device_probe(dev, sof_pdata); - if (ret) { - dev_err(dev, "error: failed to probe DSP hardware!\n"); - goto release_regions; - } - -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE) - sof_pci_probe_complete(dev); -#endif - - return ret; - -release_regions: - pci_release_regions(pci); + if (ret) + pci_release_regions(pci); return ret; } From e4330cae2a8cf4e4f3004947794bdd549e32cede Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 9 Apr 2021 15:01:16 -0700 Subject: [PATCH 0919/1091] ASoC: SOF: add Kconfig option for probe workqueues The probe workqueue is currently used in the HDaudio case, following the example of the snd-hda-intel driver. For development and validation, it's useful to enable the probe workqueue even with ACPI devices or NOCODEC mode. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220121.1542362-2-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/Kconfig | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/sof/Kconfig b/sound/soc/sof/Kconfig index 8dfc165c3690..cd659493b5df 100644 --- a/sound/soc/sof/Kconfig +++ b/sound/soc/sof/Kconfig @@ -68,6 +68,17 @@ config SND_SOC_SOF_DEVELOPER_SUPPORT if SND_SOC_SOF_DEVELOPER_SUPPORT +config SND_SOC_SOF_FORCE_PROBE_WORKQUEUE + bool "SOF force probe workqueue" + select SND_SOC_SOF_PROBE_WORK_QUEUE + help + This option forces the use of a probe workqueue, which is only used + when HDaudio is enabled due to module dependencies. Forcing this + option is intended for debug only, but this should not add any + functional issues in nominal cases. + Say Y if you are involved in SOF development and need this option. + If not, select N. + config SND_SOC_SOF_NOCODEC tristate From ca6a0122557faa4fa01d6dbfa742870c33c46218 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 9 Apr 2021 15:01:17 -0700 Subject: [PATCH 0920/1091] ASoC: soc-acpi: add new fields for mach_params We currently have an ugly way of handling the SOF nocodec mode, with blatant violations between layers. To create the nocodec card, let's add two new fields and the existing mach_params structure, that way there will be no differences with regular cards. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220121.1542362-3-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- include/sound/soc-acpi.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/include/sound/soc-acpi.h b/include/sound/soc-acpi.h index c45075024c30..2f3fa385c092 100644 --- a/include/sound/soc-acpi.h +++ b/include/sound/soc-acpi.h @@ -63,6 +63,8 @@ static inline struct snd_soc_acpi_mach *snd_soc_acpi_codec_list(void *arg) * @common_hdmi_codec_drv: use commom HDAudio HDMI codec driver * @link_mask: links enabled on the board * @links: array of link _ADR descriptors, null terminated + * @num_dai_drivers: number of elements in @dai_drivers + * @dai_drivers: pointer to dai_drivers, used e.g. in nocodec mode */ struct snd_soc_acpi_mach_params { u32 acpi_ipc_irq_index; @@ -72,6 +74,8 @@ struct snd_soc_acpi_mach_params { bool common_hdmi_codec_drv; u32 link_mask; const struct snd_soc_acpi_link_adr *links; + u32 num_dai_drivers; + struct snd_soc_dai_driver *dai_drivers; }; /** From 17e9d6b0a395a1d8973a9e1d20db88d791e157b1 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 9 Apr 2021 15:01:18 -0700 Subject: [PATCH 0921/1091] ASoC: SOF: change signature of set_mach_params() callback To set additional parameters, we need to have access to sdev, not the plain vanilla struct device pointer. No functionality change. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220121.1542362-4-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 4 ++-- sound/soc/sof/intel/byt.c | 18 +++++++++--------- sound/soc/sof/intel/hda.c | 4 ++-- sound/soc/sof/intel/hda.h | 2 +- sound/soc/sof/ops.h | 6 ++---- sound/soc/sof/sof-audio.c | 4 ++-- sound/soc/sof/sof-priv.h | 2 +- 7 files changed, 19 insertions(+), 21 deletions(-) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index fd5ae628732d..28e049ac9c5e 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -559,12 +559,12 @@ static void bdw_machine_select(struct snd_sof_dev *sdev) } static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach, - struct device *dev) + struct snd_sof_dev *sdev) { struct snd_soc_acpi_mach_params *mach_params; mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; - mach_params->platform = dev_name(dev); + mach_params->platform = dev_name(sdev->dev); } /* Broadwell DAIs */ diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index 2846fdec9d95..bed26d96dc50 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -427,15 +427,6 @@ static void byt_machine_select(struct snd_sof_dev *sdev) sof_pdata->machine = mach; } -static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach, - struct device *dev) -{ - struct snd_soc_acpi_mach_params *mach_params; - - mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; - mach_params->platform = dev_name(dev); -} - /* Baytrail DAIs */ static struct snd_soc_dai_driver byt_dai[] = { { @@ -506,6 +497,15 @@ static struct snd_soc_dai_driver byt_dai[] = { }, }; +static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach, + struct snd_sof_dev *sdev) +{ + struct snd_soc_acpi_mach_params *mach_params; + + mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; + mach_params->platform = dev_name(sdev->dev); +} + /* * Probe and remove. */ diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 5317dfa4a4bf..065b85285450 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1213,12 +1213,12 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) #endif void hda_set_mach_params(const struct snd_soc_acpi_mach *mach, - struct device *dev) + struct snd_sof_dev *sdev) { struct snd_soc_acpi_mach_params *mach_params; mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; - mach_params->platform = dev_name(dev); + mach_params->platform = dev_name(sdev->dev); } void hda_machine_select(struct snd_sof_dev *sdev) diff --git a/sound/soc/sof/intel/hda.h b/sound/soc/sof/intel/hda.h index 7c7579daee7f..5ef29dcc052d 100644 --- a/sound/soc/sof/intel/hda.h +++ b/sound/soc/sof/intel/hda.h @@ -762,7 +762,7 @@ extern const struct sof_intel_dsp_desc adls_chip_info; /* machine driver select */ void hda_machine_select(struct snd_sof_dev *sdev); void hda_set_mach_params(const struct snd_soc_acpi_mach *mach, - struct device *dev); + struct snd_sof_dev *sdev); /* PCI driver selection and probe */ int hda_pci_intel_probe(struct pci_dev *pci, const struct pci_device_id *pci_id); diff --git a/sound/soc/sof/ops.h b/sound/soc/sof/ops.h index 5099ad03df72..323a0b3f561b 100644 --- a/sound/soc/sof/ops.h +++ b/sound/soc/sof/ops.h @@ -497,12 +497,10 @@ snd_sof_machine_select(struct snd_sof_dev *sdev) static inline void snd_sof_set_mach_params(const struct snd_soc_acpi_mach *mach, - struct device *dev) + struct snd_sof_dev *sdev) { - struct snd_sof_dev *sdev = dev_get_drvdata(dev); - if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params) - sof_ops(sdev)->set_mach_params(mach, dev); + sof_ops(sdev)->set_mach_params(mach, sdev); } static inline const struct snd_sof_dsp_ops diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 928d7a46d820..5d13bafd4736 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -475,7 +475,7 @@ int sof_machine_check(struct snd_sof_dev *sdev) /* find machine */ snd_sof_machine_select(sdev); if (sof_pdata->machine) { - snd_sof_set_mach_params(sof_pdata->machine, sdev->dev); + snd_sof_set_mach_params(sof_pdata->machine, sdev); return 0; } @@ -500,7 +500,7 @@ int sof_machine_check(struct snd_sof_dev *sdev) return ret; sof_pdata->machine = mach; - snd_sof_set_mach_params(sof_pdata->machine, sdev->dev); + snd_sof_set_mach_params(sof_pdata->machine, sdev); return 0; } diff --git a/sound/soc/sof/sof-priv.h b/sound/soc/sof/sof-priv.h index ad0d7ba2708c..fd8423172d8f 100644 --- a/sound/soc/sof/sof-priv.h +++ b/sound/soc/sof/sof-priv.h @@ -259,7 +259,7 @@ struct snd_sof_dsp_ops { void *pdata); /* optional */ void (*machine_select)(struct snd_sof_dev *sdev); /* optional */ void (*set_mach_params)(const struct snd_soc_acpi_mach *mach, - struct device *dev); /* optional */ + struct snd_sof_dev *sdev); /* optional */ /* DAI ops */ struct snd_soc_dai_driver *drv; From 974cccf490ebbc0c7ea0d19edd88542cef174d38 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 9 Apr 2021 15:01:19 -0700 Subject: [PATCH 0922/1091] ASoC: SOF: Intel: update set_mach_params() Add information for num_dai_drivers and dai_drivers[], which will be used in the refactored nocodec implementation Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220121.1542362-5-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/bdw.c | 4 ++++ sound/soc/sof/intel/byt.c | 4 ++++ sound/soc/sof/intel/hda.c | 4 ++++ 3 files changed, 12 insertions(+) diff --git a/sound/soc/sof/intel/bdw.c b/sound/soc/sof/intel/bdw.c index 28e049ac9c5e..89a6c1f04a55 100644 --- a/sound/soc/sof/intel/bdw.c +++ b/sound/soc/sof/intel/bdw.c @@ -561,10 +561,14 @@ static void bdw_machine_select(struct snd_sof_dev *sdev) static void bdw_set_mach_params(const struct snd_soc_acpi_mach *mach, struct snd_sof_dev *sdev) { + struct snd_sof_pdata *pdata = sdev->pdata; + const struct sof_dev_desc *desc = pdata->desc; struct snd_soc_acpi_mach_params *mach_params; mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; mach_params->platform = dev_name(sdev->dev); + mach_params->num_dai_drivers = desc->ops->num_drv; + mach_params->dai_drivers = desc->ops->drv; } /* Broadwell DAIs */ diff --git a/sound/soc/sof/intel/byt.c b/sound/soc/sof/intel/byt.c index bed26d96dc50..d9803e2ba67f 100644 --- a/sound/soc/sof/intel/byt.c +++ b/sound/soc/sof/intel/byt.c @@ -500,10 +500,14 @@ static struct snd_soc_dai_driver byt_dai[] = { static void byt_set_mach_params(const struct snd_soc_acpi_mach *mach, struct snd_sof_dev *sdev) { + struct snd_sof_pdata *pdata = sdev->pdata; + const struct sof_dev_desc *desc = pdata->desc; struct snd_soc_acpi_mach_params *mach_params; mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; mach_params->platform = dev_name(sdev->dev); + mach_params->num_dai_drivers = desc->ops->num_drv; + mach_params->dai_drivers = desc->ops->drv; } /* diff --git a/sound/soc/sof/intel/hda.c b/sound/soc/sof/intel/hda.c index 065b85285450..b00e8fcb2312 100644 --- a/sound/soc/sof/intel/hda.c +++ b/sound/soc/sof/intel/hda.c @@ -1215,10 +1215,14 @@ static int hda_sdw_machine_select(struct snd_sof_dev *sdev) void hda_set_mach_params(const struct snd_soc_acpi_mach *mach, struct snd_sof_dev *sdev) { + struct snd_sof_pdata *pdata = sdev->pdata; + const struct sof_dev_desc *desc = pdata->desc; struct snd_soc_acpi_mach_params *mach_params; mach_params = (struct snd_soc_acpi_mach_params *)&mach->mach_params; mach_params->platform = dev_name(sdev->dev); + mach_params->num_dai_drivers = desc->ops->num_drv; + mach_params->dai_drivers = desc->ops->drv; } void hda_machine_select(struct snd_sof_dev *sdev) From f3f3af1743350fdc7c373772fb3740dc223db8e5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 9 Apr 2021 15:01:20 -0700 Subject: [PATCH 0923/1091] ASoC: SOF: pcm: export snd_pcm_dai_link_fixup In preparation of the nocodec refactoring, export the dai-link fixup. This will also be required when we have more clients and platform drivers. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220121.1542362-6-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/pcm.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sof/pcm.c b/sound/soc/sof/pcm.c index d6b1c8b7bdfb..9893b182da43 100644 --- a/sound/soc/sof/pcm.c +++ b/sound/soc/sof/pcm.c @@ -775,6 +775,7 @@ int sof_pcm_dai_link_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_pa return 0; } +EXPORT_SYMBOL(sof_pcm_dai_link_fixup); static int sof_pcm_probe(struct snd_soc_component *component) { From 4c1cc83fcc7e02f6f6f76da2ea66af86a95fd675 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 9 Apr 2021 15:01:21 -0700 Subject: [PATCH 0924/1091] ASOC: SOF: simplify nocodec mode Replace ugly #if (!IS_ENABLED) by if (!IS_ENABLED), remove cross-module dependencies and use classic mechanism to pass information to the machine driver. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220121.1542362-7-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- include/sound/sof.h | 3 --- sound/soc/sof/nocodec.c | 39 +++++++++++++++++++++------------------ sound/soc/sof/sof-audio.c | 32 ++++++++++++++------------------ 3 files changed, 35 insertions(+), 39 deletions(-) diff --git a/include/sound/sof.h b/include/sound/sof.h index b93bb8038080..502ed9b8d6a1 100644 --- a/include/sound/sof.h +++ b/include/sound/sof.h @@ -100,9 +100,6 @@ struct sof_dev_desc { const struct snd_sof_dsp_ops *ops; }; -int sof_nocodec_setup(struct device *dev, const struct snd_sof_dsp_ops *ops, - int (*pcm_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params)); int sof_dai_get_mclk(struct snd_soc_pcm_runtime *rtd); #endif diff --git a/sound/soc/sof/nocodec.c b/sound/soc/sof/nocodec.c index 3b9bb2e83a86..356497fe4f4c 100644 --- a/sound/soc/sof/nocodec.c +++ b/sound/soc/sof/nocodec.c @@ -20,16 +20,14 @@ static struct snd_soc_card sof_nocodec_card = { }; static int sof_nocodec_bes_setup(struct device *dev, - const struct snd_sof_dsp_ops *ops, + struct snd_soc_dai_driver *drv, struct snd_soc_dai_link *links, - int link_num, struct snd_soc_card *card, - int (*pcm_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params)) + int link_num, struct snd_soc_card *card) { struct snd_soc_dai_link_component *dlc; int i; - if (!ops || !links || !card) + if (!drv || !links || !card) return -EINVAL; /* set up BE dai_links */ @@ -55,16 +53,16 @@ static int sof_nocodec_bes_setup(struct device *dev, links[i].id = i; links[i].no_pcm = 1; - links[i].cpus->dai_name = ops->drv[i].name; - links[i].platforms->name = dev_name(dev); + links[i].cpus->dai_name = drv[i].name; + links[i].platforms->name = dev_name(dev->parent); links[i].codecs->dai_name = "snd-soc-dummy-dai"; links[i].codecs->name = "snd-soc-dummy"; - if (ops->drv[i].playback.channels_min) + if (drv[i].playback.channels_min) links[i].dpcm_playback = 1; - if (ops->drv[i].capture.channels_min) + if (drv[i].capture.channels_min) links[i].dpcm_capture = 1; - links[i].be_hw_params_fixup = pcm_dai_link_fixup; + links[i].be_hw_params_fixup = sof_pcm_dai_link_fixup; } card->dai_link = links; @@ -73,29 +71,34 @@ static int sof_nocodec_bes_setup(struct device *dev, return 0; } -int sof_nocodec_setup(struct device *dev, const struct snd_sof_dsp_ops *ops, - int (*pcm_dai_link_fixup)(struct snd_soc_pcm_runtime *rtd, - struct snd_pcm_hw_params *params)) +static int sof_nocodec_setup(struct device *dev, + u32 num_dai_drivers, + struct snd_soc_dai_driver *dai_drivers) { struct snd_soc_dai_link *links; /* create dummy BE dai_links */ - links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * - ops->num_drv, GFP_KERNEL); + links = devm_kzalloc(dev, sizeof(struct snd_soc_dai_link) * num_dai_drivers, GFP_KERNEL); if (!links) return -ENOMEM; - return sof_nocodec_bes_setup(dev, ops, links, ops->num_drv, - &sof_nocodec_card, pcm_dai_link_fixup); + return sof_nocodec_bes_setup(dev, dai_drivers, links, num_dai_drivers, &sof_nocodec_card); } -EXPORT_SYMBOL(sof_nocodec_setup); static int sof_nocodec_probe(struct platform_device *pdev) { struct snd_soc_card *card = &sof_nocodec_card; + struct snd_soc_acpi_mach *mach; + int ret; card->dev = &pdev->dev; card->topology_shortname_created = true; + mach = pdev->dev.platform_data; + + ret = sof_nocodec_setup(card->dev, mach->mach_params.num_dai_drivers, + mach->mach_params.dai_drivers); + if (ret < 0) + return ret; return devm_snd_soc_register_card(&pdev->dev, card); } diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 5d13bafd4736..0d0d47dc0246 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -468,24 +468,24 @@ int sof_machine_check(struct snd_sof_dev *sdev) struct snd_sof_pdata *sof_pdata = sdev->pdata; const struct sof_dev_desc *desc = sof_pdata->desc; struct snd_soc_acpi_mach *mach; - int ret; -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE) + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_FORCE_NOCODEC_MODE)) { - /* find machine */ - snd_sof_machine_select(sdev); - if (sof_pdata->machine) { - snd_sof_set_mach_params(sof_pdata->machine, sdev); - return 0; + /* find machine */ + snd_sof_machine_select(sdev); + if (sof_pdata->machine) { + snd_sof_set_mach_params(sof_pdata->machine, sdev); + return 0; + } + + if (!IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC)) { + dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); + return -ENODEV; + } + } else { + dev_warn(sdev->dev, "Force to use nocodec mode\n"); } -#if !IS_ENABLED(CONFIG_SND_SOC_SOF_NOCODEC) - dev_err(sdev->dev, "error: no matching ASoC machine driver found - aborting probe\n"); - return -ENODEV; -#endif -#else - dev_warn(sdev->dev, "Force to use nocodec mode\n"); -#endif /* select nocodec mode */ dev_warn(sdev->dev, "Using nocodec machine driver\n"); mach = devm_kzalloc(sdev->dev, sizeof(*mach), GFP_KERNEL); @@ -495,10 +495,6 @@ int sof_machine_check(struct snd_sof_dev *sdev) mach->drv_name = "sof-nocodec"; sof_pdata->tplg_filename = desc->nocodec_tplg_filename; - ret = sof_nocodec_setup(sdev->dev, desc->ops, sof_pcm_dai_link_fixup); - if (ret < 0) - return ret; - sof_pdata->machine = mach; snd_sof_set_mach_params(sof_pdata->machine, sdev); From b2fe85790d8d67ae25af58ff94673afc6cb081d9 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Fri, 9 Apr 2021 15:13:08 -0700 Subject: [PATCH 0925/1091] ASoC: SOF: Kconfig: fix typo of SND_SOC_SOF_PCI It should be 'endif ## SND_SOC_SOF_PCI' instead of 'endif ## SND_SOC_SOF_INTEL_PCI' Signed-off-by: Libin Yang Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409221308.1544000-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/intel/Kconfig b/sound/soc/sof/intel/Kconfig index da1c396f529d..4bce89b5ea40 100644 --- a/sound/soc/sof/intel/Kconfig +++ b/sound/soc/sof/intel/Kconfig @@ -293,6 +293,6 @@ config SND_SOC_SOF_INTEL_SOUNDWIRE Say Y if you want to enable SoundWire links with SOF. If unsure select "N". -endif ## SND_SOC_SOF_INTEL_PCI +endif ## SND_SOC_SOF_PCI endif ## SND_SOC_SOF_INTEL_TOPLEVEL From 7459f8b703db589e1fa6482449cd681a6a612189 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Fri, 9 Apr 2021 15:05:22 -0700 Subject: [PATCH 0926/1091] ASoC: SOF: topology: remove useless code The patch "ASoC: SOF: Intel: hda: assign link DMA channel at run-time" fixed the sof_link_hda_unload() to remove the call to the BE hw_free op but left the rest of code that become redundant. So, remove sof_link_hda_unload() along with the link_unload() op entirely as it is not longer needed. Reported-by: Pierre-Louis Bossart Reviewed-by: Kai Vehmanen Reviewed-by: Pierre-Louis Bossart Signed-off-by: Ranjani Sridharan Link: https://lore.kernel.org/r/20210409220522.1542865-1-ranjani.sridharan@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/topology.c | 64 ---------------------------------------- 1 file changed, 64 deletions(-) diff --git a/sound/soc/sof/topology.c b/sound/soc/sof/topology.c index 036202768b75..59abcfc9bd55 100644 --- a/sound/soc/sof/topology.c +++ b/sound/soc/sof/topology.c @@ -3371,69 +3371,6 @@ static int sof_link_load(struct snd_soc_component *scomp, int index, return ret; } -static int sof_link_hda_unload(struct snd_sof_dev *sdev, - struct snd_soc_dai_link *link) -{ - struct snd_soc_dai *dai; - - dai = snd_soc_find_dai(link->cpus); - if (!dai) { - dev_err(sdev->dev, "error: failed to find dai %s in %s", - link->cpus->dai_name, __func__); - return -EINVAL; - } - - return 0; -} - -static int sof_link_unload(struct snd_soc_component *scomp, - struct snd_soc_dobj *dobj) -{ - struct snd_sof_dev *sdev = snd_soc_component_get_drvdata(scomp); - struct snd_soc_dai_link *link = - container_of(dobj, struct snd_soc_dai_link, dobj); - - struct snd_sof_dai *sof_dai; - int ret = 0; - - /* only BE link is loaded by sof */ - if (!link->no_pcm) - return 0; - - list_for_each_entry(sof_dai, &sdev->dai_list, list) { - if (!sof_dai->name) - continue; - - if (strcmp(link->name, sof_dai->name) == 0) - goto found; - } - - dev_err(scomp->dev, "error: failed to find dai %s in %s", - link->name, __func__); - return -EINVAL; -found: - - switch (sof_dai->dai_config->type) { - case SOF_DAI_INTEL_SSP: - case SOF_DAI_INTEL_DMIC: - case SOF_DAI_INTEL_ALH: - case SOF_DAI_IMX_SAI: - case SOF_DAI_IMX_ESAI: - /* no resource needs to be released for all cases above */ - break; - case SOF_DAI_INTEL_HDA: - ret = sof_link_hda_unload(sdev, link); - break; - default: - dev_err(scomp->dev, "error: invalid DAI type %d\n", - sof_dai->dai_config->type); - ret = -EINVAL; - break; - } - - return ret; -} - /* DAI link - used for any driver specific init */ static int sof_route_load(struct snd_soc_component *scomp, int index, struct snd_soc_dapm_route *route) @@ -3734,7 +3671,6 @@ static struct snd_soc_tplg_ops sof_tplg_ops = { /* DAI link - used for any driver specific init */ .link_load = sof_link_load, - .link_unload = sof_link_unload, /* completion - called at completion of firmware loading */ .complete = sof_complete, From 6df0e6c57dfc064af330071f372f11aa8c584997 Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Mon, 12 Apr 2021 09:23:27 -0700 Subject: [PATCH 0927/1091] dmaengine: idxd: clear MSIX permission entry on shutdown Add disabling/clearing of MSIX permission entries on device shutdown to mirror the enabling of the MSIX entries on probe. Current code left the MSIX enabled and the pasid entries still programmed at device shutdown. Fixes: 8e50d392652f ("dmaengine: idxd: Add shared workqueue support") Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/161824457969.882533.6020239898682672311.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/device.c | 30 ++++++++++++++++++++++++++++++ drivers/dma/idxd/idxd.h | 2 ++ drivers/dma/idxd/init.c | 11 ++--------- 3 files changed, 34 insertions(+), 9 deletions(-) diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index 84a6ea60ecf0..c09687013d29 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -574,6 +574,36 @@ void idxd_device_drain_pasid(struct idxd_device *idxd, int pasid) } /* Device configuration bits */ +void idxd_msix_perm_setup(struct idxd_device *idxd) +{ + union msix_perm mperm; + int i, msixcnt; + + msixcnt = pci_msix_vec_count(idxd->pdev); + if (msixcnt < 0) + return; + + mperm.bits = 0; + mperm.pasid = idxd->pasid; + mperm.pasid_en = device_pasid_enabled(idxd); + for (i = 1; i < msixcnt; i++) + iowrite32(mperm.bits, idxd->reg_base + idxd->msix_perm_offset + i * 8); +} + +void idxd_msix_perm_clear(struct idxd_device *idxd) +{ + union msix_perm mperm; + int i, msixcnt; + + msixcnt = pci_msix_vec_count(idxd->pdev); + if (msixcnt < 0) + return; + + mperm.bits = 0; + for (i = 1; i < msixcnt; i++) + iowrite32(mperm.bits, idxd->reg_base + idxd->msix_perm_offset + i * 8); +} + static void idxd_group_config_write(struct idxd_group *group) { struct idxd_device *idxd = group->idxd; diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index 81a0e65fd316..eda2ee10501f 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -316,6 +316,8 @@ void idxd_unregister_driver(void); struct bus_type *idxd_get_bus_type(struct idxd_device *idxd); /* device interrupt control */ +void idxd_msix_perm_setup(struct idxd_device *idxd); +void idxd_msix_perm_clear(struct idxd_device *idxd); irqreturn_t idxd_irq_handler(int vec, void *data); irqreturn_t idxd_misc_thread(int vec, void *data); irqreturn_t idxd_wq_thread(int irq, void *data); diff --git a/drivers/dma/idxd/init.c b/drivers/dma/idxd/init.c index 085a0c3b62c6..6584b0ec07d5 100644 --- a/drivers/dma/idxd/init.c +++ b/drivers/dma/idxd/init.c @@ -65,7 +65,6 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) struct idxd_irq_entry *irq_entry; int i, msixcnt; int rc = 0; - union msix_perm mperm; msixcnt = pci_msix_vec_count(pdev); if (msixcnt < 0) { @@ -144,14 +143,7 @@ static int idxd_setup_interrupts(struct idxd_device *idxd) } idxd_unmask_error_interrupts(idxd); - - /* Setup MSIX permission table */ - mperm.bits = 0; - mperm.pasid = idxd->pasid; - mperm.pasid_en = device_pasid_enabled(idxd); - for (i = 1; i < msixcnt; i++) - iowrite32(mperm.bits, idxd->reg_base + idxd->msix_perm_offset + i * 8); - + idxd_msix_perm_setup(idxd); return 0; err_no_irq: @@ -510,6 +502,7 @@ static void idxd_shutdown(struct pci_dev *pdev) idxd_flush_work_list(irq_entry); } + idxd_msix_perm_clear(idxd); destroy_workqueue(idxd->wq); } From ea9aadc06a9f10ad20a90edc0a484f1147d88a7a Mon Sep 17 00:00:00 2001 From: Dave Jiang Date: Mon, 12 Apr 2021 09:02:36 -0700 Subject: [PATCH 0928/1091] dmaengine: idxd: fix wq cleanup of WQCFG registers A pre-release silicon erratum workaround where wq reset does not clear WQCFG registers was leaked into upstream code. Use wq reset command instead of blasting the MMIO region. This also address an issue where we clobber registers in future devices. Fixes: da32b28c95a7 ("dmaengine: idxd: cleanup workqueue config after disabling") Reported-by: Shreenivaas Devarajan Signed-off-by: Dave Jiang Link: https://lore.kernel.org/r/161824330020.881560.16375921906426627033.stgit@djiang5-desk3.ch.intel.com Signed-off-by: Vinod Koul --- drivers/dma/idxd/device.c | 35 ++++++++++++++++++++++++----------- drivers/dma/idxd/idxd.h | 1 + drivers/dma/idxd/sysfs.c | 9 ++------- 3 files changed, 27 insertions(+), 18 deletions(-) diff --git a/drivers/dma/idxd/device.c b/drivers/dma/idxd/device.c index c09687013d29..31c819544a22 100644 --- a/drivers/dma/idxd/device.c +++ b/drivers/dma/idxd/device.c @@ -282,6 +282,22 @@ void idxd_wq_drain(struct idxd_wq *wq) idxd_cmd_exec(idxd, IDXD_CMD_DRAIN_WQ, operand, NULL); } +void idxd_wq_reset(struct idxd_wq *wq) +{ + struct idxd_device *idxd = wq->idxd; + struct device *dev = &idxd->pdev->dev; + u32 operand; + + if (wq->state != IDXD_WQ_ENABLED) { + dev_dbg(dev, "WQ %d in wrong state: %d\n", wq->id, wq->state); + return; + } + + operand = BIT(wq->id % 16) | ((wq->id / 16) << 16); + idxd_cmd_exec(idxd, IDXD_CMD_RESET_WQ, operand, NULL); + wq->state = IDXD_WQ_DISABLED; +} + int idxd_wq_map_portal(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; @@ -363,8 +379,6 @@ int idxd_wq_disable_pasid(struct idxd_wq *wq) void idxd_wq_disable_cleanup(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; - struct device *dev = &idxd->pdev->dev; - int i, wq_offset; lockdep_assert_held(&idxd->dev_lock); memset(wq->wqcfg, 0, idxd->wqcfg_size); @@ -376,14 +390,6 @@ void idxd_wq_disable_cleanup(struct idxd_wq *wq) wq->ats_dis = 0; clear_bit(WQ_FLAG_DEDICATED, &wq->flags); memset(wq->name, 0, WQ_NAME_SIZE); - - for (i = 0; i < WQCFG_STRIDES(idxd); i++) { - wq_offset = WQCFG_OFFSET(idxd, wq->id, i); - iowrite32(0, idxd->reg_base + wq_offset); - dev_dbg(dev, "WQ[%d][%d][%#x]: %#x\n", - wq->id, i, wq_offset, - ioread32(idxd->reg_base + wq_offset)); - } } /* Device control bits */ @@ -672,7 +678,14 @@ static int idxd_wq_config_write(struct idxd_wq *wq) if (!wq->group) return 0; - memset(wq->wqcfg, 0, idxd->wqcfg_size); + /* + * Instead of memset the entire shadow copy of WQCFG, copy from the hardware after + * wq reset. This will copy back the sticky values that are present on some devices. + */ + for (i = 0; i < WQCFG_STRIDES(idxd); i++) { + wq_offset = WQCFG_OFFSET(idxd, wq->id, i); + wq->wqcfg->bits[i] = ioread32(idxd->reg_base + wq_offset); + } /* byte 0-3 */ wq->wqcfg->wq_size = wq->size; diff --git a/drivers/dma/idxd/idxd.h b/drivers/dma/idxd/idxd.h index eda2ee10501f..76014c14f473 100644 --- a/drivers/dma/idxd/idxd.h +++ b/drivers/dma/idxd/idxd.h @@ -343,6 +343,7 @@ void idxd_wq_free_resources(struct idxd_wq *wq); int idxd_wq_enable(struct idxd_wq *wq); int idxd_wq_disable(struct idxd_wq *wq); void idxd_wq_drain(struct idxd_wq *wq); +void idxd_wq_reset(struct idxd_wq *wq); int idxd_wq_map_portal(struct idxd_wq *wq); void idxd_wq_unmap_portal(struct idxd_wq *wq); void idxd_wq_disable_cleanup(struct idxd_wq *wq); diff --git a/drivers/dma/idxd/sysfs.c b/drivers/dma/idxd/sysfs.c index 5f7bc4b1621a..18bf4d148989 100644 --- a/drivers/dma/idxd/sysfs.c +++ b/drivers/dma/idxd/sysfs.c @@ -275,7 +275,6 @@ static void disable_wq(struct idxd_wq *wq) { struct idxd_device *idxd = wq->idxd; struct device *dev = &idxd->pdev->dev; - int rc; mutex_lock(&wq->wq_lock); dev_dbg(dev, "%s removing WQ %s\n", __func__, dev_name(&wq->conf_dev)); @@ -296,17 +295,13 @@ static void disable_wq(struct idxd_wq *wq) idxd_wq_unmap_portal(wq); idxd_wq_drain(wq); - rc = idxd_wq_disable(wq); + idxd_wq_reset(wq); idxd_wq_free_resources(wq); wq->client_count = 0; mutex_unlock(&wq->wq_lock); - if (rc < 0) - dev_warn(dev, "Failed to disable %s: %d\n", - dev_name(&wq->conf_dev), rc); - else - dev_info(dev, "wq %s disabled\n", dev_name(&wq->conf_dev)); + dev_info(dev, "wq %s disabled\n", dev_name(&wq->conf_dev)); } static int idxd_config_bus_remove(struct device *dev) From 1b9889974ce93dea50d010972a93c0eb529ac612 Mon Sep 17 00:00:00 2001 From: Libin Yang Date: Mon, 12 Apr 2021 11:15:18 -0500 Subject: [PATCH 0929/1091] ASoC: SOF: Intel: add missing use_acpi_target_states for TGL platforms All Intel TigerLake platforms should support the feature of getting the system state from acpi to deal with S0ix support. This was missed in previous commits, likely due to copy/paste from older code. Reviewed-by: Ranjani Sridharan Signed-off-by: Libin Yang Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210412161519.13508-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-tgl.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index 485607471181..c2abb07fb7ff 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -39,6 +39,7 @@ static const struct sof_dev_desc tgl_desc = { static const struct sof_dev_desc tglh_desc = { .machines = snd_soc_acpi_intel_tgl_machines, .alt_machines = snd_soc_acpi_intel_tgl_sdw_machines, + .use_acpi_target_states = true, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, @@ -71,6 +72,7 @@ static const struct sof_dev_desc ehl_desc = { static const struct sof_dev_desc adls_desc = { .machines = snd_soc_acpi_intel_adl_machines, .alt_machines = snd_soc_acpi_intel_adl_sdw_machines, + .use_acpi_target_states = true, .resindex_lpe_base = 0, .resindex_pcicfg_base = -1, .resindex_imr_base = -1, From 4ad03f894b3c96d77e51474f0c9731793fac412e Mon Sep 17 00:00:00 2001 From: Sathya Prakash M R Date: Mon, 12 Apr 2021 11:15:19 -0500 Subject: [PATCH 0930/1091] ASoC: SOF: Intel: Update ADL P to use its own descriptor ADL P has specific machines and hence having its own table will help separate the machines and FW Reviewed-by: Bard Liao Reviewed-by: Kai Vehmanen Signed-off-by: Sathya Prakash M R Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210412161519.13508-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/intel/pci-tgl.c | 18 +++++++++++++++++- sound/soc/sof/intel/tgl.c | 2 +- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/sound/soc/sof/intel/pci-tgl.c b/sound/soc/sof/intel/pci-tgl.c index c2abb07fb7ff..21f69204d5ad 100644 --- a/sound/soc/sof/intel/pci-tgl.c +++ b/sound/soc/sof/intel/pci-tgl.c @@ -86,6 +86,22 @@ static const struct sof_dev_desc adls_desc = { .ops = &sof_tgl_ops, }; +static const struct sof_dev_desc adl_desc = { + .machines = snd_soc_acpi_intel_adl_machines, + .alt_machines = snd_soc_acpi_intel_adl_sdw_machines, + .resindex_lpe_base = 0, + .resindex_pcicfg_base = -1, + .resindex_imr_base = -1, + .irqindex_host_ipc = -1, + .resindex_dma_base = -1, + .chip_info = &tgl_chip_info, + .default_fw_path = "intel/sof", + .default_tplg_path = "intel/sof-tplg", + .default_fw_filename = "sof-adl.ri", + .nocodec_tplg_filename = "sof-adl-nocodec.tplg", + .ops = &sof_tgl_ops, +}; + /* PCI IDs */ static const struct pci_device_id sof_pci_ids[] = { { PCI_DEVICE(0x8086, 0xa0c8), /* TGL-LP */ @@ -99,7 +115,7 @@ static const struct pci_device_id sof_pci_ids[] = { { PCI_DEVICE(0x8086, 0x7ad0), /* ADL-S */ .driver_data = (unsigned long)&adls_desc}, { PCI_DEVICE(0x8086, 0x51c8), /* ADL-P */ - .driver_data = (unsigned long)&tgl_desc}, + .driver_data = (unsigned long)&adl_desc}, { 0, } }; MODULE_DEVICE_TABLE(pci, sof_pci_ids); diff --git a/sound/soc/sof/intel/tgl.c b/sound/soc/sof/intel/tgl.c index 419f05ba1920..940f169047a0 100644 --- a/sound/soc/sof/intel/tgl.c +++ b/sound/soc/sof/intel/tgl.c @@ -125,7 +125,7 @@ const struct snd_sof_dsp_ops sof_tgl_ops = { EXPORT_SYMBOL_NS(sof_tgl_ops, SND_SOC_SOF_INTEL_HDA_COMMON); const struct sof_intel_dsp_desc tgl_chip_info = { - /* Tigerlake */ + /* Tigerlake , Alderlake */ .cores_num = 4, .init_core_mask = 1, .host_managed_cores_mask = BIT(0), From 1fe976d308acb6374c899a4ee8025a0a016e453e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pali=20Roh=C3=A1r?= Date: Mon, 12 Apr 2021 18:57:39 +0200 Subject: [PATCH 0931/1091] net: phy: marvell: fix detection of PHY on Topaz switches MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Since commit fee2d546414d ("net: phy: marvell: mv88e6390 temperature sensor reading"), Linux reports the temperature of Topaz hwmon as constant -75°C. This is because switches from the Topaz family (88E6141 / 88E6341) have the address of the temperature sensor register different from Peridot. This address is instead compatible with 88E1510 PHYs, as was used for Topaz before the above mentioned commit. Create a new mapping table between switch family and PHY ID for families which don't have a model number. And define PHY IDs for Topaz and Peridot families. Create a new PHY ID and a new PHY driver for Topaz's internal PHY. The only difference from Peridot's PHY driver is the HWMON probing method. Prior this change Topaz's internal PHY is detected by kernel as: PHY [...] driver [Marvell 88E6390] (irq=63) And afterwards as: PHY [...] driver [Marvell 88E6341 Family] (irq=63) Signed-off-by: Pali Rohár BugLink: https://github.com/globalscaletechnologies/linux/issues/1 Fixes: fee2d546414d ("net: phy: marvell: mv88e6390 temperature sensor reading") Reviewed-by: Marek Behún Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- drivers/net/dsa/mv88e6xxx/chip.c | 30 +++++++++++++----------------- drivers/net/phy/marvell.c | 32 +++++++++++++++++++++++++++++--- include/linux/marvell_phy.h | 5 +++-- 3 files changed, 45 insertions(+), 22 deletions(-) diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 903d619e08ed..e08bf9377140 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -3026,10 +3026,17 @@ out_resources: return err; } +/* prod_id for switch families which do not have a PHY model number */ +static const u16 family_prod_id_table[] = { + [MV88E6XXX_FAMILY_6341] = MV88E6XXX_PORT_SWITCH_ID_PROD_6341, + [MV88E6XXX_FAMILY_6390] = MV88E6XXX_PORT_SWITCH_ID_PROD_6390, +}; + static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg) { struct mv88e6xxx_mdio_bus *mdio_bus = bus->priv; struct mv88e6xxx_chip *chip = mdio_bus->chip; + u16 prod_id; u16 val; int err; @@ -3040,23 +3047,12 @@ static int mv88e6xxx_mdio_read(struct mii_bus *bus, int phy, int reg) err = chip->info->ops->phy_read(chip, bus, phy, reg, &val); mv88e6xxx_reg_unlock(chip); - if (reg == MII_PHYSID2) { - /* Some internal PHYs don't have a model number. */ - if (chip->info->family != MV88E6XXX_FAMILY_6165) - /* Then there is the 6165 family. It gets is - * PHYs correct. But it can also have two - * SERDES interfaces in the PHY address - * space. And these don't have a model - * number. But they are not PHYs, so we don't - * want to give them something a PHY driver - * will recognise. - * - * Use the mv88e6390 family model number - * instead, for anything which really could be - * a PHY, - */ - if (!(val & 0x3f0)) - val |= MV88E6XXX_PORT_SWITCH_ID_PROD_6390 >> 4; + /* Some internal PHYs don't have a model number. */ + if (reg == MII_PHYSID2 && !(val & 0x3f0) && + chip->info->family < ARRAY_SIZE(family_prod_id_table)) { + prod_id = family_prod_id_table[chip->info->family]; + if (prod_id) + val |= prod_id >> 4; } return err ? err : val; diff --git a/drivers/net/phy/marvell.c b/drivers/net/phy/marvell.c index e26a5d663f8a..8018ddf7f316 100644 --- a/drivers/net/phy/marvell.c +++ b/drivers/net/phy/marvell.c @@ -3021,9 +3021,34 @@ static struct phy_driver marvell_drivers[] = { .get_stats = marvell_get_stats, }, { - .phy_id = MARVELL_PHY_ID_88E6390, + .phy_id = MARVELL_PHY_ID_88E6341_FAMILY, .phy_id_mask = MARVELL_PHY_ID_MASK, - .name = "Marvell 88E6390", + .name = "Marvell 88E6341 Family", + /* PHY_GBIT_FEATURES */ + .flags = PHY_POLL_CABLE_TEST, + .probe = m88e1510_probe, + .config_init = marvell_config_init, + .config_aneg = m88e6390_config_aneg, + .read_status = marvell_read_status, + .config_intr = marvell_config_intr, + .handle_interrupt = marvell_handle_interrupt, + .resume = genphy_resume, + .suspend = genphy_suspend, + .read_page = marvell_read_page, + .write_page = marvell_write_page, + .get_sset_count = marvell_get_sset_count, + .get_strings = marvell_get_strings, + .get_stats = marvell_get_stats, + .get_tunable = m88e1540_get_tunable, + .set_tunable = m88e1540_set_tunable, + .cable_test_start = marvell_vct7_cable_test_start, + .cable_test_tdr_start = marvell_vct5_cable_test_tdr_start, + .cable_test_get_status = marvell_vct7_cable_test_get_status, + }, + { + .phy_id = MARVELL_PHY_ID_88E6390_FAMILY, + .phy_id_mask = MARVELL_PHY_ID_MASK, + .name = "Marvell 88E6390 Family", /* PHY_GBIT_FEATURES */ .flags = PHY_POLL_CABLE_TEST, .probe = m88e6390_probe, @@ -3107,7 +3132,8 @@ static struct mdio_device_id __maybe_unused marvell_tbl[] = { { MARVELL_PHY_ID_88E1540, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1545, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E3016, MARVELL_PHY_ID_MASK }, - { MARVELL_PHY_ID_88E6390, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E6341_FAMILY, MARVELL_PHY_ID_MASK }, + { MARVELL_PHY_ID_88E6390_FAMILY, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1340S, MARVELL_PHY_ID_MASK }, { MARVELL_PHY_ID_88E1548P, MARVELL_PHY_ID_MASK }, { } diff --git a/include/linux/marvell_phy.h b/include/linux/marvell_phy.h index 52b1610eae68..c544b70dfbd2 100644 --- a/include/linux/marvell_phy.h +++ b/include/linux/marvell_phy.h @@ -28,11 +28,12 @@ /* Marvel 88E1111 in Finisar SFP module with modified PHY ID */ #define MARVELL_PHY_ID_88E1111_FINISAR 0x01ff0cc0 -/* The MV88e6390 Ethernet switch contains embedded PHYs. These PHYs do +/* These Ethernet switch families contain embedded PHYs, but they do * not have a model ID. So the switch driver traps reads to the ID2 * register and returns the switch family ID */ -#define MARVELL_PHY_ID_88E6390 0x01410f90 +#define MARVELL_PHY_ID_88E6341_FAMILY 0x01410f41 +#define MARVELL_PHY_ID_88E6390_FAMILY 0x01410f90 #define MARVELL_PHY_FAMILY_ID(id) ((id) >> 4) From f33b0e196ed7aa3dc285b26db7768c1db1eb3a41 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Mon, 12 Apr 2021 11:47:07 -0700 Subject: [PATCH 0932/1091] ethtool: fix kdoc attr name Add missing 't' in attrtype. Signed-off-by: Jakub Kicinski Reviewed-by: Andrew Lunn Signed-off-by: David S. Miller --- net/ethtool/netlink.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/net/ethtool/netlink.h b/net/ethtool/netlink.h index 6eabd58d81bf..cde9f3169ae5 100644 --- a/net/ethtool/netlink.h +++ b/net/ethtool/netlink.h @@ -36,9 +36,9 @@ static inline int ethnl_strz_size(const char *s) /** * ethnl_put_strz() - put string attribute with fixed size string - * @skb: skb with the message - * @attrype: attribute type - * @s: ETH_GSTRING_LEN sized string (may not be null terminated) + * @skb: skb with the message + * @attrtype: attribute type + * @s: ETH_GSTRING_LEN sized string (may not be null terminated) * * Puts an attribute with null terminated string from @s into the message. * From b29c457a6511435960115c0f548c4360d5f4801d Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Wed, 7 Apr 2021 21:38:57 +0200 Subject: [PATCH 0933/1091] netfilter: x_tables: fix compat match/target pad out-of-bound write xt_compat_match/target_from_user doesn't check that zeroing the area to start of next rule won't write past end of allocated ruleset blob. Remove this code and zero the entire blob beforehand. Reported-by: syzbot+cfc0247ac173f597aaaa@syzkaller.appspotmail.com Reported-by: Andy Nguyen Fixes: 9fa492cdc160c ("[NETFILTER]: x_tables: simplify compat API") Signed-off-by: Florian Westphal Signed-off-by: Pablo Neira Ayuso --- net/ipv4/netfilter/arp_tables.c | 2 ++ net/ipv4/netfilter/ip_tables.c | 2 ++ net/ipv6/netfilter/ip6_tables.c | 2 ++ net/netfilter/x_tables.c | 10 ++-------- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/net/ipv4/netfilter/arp_tables.c b/net/ipv4/netfilter/arp_tables.c index 6c26533480dd..d6d45d820d79 100644 --- a/net/ipv4/netfilter/arp_tables.c +++ b/net/ipv4/netfilter/arp_tables.c @@ -1193,6 +1193,8 @@ static int translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_ARP_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/ipv4/netfilter/ip_tables.c b/net/ipv4/netfilter/ip_tables.c index f15bc21d7301..f77ea0dbe656 100644 --- a/net/ipv4/netfilter/ip_tables.c +++ b/net/ipv4/netfilter/ip_tables.c @@ -1428,6 +1428,8 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/ipv6/netfilter/ip6_tables.c b/net/ipv6/netfilter/ip6_tables.c index 2e2119bfcf13..eb2b5404806c 100644 --- a/net/ipv6/netfilter/ip6_tables.c +++ b/net/ipv6/netfilter/ip6_tables.c @@ -1443,6 +1443,8 @@ translate_compat_table(struct net *net, if (!newinfo) goto out_unlock; + memset(newinfo->entries, 0, size); + newinfo->number = compatr->num_entries; for (i = 0; i < NF_INET_NUMHOOKS; i++) { newinfo->hook_entry[i] = compatr->hook_entry[i]; diff --git a/net/netfilter/x_tables.c b/net/netfilter/x_tables.c index 6bd31a7a27fc..92e9d4ebc5e8 100644 --- a/net/netfilter/x_tables.c +++ b/net/netfilter/x_tables.c @@ -733,7 +733,7 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, { const struct xt_match *match = m->u.kernel.match; struct compat_xt_entry_match *cm = (struct compat_xt_entry_match *)m; - int pad, off = xt_compat_match_offset(match); + int off = xt_compat_match_offset(match); u_int16_t msize = cm->u.user.match_size; char name[sizeof(m->u.user.name)]; @@ -743,9 +743,6 @@ void xt_compat_match_from_user(struct xt_entry_match *m, void **dstptr, match->compat_from_user(m->data, cm->data); else memcpy(m->data, cm->data, msize - sizeof(*cm)); - pad = XT_ALIGN(match->matchsize) - match->matchsize; - if (pad > 0) - memset(m->data + match->matchsize, 0, pad); msize += off; m->u.user.match_size = msize; @@ -1116,7 +1113,7 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, { const struct xt_target *target = t->u.kernel.target; struct compat_xt_entry_target *ct = (struct compat_xt_entry_target *)t; - int pad, off = xt_compat_target_offset(target); + int off = xt_compat_target_offset(target); u_int16_t tsize = ct->u.user.target_size; char name[sizeof(t->u.user.name)]; @@ -1126,9 +1123,6 @@ void xt_compat_target_from_user(struct xt_entry_target *t, void **dstptr, target->compat_from_user(t->data, ct->data); else memcpy(t->data, ct->data, tsize - sizeof(*ct)); - pad = XT_ALIGN(target->targetsize) - target->targetsize; - if (pad > 0) - memset(t->data + target->targetsize, 0, pad); tsize += off; t->u.user.target_size = tsize; From 4d8f9065830e526c83199186c5f56a6514f457d2 Mon Sep 17 00:00:00 2001 From: Pablo Neira Ayuso Date: Sat, 10 Apr 2021 21:29:38 +0200 Subject: [PATCH 0934/1091] netfilter: nftables: clone set element expression template memcpy() breaks when using connlimit in set elements. Use nft_expr_clone() to initialize the connlimit expression list, otherwise connlimit garbage collector crashes when walking on the list head copy. [ 493.064656] Workqueue: events_power_efficient nft_rhash_gc [nf_tables] [ 493.064685] RIP: 0010:find_or_evict+0x5a/0x90 [nf_conncount] [ 493.064694] Code: 2b 43 40 83 f8 01 77 0d 48 c7 c0 f5 ff ff ff 44 39 63 3c 75 df 83 6d 18 01 48 8b 43 08 48 89 de 48 8b 13 48 8b 3d ee 2f 00 00 <48> 89 42 08 48 89 10 48 b8 00 01 00 00 00 00 ad de 48 89 03 48 83 [ 493.064699] RSP: 0018:ffffc90000417dc0 EFLAGS: 00010297 [ 493.064704] RAX: 0000000000000000 RBX: ffff888134f38410 RCX: 0000000000000000 [ 493.064708] RDX: 0000000000000000 RSI: ffff888134f38410 RDI: ffff888100060cc0 [ 493.064711] RBP: ffff88812ce594a8 R08: ffff888134f38438 R09: 00000000ebb9025c [ 493.064714] R10: ffffffff8219f838 R11: 0000000000000017 R12: 0000000000000001 [ 493.064718] R13: ffffffff82146740 R14: ffff888134f38410 R15: 0000000000000000 [ 493.064721] FS: 0000000000000000(0000) GS:ffff88840e440000(0000) knlGS:0000000000000000 [ 493.064725] CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 [ 493.064729] CR2: 0000000000000008 CR3: 00000001330aa002 CR4: 00000000001706e0 [ 493.064733] Call Trace: [ 493.064737] nf_conncount_gc_list+0x8f/0x150 [nf_conncount] [ 493.064746] nft_rhash_gc+0x106/0x390 [nf_tables] Reported-by: Laura Garcia Liebana Fixes: 409444522976 ("netfilter: nf_tables: add elements with stateful expressions") Signed-off-by: Pablo Neira Ayuso --- net/netfilter/nf_tables_api.c | 46 ++++++++++++++++++++++++++--------- 1 file changed, 34 insertions(+), 12 deletions(-) diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index f57f1a6ba96f..589d2f6978d3 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -5295,16 +5295,35 @@ err_expr: return -ENOMEM; } -static void nft_set_elem_expr_setup(const struct nft_set_ext *ext, int i, - struct nft_expr *expr_array[]) +static int nft_set_elem_expr_setup(struct nft_ctx *ctx, + const struct nft_set_ext *ext, + struct nft_expr *expr_array[], + u32 num_exprs) { struct nft_set_elem_expr *elem_expr = nft_set_ext_expr(ext); - struct nft_expr *expr = nft_setelem_expr_at(elem_expr, elem_expr->size); + struct nft_expr *expr; + int i, err; - memcpy(expr, expr_array[i], expr_array[i]->ops->size); - elem_expr->size += expr_array[i]->ops->size; - kfree(expr_array[i]); - expr_array[i] = NULL; + for (i = 0; i < num_exprs; i++) { + expr = nft_setelem_expr_at(elem_expr, elem_expr->size); + err = nft_expr_clone(expr, expr_array[i]); + if (err < 0) + goto err_elem_expr_setup; + + elem_expr->size += expr_array[i]->ops->size; + nft_expr_destroy(ctx, expr_array[i]); + expr_array[i] = NULL; + } + + return 0; + +err_elem_expr_setup: + for (; i < num_exprs; i++) { + nft_expr_destroy(ctx, expr_array[i]); + expr_array[i] = NULL; + } + + return -ENOMEM; } static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, @@ -5556,12 +5575,15 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set, *nft_set_ext_obj(ext) = obj; obj->use++; } - for (i = 0; i < num_exprs; i++) - nft_set_elem_expr_setup(ext, i, expr_array); + err = nft_set_elem_expr_setup(ctx, ext, expr_array, num_exprs); + if (err < 0) + goto err_elem_expr; trans = nft_trans_elem_alloc(ctx, NFT_MSG_NEWSETELEM, set); - if (trans == NULL) - goto err_trans; + if (trans == NULL) { + err = -ENOMEM; + goto err_elem_expr; + } ext->genmask = nft_genmask_cur(ctx->net) | NFT_SET_ELEM_BUSY_MASK; err = set->ops->insert(ctx->net, set, &elem, &ext2); @@ -5605,7 +5627,7 @@ err_set_full: set->ops->remove(ctx->net, set, &elem); err_element_clash: kfree(trans); -err_trans: +err_elem_expr: if (obj) obj->use--; From 738fa58ee1328481d1d7889e7c430b3401c571b9 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Mon, 12 Apr 2021 17:41:01 +0800 Subject: [PATCH 0935/1091] arm64: kprobes: Restore local irqflag if kprobes is cancelled If instruction being single stepped caused a page fault, the kprobes is cancelled to let the page fault handler continue as a normal page fault. But the local irqflags are disabled so cpu will restore pstate with DAIF masked. After pagefault is serviced, the kprobes is triggerred again, we overwrite the saved_irqflag by calling kprobes_save_local_irqflag(). NOTE, DAIF is masked in this new saved irqflag. After kprobes is serviced, the cpu pstate is retored with DAIF masked. This patch is inspired by one patch for riscv from Liao Chang. Signed-off-by: Jisheng Zhang Acked-by: Masami Hiramatsu Link: https://lore.kernel.org/r/20210412174101.6bfb0594@xhacker.debian Signed-off-by: Will Deacon --- arch/arm64/kernel/probes/kprobes.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kernel/probes/kprobes.c b/arch/arm64/kernel/probes/kprobes.c index 66aac2881ba8..85645b2b0c7a 100644 --- a/arch/arm64/kernel/probes/kprobes.c +++ b/arch/arm64/kernel/probes/kprobes.c @@ -267,10 +267,12 @@ int __kprobes kprobe_fault_handler(struct pt_regs *regs, unsigned int fsr) if (!instruction_pointer(regs)) BUG(); - if (kcb->kprobe_status == KPROBE_REENTER) + if (kcb->kprobe_status == KPROBE_REENTER) { restore_previous_kprobe(kcb); - else + } else { + kprobes_restore_local_irqflag(kcb, regs); reset_current_kprobe(); + } break; case KPROBE_HIT_ACTIVE: From 858066864a6383d1eecd2fa96a0b8e69935632f8 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Mon, 12 Apr 2021 15:22:56 +0200 Subject: [PATCH 0936/1091] ASoC: meson: axg-frddr: fix fifo depth on g12 and sm1 Previous fifo depth patch was only tested on axg, not g12 or sm1. Of course, while adding hw_params dai callback for the axg, I forgot to do the same for g12 and sm1, leaving the depth unset and breaking playback on these SoCs. Add hw_params callback to the g12 dai_ops to fix the problem. Fixes: 6f68accaa864 ("ASoC: meson: axg-frddr: set fifo depth according to the period") Reported-by: Christian Hewitt Tested-by: Christian Hewitt Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210412132256.89920-1-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/meson/axg-frddr.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/meson/axg-frddr.c b/sound/soc/meson/axg-frddr.c index 8ed114de0bdf..37f4bb3469b5 100644 --- a/sound/soc/meson/axg-frddr.c +++ b/sound/soc/meson/axg-frddr.c @@ -171,6 +171,7 @@ static const struct axg_fifo_match_data axg_frddr_match_data = { static const struct snd_soc_dai_ops g12a_frddr_ops = { .prepare = g12a_frddr_dai_prepare, + .hw_params = axg_frddr_dai_hw_params, .startup = axg_frddr_dai_startup, .shutdown = axg_frddr_dai_shutdown, }; From 59f5cd96e9b9e1025ab0a9dc4ce9dd8633190794 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:51:59 +0900 Subject: [PATCH 0937/1091] ASoC: simple-card-utils: setup dai_props cpu_dai/codec_dai at initial timing We couldn't setup dai_props cpu_dai/codec_dai at the initial timing, because "counting DAIs loop" and "detecting DAIs loop" were different. But we can do it now, because these are using same loops. This patch setups dai_props cpu_dai/codec_dai at the initial timing. It can removes triky code from simple-card / audio-graph. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tuocwfa8.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 19 +++++-------------- sound/soc/generic/simple-card-utils.c | 10 ++++++++++ sound/soc/generic/simple-card.c | 24 +++++------------------- 3 files changed, 20 insertions(+), 33 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 7be2c2cb253e..5ce5b7d62ee0 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -245,8 +245,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - dai = - dai_props->cpu_dai = &priv->dais[li->dais++]; + dai = dai_props->cpu_dai; ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links); if (ret) @@ -288,11 +287,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; - dai = - dai_props->codec_dai = &priv->dais[li->dais++]; - - cconf = - dai_props->codec_conf = &priv->codec_conf[li->conf++]; + dai = dai_props->codec_dai; + cconf = dai_props->codec_conf; ret = asoc_simple_parse_codec(ep, dai_link); if (ret < 0) @@ -358,19 +354,14 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct device_node *top = dev->of_node; - struct asoc_simple_dai *cpu_dai; - struct asoc_simple_dai *codec_dai; + struct asoc_simple_dai *cpu_dai = dai_props->cpu_dai; + struct asoc_simple_dai *codec_dai = dai_props->codec_dai; int ret, single_cpu = 0; dev_dbg(dev, "link_of (%pOF)\n", cpu_ep); li->link++; - cpu_dai = - dai_props->cpu_dai = &priv->dais[li->dais++]; - codec_dai = - dai_props->codec_dai = &priv->dais[li->dais++]; - /* Factor to mclk, used in hw_params() */ graph_parse_mclk_fs(top, cpu_ep, dai_props); graph_parse_mclk_fs(top, codec_ep, dai_props); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 64b1ff5bafda..ca74dfa58458 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -649,8 +649,10 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].cpus = dlcs; dai_props[i].num.cpus = dai_link[i].num_cpus = li->num[i].cpus; + dai_props[i].cpu_dai = dais; dlcs += li->num[i].cpus; + dais += li->num[i].cpus; } else { /* DPCM Be's CPU = dummy */ dai_props[i].cpus = @@ -665,8 +667,16 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_link[i].codecs = dlcs; dai_props[i].num.codecs = dai_link[i].num_codecs = li->num[i].codecs; + dai_props[i].codec_dai = dais; dlcs += li->num[i].codecs; + dais += li->num[i].codecs; + + if (!li->num[i].cpus) { + /* DPCM Be's Codec */ + dai_props[i].codec_conf = cconf; + cconf += li->num[i].codecs; + } } else { /* DPCM Fe's Codec = dummy */ dai_props[i].codecs = diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9132c0ea05af..30da8272fbc0 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -146,8 +146,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - dai = - dai_props->cpu_dai = &priv->dais[li->dais++]; + dai = dai_props->cpu_dai; ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links); if (ret) @@ -174,11 +173,8 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; - dai = - dai_props->codec_dai = &priv->dais[li->dais++]; - - cconf = - dai_props->codec_conf = &priv->codec_conf[li->conf++]; + dai = dai_props->codec_dai; + cconf = dai_props->codec_conf; ret = asoc_simple_parse_codec(np, dai_link); if (ret < 0) @@ -234,8 +230,8 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); - struct asoc_simple_dai *cpu_dai; - struct asoc_simple_dai *codec_dai; + struct asoc_simple_dai *cpu_dai = dai_props->cpu_dai; + struct asoc_simple_dai *codec_dai = dai_props->codec_dai; struct device_node *top = dev->of_node; struct device_node *cpu = NULL; struct device_node *node = NULL; @@ -257,11 +253,6 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, snprintf(prop, sizeof(prop), "%splat", prefix); plat = of_get_child_by_name(node, prop); - cpu_dai = - dai_props->cpu_dai = &priv->dais[li->dais++]; - codec_dai = - dai_props->codec_dai = &priv->dais[li->dais++]; - ret = asoc_simple_parse_daifmt(dev, node, codec, prefix, &dai_link->dai_fmt); if (ret < 0) @@ -670,8 +661,6 @@ static int asoc_simple_probe(struct platform_device *pdev) struct snd_soc_dai_link *dai_link = priv->dai_link; struct simple_dai_props *dai_props = priv->dai_props; - int dai_idx = 0; - cinfo = dev->platform_data; if (!cinfo) { dev_err(dev, "no info for asoc-simple-card\n"); @@ -687,9 +676,6 @@ static int asoc_simple_probe(struct platform_device *pdev) return -EINVAL; } - dai_props->cpu_dai = &priv->dais[dai_idx++]; - dai_props->codec_dai = &priv->dais[dai_idx++]; - cpus = dai_link->cpus; cpus->dai_name = cinfo->cpu_dai.name; From f899006d558546a8ee39c93f816eb3847c5bc6c0 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:04 +0900 Subject: [PATCH 0938/1091] ASoC: simple-card-utils: remove li->dais/li->conf li->dais is same as number of CPU + Codec, li->conf is same as number of Codec when dummy-Codec. li->dais/li->conf are no longer needed. This patch removes these. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sg3wwfa3.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 2 -- sound/soc/generic/audio-graph-card.c | 10 +--------- sound/soc/generic/simple-card-utils.c | 14 ++++++++++---- sound/soc/generic/simple-card.c | 11 +---------- 4 files changed, 12 insertions(+), 25 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 6635283a8160..da9d7e3665a8 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -75,9 +75,7 @@ struct asoc_simple_priv { #define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i)) struct link_info { - int dais; /* number of dai */ int link; /* number of link */ - int conf; /* number of codec_conf */ int cpu; /* turn for CPU / Codec */ struct prop_nums num[SNDRV_MINOR_DEVICES]; }; diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 5ce5b7d62ee0..3a5bef2a91d3 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -552,7 +552,7 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) memset(&li, 0, sizeof(li)); graph_get_dais_count(priv, &li); - if (!li.link || !li.dais) + if (!li.link) return -EINVAL; ret = asoc_simple_init_priv(priv, &li); @@ -622,7 +622,6 @@ static int graph_count_noml(struct asoc_simple_priv *priv, li->num[li->link].platforms = 1; li->link += 1; /* 1xCPU-Codec */ - li->dais += 2; /* 1xCPU + 1xCodec */ dev_dbg(dev, "Count As Normal\n"); @@ -646,13 +645,10 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, li->num[li->link].platforms = 1; li->link++; /* 1xCPU-dummy */ - li->dais++; /* 1xCPU */ } else { li->num[li->link].codecs = 1; li->link++; /* 1xdummy-Codec */ - li->conf++; /* 1xdummy-Codec */ - li->dais++; /* 1xCodec */ } dev_dbg(dev, "Count As DPCM\n"); @@ -663,8 +659,6 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, static void graph_get_dais_count(struct asoc_simple_priv *priv, struct link_info *li) { - struct device *dev = simple_priv_to_dev(priv); - /* * link_num : number of links. * CPU-Codec / CPU-dummy / dummy-Codec @@ -714,8 +708,6 @@ static void graph_get_dais_count(struct asoc_simple_priv *priv, graph_for_each_link(priv, li, graph_count_noml, graph_count_dpcm); - dev_dbg(dev, "link %d, dais %d, ccnf %d\n", - li->link, li->dais, li->conf); } int audio_graph_card_probe(struct snd_soc_card *card) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index ca74dfa58458..59b4fb2bd586 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -597,7 +597,7 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct asoc_simple_dai *dais; struct snd_soc_dai_link_component *dlcs; struct snd_soc_codec_conf *cconf = NULL; - int i, dai_num = 0, dlc_num = 0; + int i, dai_num = 0, dlc_num = 0, cnf_num = 0; dai_props = devm_kcalloc(dev, li->link, sizeof(*dai_props), GFP_KERNEL); dai_link = devm_kcalloc(dev, li->link, sizeof(*dai_link), GFP_KERNEL); @@ -613,6 +613,9 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, dai_num += cc; dlc_num += cc + li->num[i].platforms; + + if (!li->num[i].cpus) + cnf_num += li->num[i].codecs; } dais = devm_kcalloc(dev, dai_num, sizeof(*dais), GFP_KERNEL); @@ -620,12 +623,15 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, if (!dais || !dlcs) return -ENOMEM; - if (li->conf) { - cconf = devm_kcalloc(dev, li->conf, sizeof(*cconf), GFP_KERNEL); + if (cnf_num) { + cconf = devm_kcalloc(dev, cnf_num, sizeof(*cconf), GFP_KERNEL); if (!cconf) return -ENOMEM; } + dev_dbg(dev, "link %d, dais %d, ccnf %d\n", + li->link, dai_num, cnf_num); + /* dummy CPU/Codec */ priv->dummy.of_node = NULL; priv->dummy.dai_name = "snd-soc-dummy-dai"; @@ -640,7 +646,7 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, card->dai_link = priv->dai_link; card->num_links = li->link; card->codec_conf = cconf; - card->num_configs = li->conf; + card->num_configs = cnf_num; for (i = 0; i < li->link; i++) { if (li->num[i].cpus) { diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 30da8272fbc0..7665bbf2a6c0 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -495,7 +495,6 @@ static int simple_count_noml(struct asoc_simple_priv *priv, li->num[li->link].platforms = 1; li->link += 1; - li->dais += 2; return 0; } @@ -517,13 +516,10 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, li->num[li->link].platforms = 1; li->link++; /* CPU-dummy */ - li->dais++; } else { li->num[li->link].codecs = 1; li->link++; /* dummy-Codec */ - li->dais++; - li->conf++; } return 0; @@ -587,17 +583,12 @@ static void simple_get_dais_count(struct asoc_simple_priv *priv, li->num[0].platforms = 1; li->link = 1; - li->dais = 2; - li->conf = 0; return; } simple_for_each_link(priv, li, simple_count_noml, simple_count_dpcm); - - dev_dbg(dev, "link %d, dais %d, ccnf %d\n", - li->link, li->dais, li->conf); } static int simple_soc_probe(struct snd_soc_card *card) @@ -637,7 +628,7 @@ static int asoc_simple_probe(struct platform_device *pdev) memset(&li, 0, sizeof(li)); simple_get_dais_count(priv, &li); - if (!li.link || !li.dais) + if (!li.link) return -EINVAL; ret = asoc_simple_init_priv(priv, &li); From fafc05aadd4b6ce5c161135de9d3a653fc054543 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:09 +0900 Subject: [PATCH 0939/1091] ASoC: simple-card-utils: use for_each_prop_xxx() ASoC is now supporting multi DAI, but, current simple-card / audio-graph are assuming fixed single DAI. This patch uses for_each_prop_xxx() to support multi DAI. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87r1jgwf9y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 43 ++++++++- sound/soc/generic/simple-card-utils.c | 126 +++++++++++++++----------- 2 files changed, 113 insertions(+), 56 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index da9d7e3665a8..de40f09d226f 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -74,6 +74,34 @@ struct asoc_simple_priv { #define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev) #define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i)) +#define for_each_prop_dlc_cpus(props, i, cpu) \ + for ((i) = 0; \ + ((i) < (props)->num.cpus) && ((cpu) = &(props)->cpus[i]); \ + (i)++) +#define for_each_prop_dlc_codecs(props, i, codec) \ + for ((i) = 0; \ + ((i) < (props)->num.codecs) && ((codec) = &(props)->codecs[i]); \ + (i)++) +#define for_each_prop_dlc_platforms(props, i, platform) \ + for ((i) = 0; \ + ((i) < (props)->num.platforms) && ((platform) = &(props)->platforms[i]); \ + (i)++) +#define for_each_prop_codec_conf(props, i, conf) \ + for ((i) = 0; \ + ((i) < (props)->num.codecs) && \ + (props)->codec_conf && \ + ((conf) = &(props)->codec_conf[i]); \ + (i)++) + +#define for_each_prop_dai_cpu(props, i, cpu) \ + for ((i) = 0; \ + ((i) < (props)->num.cpus) && ((cpu) = &(props)->cpu_dai[i]); \ + (i)++) +#define for_each_prop_dai_codec(props, i, codec) \ + for ((i) = 0; \ + ((i) < (props)->num.codecs) && ((codec) = &(props)->codec_dai[i]); \ + (i)++) + struct link_info { int link; /* number of link */ int cpu; /* turn for CPU / Codec */ @@ -192,11 +220,16 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) for (i = 0; i < card->num_links; i++) { struct simple_dai_props *props = simple_priv_to_props(priv, i); struct snd_soc_dai_link *link = simple_priv_to_link(priv, i); + struct asoc_simple_dai *dai; + struct snd_soc_codec_conf *cnf; + int j; dev_dbg(dev, "DAI%d\n", i); - asoc_simple_debug_dai(priv, "cpu", props->cpu_dai); - asoc_simple_debug_dai(priv, "codec", props->codec_dai); + for_each_prop_dai_cpu(props, j, dai) + asoc_simple_debug_dai(priv, "cpu", dai); + for_each_prop_dai_codec(props, j, dai) + asoc_simple_debug_dai(priv, "codec", dai); if (link->name) dev_dbg(dev, "dai name = %s\n", link->name); @@ -209,9 +242,9 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) if (props->adata.convert_channels) dev_dbg(dev, "convert_channels = %d\n", props->adata.convert_channels); - if (props->codec_conf && props->codec_conf->name_prefix) - dev_dbg(dev, "name prefix = %s\n", - props->codec_conf->name_prefix); + for_each_prop_codec_conf(props, j, cnf) + if (cnf->name_prefix) + dev_dbg(dev, "name prefix = %s\n", cnf->name_prefix); if (props->mclk_fs) dev_dbg(dev, "mclk-fs = %d\n", props->mclk_fs); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 59b4fb2bd586..fad9c7f37d2b 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -195,17 +195,37 @@ int asoc_simple_startup(struct snd_pcm_substream *substream) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); + struct asoc_simple_dai *dai; + int i1, i2, i; int ret; - ret = asoc_simple_clk_enable(dai_props->cpu_dai); - if (ret) - return ret; + for_each_prop_dai_cpu(props, i1, dai) { + ret = asoc_simple_clk_enable(dai); + if (ret) + goto cpu_err; + } - ret = asoc_simple_clk_enable(dai_props->codec_dai); - if (ret) - asoc_simple_clk_disable(dai_props->cpu_dai); + for_each_prop_dai_codec(props, i2, dai) { + ret = asoc_simple_clk_enable(dai); + if (ret) + goto codec_err; + } + return 0; + +codec_err: + for_each_prop_dai_codec(props, i, dai) { + if (i >= i2) + break; + asoc_simple_clk_disable(dai); + } +cpu_err: + for_each_prop_dai_cpu(props, i, dai) { + if (i >= i1) + break; + asoc_simple_clk_disable(dai); + } return ret; } EXPORT_SYMBOL_GPL(asoc_simple_startup); @@ -216,17 +236,19 @@ void asoc_simple_shutdown(struct snd_pcm_substream *substream) struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *dai_props = - simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); + struct asoc_simple_dai *dai; + int i; - if (dai_props->mclk_fs) { + if (props->mclk_fs) { snd_soc_dai_set_sysclk(codec_dai, 0, 0, SND_SOC_CLOCK_IN); snd_soc_dai_set_sysclk(cpu_dai, 0, 0, SND_SOC_CLOCK_OUT); } - asoc_simple_clk_disable(dai_props->cpu_dai); - - asoc_simple_clk_disable(dai_props->codec_dai); + for_each_prop_dai_cpu(props, i, dai) + asoc_simple_clk_disable(dai); + for_each_prop_dai_codec(props, i, dai) + asoc_simple_clk_disable(dai); } EXPORT_SYMBOL_GPL(asoc_simple_shutdown); @@ -249,41 +271,41 @@ int asoc_simple_hw_params(struct snd_pcm_substream *substream, struct snd_pcm_hw_params *params) { struct snd_soc_pcm_runtime *rtd = asoc_substream_to_rtd(substream); - struct snd_soc_dai *codec_dai = asoc_rtd_to_codec(rtd, 0); - struct snd_soc_dai *cpu_dai = asoc_rtd_to_cpu(rtd, 0); + struct asoc_simple_dai *pdai; + struct snd_soc_dai *sdai; struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *dai_props = - simple_priv_to_props(priv, rtd->num); + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); unsigned int mclk, mclk_fs = 0; - int ret; + int i, ret; - if (dai_props->mclk_fs) - mclk_fs = dai_props->mclk_fs; + if (props->mclk_fs) + mclk_fs = props->mclk_fs; if (mclk_fs) { mclk = params_rate(params) * mclk_fs; - ret = asoc_simple_set_clk_rate(dai_props->codec_dai, mclk); - if (ret < 0) - return ret; - - ret = asoc_simple_set_clk_rate(dai_props->cpu_dai, mclk); - if (ret < 0) - return ret; - - ret = snd_soc_dai_set_sysclk(codec_dai, 0, mclk, - SND_SOC_CLOCK_IN); - if (ret && ret != -ENOTSUPP) - goto err; - - ret = snd_soc_dai_set_sysclk(cpu_dai, 0, mclk, - SND_SOC_CLOCK_OUT); - if (ret && ret != -ENOTSUPP) - goto err; + for_each_prop_dai_codec(props, i, pdai) { + ret = asoc_simple_set_clk_rate(pdai, mclk); + if (ret < 0) + return ret; + } + for_each_prop_dai_cpu(props, i, pdai) { + ret = asoc_simple_set_clk_rate(pdai, mclk); + if (ret < 0) + return ret; + } + for_each_rtd_codec_dais(rtd, i, sdai) { + ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_IN); + if (ret && ret != -ENOTSUPP) + return ret; + } + for_each_rtd_cpu_dais(rtd, i, sdai) { + ret = snd_soc_dai_set_sysclk(sdai, 0, mclk, SND_SOC_CLOCK_OUT); + if (ret && ret != -ENOTSUPP) + return ret; + } } return 0; -err: - return ret; } EXPORT_SYMBOL_GPL(asoc_simple_hw_params); @@ -378,20 +400,22 @@ static int asoc_simple_init_dai_link_params(struct snd_soc_pcm_runtime *rtd, int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd) { struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(rtd->card); - struct simple_dai_props *dai_props = simple_priv_to_props(priv, rtd->num); - int ret; + struct simple_dai_props *props = simple_priv_to_props(priv, rtd->num); + struct asoc_simple_dai *dai; + int i, ret; - ret = asoc_simple_init_dai(asoc_rtd_to_codec(rtd, 0), - dai_props->codec_dai); - if (ret < 0) - return ret; + for_each_prop_dai_codec(props, i, dai) { + ret = asoc_simple_init_dai(asoc_rtd_to_codec(rtd, i), dai); + if (ret < 0) + return ret; + } + for_each_prop_dai_cpu(props, i, dai) { + ret = asoc_simple_init_dai(asoc_rtd_to_cpu(rtd, i), dai); + if (ret < 0) + return ret; + } - ret = asoc_simple_init_dai(asoc_rtd_to_cpu(rtd, 0), - dai_props->cpu_dai); - if (ret < 0) - return ret; - - ret = asoc_simple_init_dai_link_params(rtd, dai_props); + ret = asoc_simple_init_dai_link_params(rtd, props); if (ret < 0) return ret; From e25704f84ca2b586e8e65d1b2ab686205b3076fe Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:13 +0900 Subject: [PATCH 0940/1091] ASoC: simple-card-utils: remove asoc_simple_parse_xxx() ASoC is now supporting multi DAI, but, current simple-card / audio-graph are assuming fixed single DAI. Now, asoc_simple_parse_xxx() macro is assuming single DAI. To support multi-CPU/Codec, this patch unpack asoc_simple_parse_xxx() macro, and uses "&dai_link->cpus[i]" instead of "dai_link->cpus". Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pmz0wf9u.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 11 ----------- sound/soc/generic/audio-graph-card.c | 16 ++++++++-------- sound/soc/generic/simple-card.c | 18 +++++++++--------- 3 files changed, 17 insertions(+), 28 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index de40f09d226f..23f17ccc7908 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -120,10 +120,6 @@ int asoc_simple_set_dailink_name(struct device *dev, int asoc_simple_parse_card_name(struct snd_soc_card *card, char *prefix); -#define asoc_simple_parse_clk_cpu(dev, node, dai_link, simple_dai) \ - asoc_simple_parse_clk(dev, node, simple_dai, dai_link->cpus) -#define asoc_simple_parse_clk_codec(dev, node, dai_link, simple_dai) \ - asoc_simple_parse_clk(dev, node, simple_dai, dai_link->codecs) int asoc_simple_parse_clk(struct device *dev, struct device_node *node, struct asoc_simple_dai *simple_dai, @@ -136,13 +132,6 @@ int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd); int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_pcm_hw_params *params); -#define asoc_simple_parse_cpu(node, dai_link, is_single_link) \ - asoc_simple_parse_dai(node, dai_link->cpus, is_single_link) -#define asoc_simple_parse_codec(node, dai_link) \ - asoc_simple_parse_dai(node, dai_link->codecs, NULL) -#define asoc_simple_parse_platform(node, dai_link) \ - asoc_simple_parse_dai(node, dai_link->platforms, NULL) - #define asoc_simple_parse_tdm(np, dai) \ snd_soc_of_parse_tdm_slot(np, &(dai)->tx_slot_mask, \ &(dai)->rx_slot_mask, \ diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 3a5bef2a91d3..145f8a19c9e8 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -247,11 +247,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->cpu_dai; - ret = asoc_simple_parse_cpu(ep, dai_link, &is_single_links); + ret = asoc_simple_parse_dai(ep, dai_link->cpus, &is_single_links); if (ret) goto out_put_node; - ret = asoc_simple_parse_clk_cpu(dev, ep, dai_link, dai); + ret = asoc_simple_parse_clk(dev, ep, dai, dai_link->cpus); if (ret < 0) goto out_put_node; @@ -290,11 +290,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->codec_dai; cconf = dai_props->codec_conf; - ret = asoc_simple_parse_codec(ep, dai_link); + ret = asoc_simple_parse_dai(ep, dai_link->codecs, NULL); if (ret < 0) goto out_put_node; - ret = asoc_simple_parse_clk_codec(dev, ep, dai_link, dai); + ret = asoc_simple_parse_clk(dev, ep, dai, dai_link->codecs); if (ret < 0) goto out_put_node; @@ -371,11 +371,11 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) return ret; - ret = asoc_simple_parse_cpu(cpu_ep, dai_link, &single_cpu); + ret = asoc_simple_parse_dai(cpu_ep, dai_link->cpus, &single_cpu); if (ret < 0) return ret; - ret = asoc_simple_parse_codec(codec_ep, dai_link); + ret = asoc_simple_parse_dai(codec_ep, dai_link->codecs, NULL); if (ret < 0) return ret; @@ -387,11 +387,11 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) return ret; - ret = asoc_simple_parse_clk_cpu(dev, cpu_ep, dai_link, cpu_dai); + ret = asoc_simple_parse_clk(dev, cpu_ep, cpu_dai, dai_link->cpus); if (ret < 0) return ret; - ret = asoc_simple_parse_clk_codec(dev, codec_ep, dai_link, codec_dai); + ret = asoc_simple_parse_clk(dev, codec_ep, codec_dai, dai_link->codecs); if (ret < 0) return ret; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7665bbf2a6c0..6a55b8672166 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -148,11 +148,11 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->cpu_dai; - ret = asoc_simple_parse_cpu(np, dai_link, &is_single_links); + ret = asoc_simple_parse_dai(np, dai_link->cpus, &is_single_links); if (ret) goto out_put_node; - ret = asoc_simple_parse_clk_cpu(dev, np, dai_link, dai); + ret = asoc_simple_parse_clk(dev, np, dai, dai_link->cpus); if (ret < 0) goto out_put_node; @@ -176,11 +176,11 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->codec_dai; cconf = dai_props->codec_conf; - ret = asoc_simple_parse_codec(np, dai_link); + ret = asoc_simple_parse_dai(np, dai_link->codecs, NULL); if (ret < 0) goto out_put_node; - ret = asoc_simple_parse_clk_codec(dev, np, dai_link, dai); + ret = asoc_simple_parse_clk(dev, np, dai, dai_link->codecs); if (ret < 0) goto out_put_node; @@ -260,15 +260,15 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix); - ret = asoc_simple_parse_cpu(cpu, dai_link, &single_cpu); + ret = asoc_simple_parse_dai(cpu, dai_link->cpus, &single_cpu); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_codec(codec, dai_link); + ret = asoc_simple_parse_dai(codec, dai_link->codecs, NULL); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_platform(plat, dai_link); + ret = asoc_simple_parse_dai(plat, dai_link->platforms, NULL); if (ret < 0) goto dai_link_of_err; @@ -280,11 +280,11 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_clk_cpu(dev, cpu, dai_link, cpu_dai); + ret = asoc_simple_parse_clk(dev, cpu, cpu_dai, dai_link->cpus); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_clk_codec(dev, codec, dai_link, codec_dai); + ret = asoc_simple_parse_clk(dev, codec, codec_dai, dai_link->codecs); if (ret < 0) goto dai_link_of_err; From 1cf6805700ecf25942468a01eff902ab8c32ce3c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:18 +0900 Subject: [PATCH 0941/1091] ASoC: simple-card-utils: care multi DAI at asoc_simple_clean_reference() ASoC is now supporting multi DAI, but, current simple-card / audio-graph are assuming fixed single DAI. This patch cares multi DAI at asoc_simple_clean_reference() for of_node_put(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o8ekwf9p.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card-utils.c | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index fad9c7f37d2b..6efe3757eff8 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -451,11 +451,15 @@ EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_cpu); int asoc_simple_clean_reference(struct snd_soc_card *card) { struct snd_soc_dai_link *dai_link; - int i; + struct snd_soc_dai_link_component *cpu; + struct snd_soc_dai_link_component *codec; + int i, j; for_each_card_prelinks(card, i, dai_link) { - of_node_put(dai_link->cpus->of_node); - of_node_put(dai_link->codecs->of_node); + for_each_link_cpus(dai_link, j, cpu) + of_node_put(cpu->of_node); + for_each_link_codecs(dai_link, j, codec) + of_node_put(codec->of_node); } return 0; } From ac813c625ad5c3ee98a99e1b37659a0d85178978 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:23 +0900 Subject: [PATCH 0942/1091] ASoC: simple-card-utils: indicate dai_fmt if exist link->dai_fmt might be 0. Don't indicate it in such case when debugging. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mtu4wf9k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 23f17ccc7908..080fe7eb560f 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -222,9 +222,8 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) if (link->name) dev_dbg(dev, "dai name = %s\n", link->name); - - dev_dbg(dev, "dai format = %04x\n", link->dai_fmt); - + if (link->dai_fmt) + dev_dbg(dev, "dai format = %04x\n", link->dai_fmt); if (props->adata.convert_rate) dev_dbg(dev, "convert_rate = %d\n", props->adata.convert_rate); From 40d8cbe70e71be170e0a4fe6ab112d9aaa9cfb18 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:27 +0900 Subject: [PATCH 0943/1091] ASoC: simple-card-utils: indicate missing CPU/Codec numbers for debug Now ALSA is supporting multi-CPU/Codec, thus, we want to know number of CPU/Codec when debugging. This patch indicates it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lf9owf9g.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 080fe7eb560f..e366e432c475 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -215,8 +215,10 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) dev_dbg(dev, "DAI%d\n", i); + dev_dbg(dev, "cpu num = %d\n", link->num_cpus); for_each_prop_dai_cpu(props, j, dai) asoc_simple_debug_dai(priv, "cpu", dai); + dev_dbg(dev, "codec num = %d\n", link->num_codecs); for_each_prop_dai_codec(props, j, dai) asoc_simple_debug_dai(priv, "codec", dai); From 9830d3e99f51fc1c1c6ab8be7778fd205af198ad Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:32 +0900 Subject: [PATCH 0944/1091] ASoC: simple-card-utils: add simple_props_to_xxx() macro We shouldn't use dai_props->cpus/codecs/cpu_dai/codec_dai/codec_conf directly, because these are array to supporting multi CPU/Codec/Platform. This patch adds asoc_link_to_xxx() macro for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0p8wf9b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 27 ++++++++++++++++++++------- 1 file changed, 20 insertions(+), 7 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index e366e432c475..78b6cf0194d2 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -74,32 +74,45 @@ struct asoc_simple_priv { #define simple_priv_to_dev(priv) (simple_priv_to_card(priv)->dev) #define simple_priv_to_link(priv, i) (simple_priv_to_card(priv)->dai_link + (i)) +#define simple_props_to_dlc_cpu(props, i) ((props)->cpus + i) +#define simple_props_to_dlc_codec(props, i) ((props)->codecs + i) +#define simple_props_to_dlc_platform(props, i) ((props)->platforms + i) + +#define simple_props_to_dai_cpu(props, i) ((props)->cpu_dai + i) +#define simple_props_to_dai_codec(props, i) ((props)->codec_dai + i) +#define simple_props_to_codec_conf(props, i) ((props)->codec_conf + i) + #define for_each_prop_dlc_cpus(props, i, cpu) \ for ((i) = 0; \ - ((i) < (props)->num.cpus) && ((cpu) = &(props)->cpus[i]); \ + ((i) < (props)->num.cpus) && \ + ((cpu) = simple_props_to_dlc_cpu(props, i)); \ (i)++) -#define for_each_prop_dlc_codecs(props, i, codec) \ +#define for_each_prop_dlc_codecs(props, i, codec) \ for ((i) = 0; \ - ((i) < (props)->num.codecs) && ((codec) = &(props)->codecs[i]); \ + ((i) < (props)->num.codecs) && \ + ((codec) = simple_props_to_dlc_codec(props, i)); \ (i)++) #define for_each_prop_dlc_platforms(props, i, platform) \ for ((i) = 0; \ - ((i) < (props)->num.platforms) && ((platform) = &(props)->platforms[i]); \ + ((i) < (props)->num.platforms) && \ + ((platform) = simple_props_to_dlc_platform(props, i)); \ (i)++) #define for_each_prop_codec_conf(props, i, conf) \ for ((i) = 0; \ ((i) < (props)->num.codecs) && \ (props)->codec_conf && \ - ((conf) = &(props)->codec_conf[i]); \ + ((conf) = simple_props_to_codec_conf(props, i)); \ (i)++) #define for_each_prop_dai_cpu(props, i, cpu) \ for ((i) = 0; \ - ((i) < (props)->num.cpus) && ((cpu) = &(props)->cpu_dai[i]); \ + ((i) < (props)->num.cpus) && \ + ((cpu) = simple_props_to_dai_cpu(props, i)); \ (i)++) #define for_each_prop_dai_codec(props, i, codec) \ for ((i) = 0; \ - ((i) < (props)->num.codecs) && ((codec) = &(props)->codec_dai[i]); \ + ((i) < (props)->num.codecs) && \ + ((codec) = simple_props_to_dai_codec(props, i)); \ (i)++) struct link_info { From c826ec0391c83f06354a4ebb25c7b2480c18f33a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:45 +0900 Subject: [PATCH 0945/1091] ASoC: simple-card-utils: multi support at asoc_simple_canonicalize_cpu/platform() Current asoc_simple_canonicalize_cpu/platform() is assuming single CPU, single Platform, but we want to support Multi support. This patch is prepare for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87im4swf8y.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 7 ++++--- sound/soc/generic/audio-graph-card.c | 9 +++++---- sound/soc/generic/simple-card-utils.c | 11 ++++++----- sound/soc/generic/simple-card.c | 9 +++++---- 4 files changed, 20 insertions(+), 16 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 78b6cf0194d2..cccd9987a1b4 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -151,9 +151,10 @@ int asoc_simple_be_hw_params_fixup(struct snd_soc_pcm_runtime *rtd, &(dai)->slots, \ &(dai)->slot_width); -void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link); -void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link, - int is_single_links); +void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms, + struct snd_soc_dai_link_component *cpus); +void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, + int is_single_links); int asoc_simple_clean_reference(struct snd_soc_card *card); diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 145f8a19c9e8..e6b64fdbdc76 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -226,6 +226,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct asoc_simple_dai *dai; struct snd_soc_dai_link_component *cpus = dai_link->cpus; struct snd_soc_dai_link_component *codecs = dai_link->codecs; + struct snd_soc_dai_link_component *platforms = dai_link->platforms; int ret; port = of_get_parent(ep); @@ -276,8 +277,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; /* card->num_links includes Codec */ - asoc_simple_canonicalize_cpu(dai_link, is_single_links); - asoc_simple_canonicalize_platform(dai_link); + asoc_simple_canonicalize_cpu(cpus, is_single_links); + asoc_simple_canonicalize_platform(platforms, cpus); } else { struct snd_soc_codec_conf *cconf; @@ -405,8 +406,8 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, dai_link->ops = &graph_ops; dai_link->init = asoc_simple_dai_init; - asoc_simple_canonicalize_cpu(dai_link, single_cpu); - asoc_simple_canonicalize_platform(dai_link); + asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu); + asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus); return 0; } diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index 6efe3757eff8..a15956c25858 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -423,15 +423,16 @@ int asoc_simple_dai_init(struct snd_soc_pcm_runtime *rtd) } EXPORT_SYMBOL_GPL(asoc_simple_dai_init); -void asoc_simple_canonicalize_platform(struct snd_soc_dai_link *dai_link) +void asoc_simple_canonicalize_platform(struct snd_soc_dai_link_component *platforms, + struct snd_soc_dai_link_component *cpus) { /* Assumes platform == cpu */ - if (!dai_link->platforms->of_node) - dai_link->platforms->of_node = dai_link->cpus->of_node; + if (!platforms->of_node) + platforms->of_node = cpus->of_node; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_platform); -void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link, +void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link_component *cpus, int is_single_links) { /* @@ -444,7 +445,7 @@ void asoc_simple_canonicalize_cpu(struct snd_soc_dai_link *dai_link, * fmt_multiple_name() */ if (is_single_links) - dai_link->cpus->dai_name = NULL; + cpus->dai_name = NULL; } EXPORT_SYMBOL_GPL(asoc_simple_canonicalize_cpu); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 6a55b8672166..06b2d6a7f48d 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -124,6 +124,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct asoc_simple_dai *dai; struct snd_soc_dai_link_component *cpus = dai_link->cpus; struct snd_soc_dai_link_component *codecs = dai_link->codecs; + struct snd_soc_dai_link_component *platforms = dai_link->platforms; struct device_node *top = dev->of_node; struct device_node *node = of_get_parent(np); char *prefix = ""; @@ -162,8 +163,8 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node; - asoc_simple_canonicalize_cpu(dai_link, is_single_links); - asoc_simple_canonicalize_platform(dai_link); + asoc_simple_canonicalize_cpu(cpus, is_single_links); + asoc_simple_canonicalize_platform(platforms, cpus); } else { struct snd_soc_codec_conf *cconf; @@ -298,8 +299,8 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, dai_link->ops = &simple_ops; dai_link->init = asoc_simple_dai_init; - asoc_simple_canonicalize_cpu(dai_link, single_cpu); - asoc_simple_canonicalize_platform(dai_link); + asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu); + asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus); dai_link_of_err: of_node_put(plat); From 33cd6b191f1cdb5f332717a80ce26f661f53e924 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:50 +0900 Subject: [PATCH 0946/1091] ASoC: simple-card-utils: tidyup debug info for clock simple-card / audio-graph can use clock as dai->clk or dai->sysclk. These related information should be indicated at same position. This patch tidyup it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87h7kcwf8t.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index cccd9987a1b4..bf068803eb1f 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -191,12 +191,6 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, if (dai->name) dev_dbg(dev, "%s dai name = %s\n", name, dai->name); - if (dai->sysclk) - dev_dbg(dev, "%s sysclk = %d\n", - name, dai->sysclk); - - dev_dbg(dev, "%s direction = %s\n", - name, dai->clk_direction ? "OUT" : "IN"); if (dai->slots) dev_dbg(dev, "%s slots = %d\n", name, dai->slots); @@ -208,6 +202,12 @@ static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, dev_dbg(dev, "%s rx slot mask = %d\n", name, dai->rx_slot_mask); if (dai->clk) dev_dbg(dev, "%s clk %luHz\n", name, clk_get_rate(dai->clk)); + if (dai->sysclk) + dev_dbg(dev, "%s sysclk = %dHz\n", + name, dai->sysclk); + if (dai->clk || dai->sysclk) + dev_dbg(dev, "%s direction = %s\n", + name, dai->clk_direction ? "OUT" : "IN"); } static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) From 3919249e80995ed5f125f94d05fcb6171f79e732 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:52:55 +0900 Subject: [PATCH 0947/1091] ASoC: simple-card-utils: tidyup dev_dbg() to use 1 line We can use 100 char now for 1 line. This patch tidyup unreadable dev_dbg() message. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87fszwwf8o.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index bf068803eb1f..20c22bffe091 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -241,17 +241,14 @@ static inline void asoc_simple_debug_info(struct asoc_simple_priv *priv) if (link->dai_fmt) dev_dbg(dev, "dai format = %04x\n", link->dai_fmt); if (props->adata.convert_rate) - dev_dbg(dev, "convert_rate = %d\n", - props->adata.convert_rate); + dev_dbg(dev, "convert_rate = %d\n", props->adata.convert_rate); if (props->adata.convert_channels) - dev_dbg(dev, "convert_channels = %d\n", - props->adata.convert_channels); + dev_dbg(dev, "convert_channels = %d\n", props->adata.convert_channels); for_each_prop_codec_conf(props, j, cnf) if (cnf->name_prefix) dev_dbg(dev, "name prefix = %s\n", cnf->name_prefix); if (props->mclk_fs) - dev_dbg(dev, "mclk-fs = %d\n", - props->mclk_fs); + dev_dbg(dev, "mclk-fs = %d\n", props->mclk_fs); } } #else From fcfd763bef4ff7f6371790979a6ceac9c4ac425a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 12 Apr 2021 08:53:00 +0900 Subject: [PATCH 0948/1091] ASoC: simple-card-utils: tidyup asoc_simple_parse_convert() dev is not used. This patch removes it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87eefgwf8j.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 3 +-- sound/soc/generic/audio-graph-card.c | 10 +++++----- sound/soc/generic/simple-card-utils.c | 3 +-- sound/soc/generic/simple-card.c | 8 ++++---- 4 files changed, 11 insertions(+), 13 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 20c22bffe091..fac3b832d982 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -160,8 +160,7 @@ int asoc_simple_clean_reference(struct snd_soc_card *card); void asoc_simple_convert_fixup(struct asoc_simple_data *data, struct snd_pcm_hw_params *params); -void asoc_simple_parse_convert(struct device *dev, - struct device_node *np, char *prefix, +void asoc_simple_parse_convert(struct device_node *np, char *prefix, struct asoc_simple_data *data); int asoc_simple_parse_routing(struct snd_soc_card *card, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index e6b64fdbdc76..0582fe296471 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -180,11 +180,11 @@ static void graph_parse_convert(struct device *dev, struct device_node *ports = of_get_parent(port); struct device_node *node = of_graph_get_port_parent(ep); - asoc_simple_parse_convert(dev, top, NULL, adata); - asoc_simple_parse_convert(dev, node, PREFIX, adata); - asoc_simple_parse_convert(dev, ports, NULL, adata); - asoc_simple_parse_convert(dev, port, NULL, adata); - asoc_simple_parse_convert(dev, ep, NULL, adata); + asoc_simple_parse_convert(top, NULL, adata); + asoc_simple_parse_convert(node, PREFIX, adata); + asoc_simple_parse_convert(ports, NULL, adata); + asoc_simple_parse_convert(port, NULL, adata); + asoc_simple_parse_convert(ep, NULL, adata); of_node_put(port); of_node_put(ports); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index a15956c25858..e1b7b30a4c8c 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -32,8 +32,7 @@ void asoc_simple_convert_fixup(struct asoc_simple_data *data, } EXPORT_SYMBOL_GPL(asoc_simple_convert_fixup); -void asoc_simple_parse_convert(struct device *dev, - struct device_node *np, +void asoc_simple_parse_convert(struct device_node *np, char *prefix, struct asoc_simple_data *data) { diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 06b2d6a7f48d..bf5ddf1ea65f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -84,10 +84,10 @@ static void simple_parse_convert(struct device *dev, struct device_node *top = dev->of_node; struct device_node *node = of_get_parent(np); - asoc_simple_parse_convert(dev, top, PREFIX, adata); - asoc_simple_parse_convert(dev, node, PREFIX, adata); - asoc_simple_parse_convert(dev, node, NULL, adata); - asoc_simple_parse_convert(dev, np, NULL, adata); + asoc_simple_parse_convert(top, PREFIX, adata); + asoc_simple_parse_convert(node, PREFIX, adata); + asoc_simple_parse_convert(node, NULL, adata); + asoc_simple_parse_convert(np, NULL, adata); of_node_put(node); } From 462c47c2fcc26d838c82646a31d6e3e8fc01ce68 Mon Sep 17 00:00:00 2001 From: Chen Lifu Date: Fri, 9 Apr 2021 09:59:53 +0800 Subject: [PATCH 0949/1091] ASoC: sti: sti_uniperif: add missing MODULE_DEVICE_TABLE This patch adds missing MODULE_DEVICE_TABLE definition which generates correct modalias for automatic loading of this driver when it is built as an external module. Reported-by: Hulk Robot Signed-off-by: Chen Lifu Reviewed-by: Arnaud Pouliquen Link: https://lore.kernel.org/r/20210409015953.259688-1-chenlifu@huawei.com Signed-off-by: Mark Brown --- sound/soc/sti/sti_uniperif.c | 1 + 1 file changed, 1 insertion(+) diff --git a/sound/soc/sti/sti_uniperif.c b/sound/soc/sti/sti_uniperif.c index 67315d9b352d..e3561f00ed40 100644 --- a/sound/soc/sti/sti_uniperif.c +++ b/sound/soc/sti/sti_uniperif.c @@ -97,6 +97,7 @@ static const struct of_device_id snd_soc_sti_match[] = { }, {}, }; +MODULE_DEVICE_TABLE(of, snd_soc_sti_match); int sti_uniperiph_reset(struct uniperif *uni) { From 38c694e98f6a6c8dfa48f2ba6f442363ed836efb Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 11 Apr 2021 14:51:06 +0200 Subject: [PATCH 0950/1091] ASoC: cs35l35: Fix an error handling path in 'cs35l35_i2c_probe()' If 'devm_regmap_init_i2c()' fails, there is no need to goto err. We should return directly as already done by the surrounding error handling paths. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/15720439769ba94ffb65c90217392b0758b08f61.1618145369.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l35.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index 55d529aa0011..7b9f5498f8a7 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -1488,7 +1488,7 @@ static int cs35l35_i2c_probe(struct i2c_client *i2c_client, if (IS_ERR(cs35l35->regmap)) { ret = PTR_ERR(cs35l35->regmap); dev_err(dev, "regmap_init() failed: %d\n", ret); - goto err; + return ret; } for (i = 0; i < ARRAY_SIZE(cs35l35_supplies); i++) From cdf20c3ef0e90b962e62ae7d835d7f46333285bc Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 11 Apr 2021 14:57:13 +0200 Subject: [PATCH 0951/1091] ASoC: cs35l36: Fix an error handling path in 'cs35l36_i2c_probe()' If 'devm_regmap_init_i2c()' fails, there is no need to goto err. We should return directly as already done by the surrounding error handling paths. Signed-off-by: Christophe JAILLET Link: https://lore.kernel.org/r/9fec48e75bc1d3c92626e6f6aca2344bda223379.1618145790.git.christophe.jaillet@wanadoo.fr Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l36.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/cs35l36.c b/sound/soc/codecs/cs35l36.c index 4451ca9f4916..a038bcec2d17 100644 --- a/sound/soc/codecs/cs35l36.c +++ b/sound/soc/codecs/cs35l36.c @@ -1721,7 +1721,7 @@ static int cs35l36_i2c_probe(struct i2c_client *i2c_client, if (IS_ERR(cs35l36->regmap)) { ret = PTR_ERR(cs35l36->regmap); dev_err(dev, "regmap_init() failed: %d\n", ret); - goto err; + return ret; } cs35l36->num_supplies = ARRAY_SIZE(cs35l36_supplies); From 6998a8800d73116187aad542391ce3b2dd0f9e30 Mon Sep 17 00:00:00 2001 From: "Rafael J. Wysocki" Date: Tue, 13 Apr 2021 16:01:00 +0200 Subject: [PATCH 0952/1091] ACPI: x86: Call acpi_boot_table_init() after acpi_table_upgrade() Commit 1a1c130ab757 ("ACPI: tables: x86: Reserve memory occupied by ACPI tables") attempted to address an issue with reserving the memory occupied by ACPI tables, but it broke the initrd-based table override mechanism relied on by multiple users. To restore the initrd-based ACPI table override functionality, move the acpi_boot_table_init() invocation in setup_arch() on x86 after the acpi_table_upgrade() one. Fixes: 1a1c130ab757 ("ACPI: tables: x86: Reserve memory occupied by ACPI tables") Reported-by: Hans de Goede Tested-by: Hans de Goede Signed-off-by: Rafael J. Wysocki --- arch/x86/kernel/setup.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c index 5ecd69a48393..ccab6cf91283 100644 --- a/arch/x86/kernel/setup.c +++ b/arch/x86/kernel/setup.c @@ -1045,9 +1045,6 @@ void __init setup_arch(char **cmdline_p) cleanup_highmap(); - /* Look for ACPI tables and reserve memory occupied by them. */ - acpi_boot_table_init(); - memblock_set_current_limit(ISA_END_ADDRESS); e820__memblock_setup(); @@ -1132,6 +1129,8 @@ void __init setup_arch(char **cmdline_p) reserve_initrd(); acpi_table_upgrade(); + /* Look for ACPI tables and reserve memory occupied by them. */ + acpi_boot_table_init(); vsmp_init(); From 909290786ea335366e21d7f1ed5812b90f2f0a92 Mon Sep 17 00:00:00 2001 From: "Christian A. Ehrhardt" Date: Mon, 12 Apr 2021 23:41:24 +0200 Subject: [PATCH 0953/1091] vfio/pci: Add missing range check in vfio_pci_mmap When mmaping an extra device region verify that the region index derived from the mmap offset is valid. Fixes: a15b1883fee1 ("vfio_pci: Allow mapping extra regions") Cc: stable@vger.kernel.org Signed-off-by: Christian A. Ehrhardt Message-Id: <20210412214124.GA241759@lisa.in-ulm.de> Reviewed-by: David Gibson Reviewed-by: Cornelia Huck Signed-off-by: Alex Williamson --- drivers/vfio/pci/vfio_pci.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 65e7e6b44578..5023e23db3bc 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -1656,6 +1656,8 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma) index = vma->vm_pgoff >> (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT); + if (index >= VFIO_PCI_NUM_REGIONS + vdev->num_regions) + return -EINVAL; if (vma->vm_end < vma->vm_start) return -EINVAL; if ((vma->vm_flags & VM_SHARED) == 0) @@ -1664,7 +1666,7 @@ static int vfio_pci_mmap(void *device_data, struct vm_area_struct *vma) int regnum = index - VFIO_PCI_NUM_REGIONS; struct vfio_pci_region *region = vdev->region + regnum; - if (region && region->ops && region->ops->mmap && + if (region->ops && region->ops->mmap && (region->flags & VFIO_REGION_INFO_FLAG_MMAP)) return region->ops->mmap(vdev, region, vma); return -EINVAL; From 8db403b9631331ef1d5e302cdf353c48849ca9d5 Mon Sep 17 00:00:00 2001 From: Christophe JAILLET Date: Sun, 11 Apr 2021 12:21:54 +0200 Subject: [PATCH 0954/1091] tracing/dynevent: Fix a memory leak in an error handling path We must free 'argv' before returning, as already done in all the other paths of this function. Link: https://lkml.kernel.org/r/21e3594ccd7fc88c5c162c98450409190f304327.1618136448.git.christophe.jaillet@wanadoo.fr Fixes: d262271d0483 ("tracing/dynevent: Delegate parsing to create function") Acked-by: Masami Hiramatsu Signed-off-by: Christophe JAILLET Signed-off-by: Steven Rostedt (VMware) --- kernel/trace/trace_dynevent.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/kernel/trace/trace_dynevent.c b/kernel/trace/trace_dynevent.c index dc971a68dda4..e57cc0870892 100644 --- a/kernel/trace/trace_dynevent.c +++ b/kernel/trace/trace_dynevent.c @@ -63,8 +63,10 @@ int dyn_event_release(const char *raw_command, struct dyn_event_operations *type event = p + 1; *p = '\0'; } - if (event[0] == '\0') - return -EINVAL; + if (event[0] == '\0') { + ret = -EINVAL; + goto out; + } mutex_lock(&event_mutex); for_each_dyn_event_safe(pos, n) { From 31166efb1cee348eb6314e9c0095d84cbeb66b9d Mon Sep 17 00:00:00 2001 From: Alexander Duyck Date: Mon, 8 Mar 2021 12:41:56 -0800 Subject: [PATCH 0955/1091] ixgbe: Fix NULL pointer dereference in ethtool loopback test MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The ixgbe driver currently generates a NULL pointer dereference when performing the ethtool loopback test. This is due to the fact that there isn't a q_vector associated with the test ring when it is setup as interrupts are not normally added to the test rings. To address this I have added code that will check for a q_vector before returning a napi_id value. If a q_vector is not present it will return a value of 0. Fixes: b02e5a0ebb17 ("xsk: Propagate napi_id to XDP socket Rx path") Signed-off-by: Alexander Duyck Acked-by: Björn Töpel Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 03d9aad516d4..45d2c8f37c01 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6536,6 +6536,13 @@ err_setup_tx: return err; } +static int ixgbe_rx_napi_id(struct ixgbe_ring *rx_ring) +{ + struct ixgbe_q_vector *q_vector = rx_ring->q_vector; + + return q_vector ? q_vector->napi.napi_id : 0; +} + /** * ixgbe_setup_rx_resources - allocate Rx resources (Descriptors) * @adapter: pointer to ixgbe_adapter @@ -6583,7 +6590,7 @@ int ixgbe_setup_rx_resources(struct ixgbe_adapter *adapter, /* XDP RX-queue info */ if (xdp_rxq_info_reg(&rx_ring->xdp_rxq, adapter->netdev, - rx_ring->queue_index, rx_ring->q_vector->napi.napi_id) < 0) + rx_ring->queue_index, ixgbe_rx_napi_id(rx_ring)) < 0) goto err; rx_ring->xdp_prog = adapter->xdp_prog; From debb9df311582c83fe369baa35fa4b92e8a9c58a Mon Sep 17 00:00:00 2001 From: Yongxin Liu Date: Mon, 22 Mar 2021 15:14:48 +0800 Subject: [PATCH 0956/1091] ixgbe: fix unbalanced device enable/disable in suspend/resume pci_disable_device() called in __ixgbe_shutdown() decreases dev->enable_cnt by 1. pci_enable_device_mem() which increases dev->enable_cnt by 1, was removed from ixgbe_resume() in commit 6f82b2558735 ("ixgbe: use generic power management"). This caused unbalanced increase/decrease. So add pci_enable_device_mem() back. Fix the following call trace. ixgbe 0000:17:00.1: disabling already-disabled device Call Trace: __ixgbe_shutdown+0x10a/0x1e0 [ixgbe] ixgbe_suspend+0x32/0x70 [ixgbe] pci_pm_suspend+0x87/0x160 ? pci_pm_freeze+0xd0/0xd0 dpm_run_callback+0x42/0x170 __device_suspend+0x114/0x460 async_suspend+0x1f/0xa0 async_run_entry_fn+0x3c/0xf0 process_one_work+0x1dd/0x410 worker_thread+0x34/0x3f0 ? cancel_delayed_work+0x90/0x90 kthread+0x14c/0x170 ? kthread_park+0x90/0x90 ret_from_fork+0x1f/0x30 Fixes: 6f82b2558735 ("ixgbe: use generic power management") Signed-off-by: Yongxin Liu Tested-by: Dave Switzer Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ixgbe/ixgbe_main.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c index 45d2c8f37c01..cffb95f8f632 100644 --- a/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c +++ b/drivers/net/ethernet/intel/ixgbe/ixgbe_main.c @@ -6899,6 +6899,11 @@ static int __maybe_unused ixgbe_resume(struct device *dev_d) adapter->hw.hw_addr = adapter->io_addr; + err = pci_enable_device_mem(pdev); + if (err) { + e_dev_err("Cannot enable PCI device from suspend\n"); + return err; + } smp_mb__before_atomic(); clear_bit(__IXGBE_DISABLED, &adapter->state); pci_set_master(pdev); From ef963ae427aa4669905e0a96b3bd9d44dc85db32 Mon Sep 17 00:00:00 2001 From: Colin Ian King Date: Wed, 31 Mar 2021 15:46:28 +0100 Subject: [PATCH 0957/1091] ice: Fix potential infinite loop when using u8 loop counter A for-loop is using a u8 loop counter that is being compared to a u32 cmp_dcbcfg->numapp to check for the end of the loop. If cmp_dcbcfg->numapp is larger than 255 then the counter j will wrap around to zero and hence an infinite loop occurs. Fix this by making counter j the same type as cmp_dcbcfg->numapp. Addresses-Coverity: ("Infinite loop") Fixes: aeac8ce864d9 ("ice: Recognize 860 as iSCSI port in CEE mode") Signed-off-by: Colin Ian King Tested-by: Tony Brelinski Signed-off-by: Tony Nguyen --- drivers/net/ethernet/intel/ice/ice_dcb.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_dcb.c b/drivers/net/ethernet/intel/ice/ice_dcb.c index 211ac6f907ad..28e834a128c0 100644 --- a/drivers/net/ethernet/intel/ice/ice_dcb.c +++ b/drivers/net/ethernet/intel/ice/ice_dcb.c @@ -747,8 +747,8 @@ ice_cee_to_dcb_cfg(struct ice_aqc_get_cee_dcb_cfg_resp *cee_cfg, struct ice_port_info *pi) { u32 status, tlv_status = le32_to_cpu(cee_cfg->tlv_status); - u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift; - u8 i, j, err, sync, oper, app_index, ice_app_sel_type; + u32 ice_aqc_cee_status_mask, ice_aqc_cee_status_shift, j; + u8 i, err, sync, oper, app_index, ice_app_sel_type; u16 app_prio = le16_to_cpu(cee_cfg->oper_app_prio); u16 ice_aqc_cee_app_mask, ice_aqc_cee_app_shift; struct ice_dcbx_cfg *cmp_dcbcfg, *dcbcfg; From 610f8c0fc8d46e0933955ce13af3d64484a4630a Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Mon, 12 Apr 2021 20:41:16 +0300 Subject: [PATCH 0958/1091] net: sit: Unregister catch-all devices A sit interface created without a local or a remote address is linked into the `sit_net::tunnels_wc` list of its original namespace. When deleting a network namespace, delete the devices that have been moved. The following script triggers a null pointer dereference if devices linked in a deleted `sit_net` remain: for i in `seq 1 30`; do ip netns add ns-test ip netns exec ns-test ip link add dev veth0 type veth peer veth1 ip netns exec ns-test ip link add dev sit$i type sit dev veth0 ip netns exec ns-test ip link set dev sit$i netns $$ ip netns del ns-test done for i in `seq 1 30`; do ip link del dev sit$i done Fixes: 5e6700b3bf98f ("sit: add support of x-netns") Signed-off-by: Hristo Venev Signed-off-by: David S. Miller --- net/ipv6/sit.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv6/sit.c b/net/ipv6/sit.c index 63ccd9f2dccc..9fdccf0718b5 100644 --- a/net/ipv6/sit.c +++ b/net/ipv6/sit.c @@ -1867,9 +1867,9 @@ static void __net_exit sit_destroy_tunnels(struct net *net, if (dev->rtnl_link_ops == &sit_link_ops) unregister_netdevice_queue(dev, head); - for (prio = 1; prio < 4; prio++) { + for (prio = 0; prio < 4; prio++) { int h; - for (h = 0; h < IP6_SIT_HASH_SIZE; h++) { + for (h = 0; h < (prio ? IP6_SIT_HASH_SIZE : 1); h++) { struct ip_tunnel *t; t = rtnl_dereference(sitn->tunnels[prio][h]); From 941ea91e87a6e879ed82dad4949f6234f2702bec Mon Sep 17 00:00:00 2001 From: Hristo Venev Date: Mon, 12 Apr 2021 20:41:17 +0300 Subject: [PATCH 0959/1091] net: ip6_tunnel: Unregister catch-all devices Similarly to the sit case, we need to remove the tunnels with no addresses that have been moved to another network namespace. Fixes: 0bd8762824e73 ("ip6tnl: add x-netns support") Signed-off-by: Hristo Venev Signed-off-by: David S. Miller --- net/ipv6/ip6_tunnel.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/net/ipv6/ip6_tunnel.c b/net/ipv6/ip6_tunnel.c index 3fa0eca5a06f..42fe7db6bbb3 100644 --- a/net/ipv6/ip6_tunnel.c +++ b/net/ipv6/ip6_tunnel.c @@ -2244,6 +2244,16 @@ static void __net_exit ip6_tnl_destroy_tunnels(struct net *net, struct list_head t = rtnl_dereference(t->next); } } + + t = rtnl_dereference(ip6n->tnls_wc[0]); + while (t) { + /* If dev is in the same netns, it has already + * been added to the list by the previous loop. + */ + if (!net_eq(dev_net(t->dev), net)) + unregister_netdevice_queue(t->dev, list); + t = rtnl_dereference(t->next); + } } static int __net_init ip6_tnl_init_net(struct net *net) From 97684f0970f6e112926de631fdd98d9693c7e5c1 Mon Sep 17 00:00:00 2001 From: Jonathon Reinhart Date: Tue, 13 Apr 2021 03:08:48 -0400 Subject: [PATCH 0960/1091] net: Make tcp_allowed_congestion_control readonly in non-init netns Currently, tcp_allowed_congestion_control is global and writable; writing to it in any net namespace will leak into all other net namespaces. tcp_available_congestion_control and tcp_allowed_congestion_control are the only sysctls in ipv4_net_table (the per-netns sysctl table) with a NULL data pointer; their handlers (proc_tcp_available_congestion_control and proc_allowed_congestion_control) have no other way of referencing a struct net. Thus, they operate globally. Because ipv4_net_table does not use designated initializers, there is no easy way to fix up this one "bad" table entry. However, the data pointer updating logic shouldn't be applied to NULL pointers anyway, so we instead force these entries to be read-only. These sysctls used to exist in ipv4_table (init-net only), but they were moved to the per-net ipv4_net_table, presumably without realizing that tcp_allowed_congestion_control was writable and thus introduced a leak. Because the intent of that commit was only to know (i.e. read) "which congestion algorithms are available or allowed", this read-only solution should be sufficient. The logic added in recent commit 31c4d2f160eb: ("net: Ensure net namespace isolation of sysctls") does not and cannot check for NULL data pointers, because other table entries (e.g. /proc/sys/net/netfilter/nf_log/) have .data=NULL but use other methods (.extra2) to access the struct net. Fixes: 9cb8e048e5d9 ("net/ipv4/sysctl: show tcp_{allowed, available}_congestion_control in non-initial netns") Signed-off-by: Jonathon Reinhart Signed-off-by: David S. Miller --- net/ipv4/sysctl_net_ipv4.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/net/ipv4/sysctl_net_ipv4.c b/net/ipv4/sysctl_net_ipv4.c index f55095d3ed16..60465f077497 100644 --- a/net/ipv4/sysctl_net_ipv4.c +++ b/net/ipv4/sysctl_net_ipv4.c @@ -1378,9 +1378,19 @@ static __net_init int ipv4_sysctl_init_net(struct net *net) if (!table) goto err_alloc; - /* Update the variables to point into the current struct net */ - for (i = 0; i < ARRAY_SIZE(ipv4_net_table) - 1; i++) - table[i].data += (void *)net - (void *)&init_net; + for (i = 0; i < ARRAY_SIZE(ipv4_net_table) - 1; i++) { + if (table[i].data) { + /* Update the variables to point into + * the current struct net + */ + table[i].data += (void *)net - (void *)&init_net; + } else { + /* Entries without data pointer are global; + * Make them read-only in non-init_net ns + */ + table[i].mode &= ~0222; + } + } } net->ipv4.ipv4_hdr = register_net_sysctl(net, "net/ipv4", table); From ca09bf7bb109a37a7ff05f230bb3fa3627e6625f Mon Sep 17 00:00:00 2001 From: Lijun Pan Date: Tue, 13 Apr 2021 03:33:25 -0500 Subject: [PATCH 0961/1091] ibmvnic: correctly use dev_consume/free_skb_irq It is more correct to use dev_kfree_skb_irq when packets are dropped, and to use dev_consume_skb_irq when packets are consumed. Fixes: 0d973388185d ("ibmvnic: Introduce xmit_more support using batched subCRQ hcalls") Suggested-by: Thomas Falcon Signed-off-by: Lijun Pan Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 9c6438d3b3a5..110a0d0eaabb 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -3204,9 +3204,6 @@ restart_loop: next = ibmvnic_next_scrq(adapter, scrq); for (i = 0; i < next->tx_comp.num_comps; i++) { - if (next->tx_comp.rcs[i]) - dev_err(dev, "tx error %x\n", - next->tx_comp.rcs[i]); index = be32_to_cpu(next->tx_comp.correlators[i]); if (index & IBMVNIC_TSO_POOL_MASK) { tx_pool = &adapter->tso_pool[pool]; @@ -3220,7 +3217,13 @@ restart_loop: num_entries += txbuff->num_entries; if (txbuff->skb) { total_bytes += txbuff->skb->len; - dev_consume_skb_irq(txbuff->skb); + if (next->tx_comp.rcs[i]) { + dev_err(dev, "tx error %x\n", + next->tx_comp.rcs[i]); + dev_kfree_skb_irq(txbuff->skb); + } else { + dev_consume_skb_irq(txbuff->skb); + } txbuff->skb = NULL; } else { netdev_warn(adapter->netdev, From b166a20b07382b8bc1dcee2a448715c9c2c81b5b Mon Sep 17 00:00:00 2001 From: Or Cohen Date: Tue, 13 Apr 2021 21:10:31 +0300 Subject: [PATCH 0962/1091] net/sctp: fix race condition in sctp_destroy_sock If sctp_destroy_sock is called without sock_net(sk)->sctp.addr_wq_lock held and sp->do_auto_asconf is true, then an element is removed from the auto_asconf_splist without any proper locking. This can happen in the following functions: 1. In sctp_accept, if sctp_sock_migrate fails. 2. In inet_create or inet6_create, if there is a bpf program attached to BPF_CGROUP_INET_SOCK_CREATE which denies creation of the sctp socket. The bug is fixed by acquiring addr_wq_lock in sctp_destroy_sock instead of sctp_close. This addresses CVE-2021-23133. Reported-by: Or Cohen Reviewed-by: Xin Long Fixes: 610236587600 ("bpf: Add new cgroup attach type to enable sock modifications") Signed-off-by: Or Cohen Acked-by: Marcelo Ricardo Leitner Signed-off-by: David S. Miller --- net/sctp/socket.c | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/net/sctp/socket.c b/net/sctp/socket.c index a710917c5ac7..b9b3d899a611 100644 --- a/net/sctp/socket.c +++ b/net/sctp/socket.c @@ -1520,11 +1520,9 @@ static void sctp_close(struct sock *sk, long timeout) /* Supposedly, no process has access to the socket, but * the net layers still may. - * Also, sctp_destroy_sock() needs to be called with addr_wq_lock - * held and that should be grabbed before socket lock. */ - spin_lock_bh(&net->sctp.addr_wq_lock); - bh_lock_sock_nested(sk); + local_bh_disable(); + bh_lock_sock(sk); /* Hold the sock, since sk_common_release() will put sock_put() * and we have just a little more cleanup. @@ -1533,7 +1531,7 @@ static void sctp_close(struct sock *sk, long timeout) sk_common_release(sk); bh_unlock_sock(sk); - spin_unlock_bh(&net->sctp.addr_wq_lock); + local_bh_enable(); sock_put(sk); @@ -4993,9 +4991,6 @@ static int sctp_init_sock(struct sock *sk) sk_sockets_allocated_inc(sk); sock_prot_inuse_add(net, sk->sk_prot, 1); - /* Nothing can fail after this block, otherwise - * sctp_destroy_sock() will be called without addr_wq_lock held - */ if (net->sctp.default_auto_asconf) { spin_lock(&sock_net(sk)->sctp.addr_wq_lock); list_add_tail(&sp->auto_asconf_list, @@ -5030,7 +5025,9 @@ static void sctp_destroy_sock(struct sock *sk) if (sp->do_auto_asconf) { sp->do_auto_asconf = 0; + spin_lock_bh(&sock_net(sk)->sctp.addr_wq_lock); list_del(&sp->auto_asconf_list); + spin_unlock_bh(&sock_net(sk)->sctp.addr_wq_lock); } sctp_endpoint_free(sp->ep); local_bh_disable(); From 38ec4944b593fd90c5ef42aaaa53e66ae5769d04 Mon Sep 17 00:00:00 2001 From: Eric Dumazet Date: Tue, 13 Apr 2021 05:41:35 -0700 Subject: [PATCH 0963/1091] gro: ensure frag0 meets IP header alignment After commit 0f6925b3e8da ("virtio_net: Do not pull payload in skb->head") Guenter Roeck reported one failure in his tests using sh architecture. After much debugging, we have been able to spot silent unaligned accesses in inet_gro_receive() The issue at hand is that upper networking stacks assume their header is word-aligned. Low level drivers are supposed to reserve NET_IP_ALIGN bytes before the Ethernet header to make that happen. This patch hardens skb_gro_reset_offset() to not allow frag0 fast-path if the fragment is not properly aligned. Some arches like x86, arm64 and powerpc do not care and define NET_IP_ALIGN as 0, this extra check will be a NOP for them. Note that if frag0 is not used, GRO will call pskb_may_pull() as many times as needed to pull network and transport headers. Fixes: 0f6925b3e8da ("virtio_net: Do not pull payload in skb->head") Fixes: 78a478d0efd9 ("gro: Inline skb_gro_header and cache frag0 virtual address") Signed-off-by: Eric Dumazet Reported-by: Guenter Roeck Cc: Xuan Zhuo Cc: "Michael S. Tsirkin" Cc: Jason Wang Acked-by: Michael S. Tsirkin Tested-by: Guenter Roeck Signed-off-by: David S. Miller --- net/core/dev.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/core/dev.c b/net/core/dev.c index af8c1ea040b9..1f79b9aa9a3f 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5924,7 +5924,8 @@ static void skb_gro_reset_offset(struct sk_buff *skb) NAPI_GRO_CB(skb)->frag0_len = 0; if (!skb_headlen(skb) && pinfo->nr_frags && - !PageHighMem(skb_frag_page(frag0))) { + !PageHighMem(skb_frag_page(frag0)) && + (!NET_IP_ALIGN || !(skb_frag_off(frag0) & 3))) { NAPI_GRO_CB(skb)->frag0 = skb_frag_address(frag0); NAPI_GRO_CB(skb)->frag0_len = min_t(unsigned int, skb_frag_size(frag0), From 04c4f2ee3f68c9a4bf1653d15f1a9a435ae33f7a Mon Sep 17 00:00:00 2001 From: Reiji Watanabe Date: Tue, 13 Apr 2021 15:47:40 +0000 Subject: [PATCH 0964/1091] KVM: VMX: Don't use vcpu->run->internal.ndata as an array index __vmx_handle_exit() uses vcpu->run->internal.ndata as an index for an array access. Since vcpu->run is (can be) mapped to a user address space with a writer permission, the 'ndata' could be updated by the user process at anytime (the user process can set it to outside the bounds of the array). So, it is not safe that __vmx_handle_exit() uses the 'ndata' that way. Fixes: 1aa561b1a4c0 ("kvm: x86: Add "last CPU" to some KVM_EXIT information") Signed-off-by: Reiji Watanabe Reviewed-by: Jim Mattson Message-Id: <20210413154739.490299-1-reijiw@google.com> Cc: stable@vger.kernel.org Signed-off-by: Paolo Bonzini --- arch/x86/kvm/vmx/vmx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c index 32cf8287d4a7..29b40e092d13 100644 --- a/arch/x86/kvm/vmx/vmx.c +++ b/arch/x86/kvm/vmx/vmx.c @@ -6027,19 +6027,19 @@ static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath) exit_reason.basic != EXIT_REASON_PML_FULL && exit_reason.basic != EXIT_REASON_APIC_ACCESS && exit_reason.basic != EXIT_REASON_TASK_SWITCH)) { + int ndata = 3; + vcpu->run->exit_reason = KVM_EXIT_INTERNAL_ERROR; vcpu->run->internal.suberror = KVM_INTERNAL_ERROR_DELIVERY_EV; - vcpu->run->internal.ndata = 3; vcpu->run->internal.data[0] = vectoring_info; vcpu->run->internal.data[1] = exit_reason.full; vcpu->run->internal.data[2] = vcpu->arch.exit_qualification; if (exit_reason.basic == EXIT_REASON_EPT_MISCONFIG) { - vcpu->run->internal.ndata++; - vcpu->run->internal.data[3] = + vcpu->run->internal.data[ndata++] = vmcs_read64(GUEST_PHYSICAL_ADDRESS); } - vcpu->run->internal.data[vcpu->run->internal.ndata++] = - vcpu->arch.last_vmentry_cpu; + vcpu->run->internal.data[ndata++] = vcpu->arch.last_vmentry_cpu; + vcpu->run->internal.ndata = ndata; return 0; } From 2afeec08ab5c86ae21952151f726bfe184f6b23d Mon Sep 17 00:00:00 2001 From: Michael Brown Date: Tue, 13 Apr 2021 16:25:12 +0100 Subject: [PATCH 0965/1091] xen-netback: Check for hotplug-status existence before watching The logic in connect() is currently written with the assumption that xenbus_watch_pathfmt() will return an error for a node that does not exist. This assumption is incorrect: xenstore does allow a watch to be registered for a nonexistent node (and will send notifications should the node be subsequently created). As of commit 1f2565780 ("xen-netback: remove 'hotplug-status' once it has served its purpose"), this leads to a failure when a domU transitions into XenbusStateConnected more than once. On the first domU transition into Connected state, the "hotplug-status" node will be deleted by the hotplug_status_changed() callback in dom0. On the second or subsequent domU transition into Connected state, the hotplug_status_changed() callback will therefore never be invoked, and so the backend will remain stuck in InitWait. This failure prevents scenarios such as reloading the xen-netfront module within a domU, or booting a domU via iPXE. There is unfortunately no way for the domU to work around this dom0 bug. Fix by explicitly checking for existence of the "hotplug-status" node, thereby creating the behaviour that was previously assumed to exist. Signed-off-by: Michael Brown Reviewed-by: Paul Durrant Signed-off-by: David S. Miller --- drivers/net/xen-netback/xenbus.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/drivers/net/xen-netback/xenbus.c b/drivers/net/xen-netback/xenbus.c index a5439c130130..d24b7a7993aa 100644 --- a/drivers/net/xen-netback/xenbus.c +++ b/drivers/net/xen-netback/xenbus.c @@ -824,11 +824,15 @@ static void connect(struct backend_info *be) xenvif_carrier_on(be->vif); unregister_hotplug_status_watch(be); - err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, NULL, - hotplug_status_changed, - "%s/%s", dev->nodename, "hotplug-status"); - if (!err) + if (xenbus_exists(XBT_NIL, dev->nodename, "hotplug-status")) { + err = xenbus_watch_pathfmt(dev, &be->hotplug_status_watch, + NULL, hotplug_status_changed, + "%s/%s", dev->nodename, + "hotplug-status"); + if (err) + goto err; be->have_hotplug_status_watch = 1; + } netif_tx_wake_all_queues(be->vif->dev); From a122a116fc6d8fcf2f202dcd185173a54268f239 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Apr 2021 13:28:38 +0900 Subject: [PATCH 0966/1091] ASoC: rsnd: call rsnd_ssi_master_clk_start() from rsnd_ssi_init() Current rsnd needs to call .prepare (P) for clock settings, .trigger for playback start (S) and stop (E). It should be called as below from SSI point of view. P -> S -> E -> P -> S -> E -> ... But, if you used MIXer, below case might happen (2) 1: P -> S ---> E -> ... 2: P ----> S -> ... (1) (3) P(1) setups clock, but E(2) resets it. and starts playback (3). In such case, it will reports "SSI parent/child should use same rate". rsnd_ssi_master_clk_start() which is the main function at (P) was called from rsnd_ssi_init() (= S) before, but was moved by below patch to rsnd_soc_dai_prepare() (= P) to avoid using clk_get_rate() which shouldn't be used under atomic context. commit 4d230d1271064 ("ASoC: rsnd: fixup not to call clk_get/set under non-atomic") Because of above patch, rsnd_ssi_master_clk_start() is now called at (P) which is for non atomic context. But (P) is assuming that spin lock is *not* used. One issue now is rsnd_ssi_master_clk_start() is checking ssi->xxx which should be protected by spin lock. After above patch, adg.c had below patch for other reasons. commit 06e8f5c842f2d ("ASoC: rsnd: don't call clk_get_rate() under atomic context") clk_get_rate() is used at probe() timing by this patch. In other words, rsnd_ssi_master_clk_start() is no longer using clk_get_rate() any more. This means we can call it from rsnd_ssi_init() (= S) again which is protected by spin lock. This patch re-move it to under spin lock, and solves 1. checking ssi->xxx without spin lock issue. 2. clk setting / device start / device stop race condition. Reported-by: Linh Phung T. Y. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/875z0x1jt5.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index d071cec25f71..048d53566127 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -506,10 +506,15 @@ static int rsnd_ssi_init(struct rsnd_mod *mod, struct rsnd_priv *priv) { struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); + int ret; if (!rsnd_ssi_is_run_mods(mod, io)) return 0; + ret = rsnd_ssi_master_clk_start(mod, io); + if (ret < 0) + return ret; + ssi->usrcnt++; rsnd_mod_power_on(mod); @@ -1060,13 +1065,6 @@ static int rsnd_ssi_pio_pointer(struct rsnd_mod *mod, return 0; } -static int rsnd_ssi_prepare(struct rsnd_mod *mod, - struct rsnd_dai_stream *io, - struct rsnd_priv *priv) -{ - return rsnd_ssi_master_clk_start(mod, io); -} - static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .name = SSI_NAME, .probe = rsnd_ssi_common_probe, @@ -1079,7 +1077,6 @@ static struct rsnd_mod_ops rsnd_ssi_pio_ops = { .pointer = rsnd_ssi_pio_pointer, .pcm_new = rsnd_ssi_pcm_new, .hw_params = rsnd_ssi_hw_params, - .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, }; @@ -1166,7 +1163,6 @@ static struct rsnd_mod_ops rsnd_ssi_dma_ops = { .pcm_new = rsnd_ssi_pcm_new, .fallback = rsnd_ssi_fallback, .hw_params = rsnd_ssi_hw_params, - .prepare = rsnd_ssi_prepare, .get_status = rsnd_ssi_get_status, }; From a4856e15e58b54977f1c0c0299309ad4d1f13365 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Apr 2021 13:28:47 +0900 Subject: [PATCH 0967/1091] ASoC: rsnd: check all BUSIF status when error commit 66c705d07d784 ("SoC: rsnd: add interrupt support for SSI BUSIF buffer") adds __rsnd_ssi_interrupt() checks for BUSIF status, but is using "break" at for loop. This means it is not checking all status. Let's check all BUSIF status. Fixes: commit 66c705d07d784 ("SoC: rsnd: add interrupt support for SSI BUSIF buffer") Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/874kgh1jsw.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 048d53566127..9a3310393989 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -797,7 +797,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, SSI_SYS_STATUS(i * 2), 0xf << (id * 4)); stop = true; - break; } } break; @@ -815,7 +814,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << 4); stop = true; - break; } } break; From 691b379cbe348fbead33e49d1c1d0f045a2e3446 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Apr 2021 13:28:55 +0900 Subject: [PATCH 0968/1091] ASoC: rsnd: add rsnd_ssi_busif_err_status_clear() Current ssi.c clears BUSIF error status at __rsnd_ssi_interrupt(), but its code is verbose. This patch off-load it to rsnd_ssi_busif_err_status_clear(). Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8735w11jso.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 97 ++++++++++++++++++++++------------------- 1 file changed, 51 insertions(+), 46 deletions(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 9a3310393989..4af024917f03 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -359,6 +359,55 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, rsnd_adg_ssi_clk_stop(mod); } +static bool rsnd_ssi_busif_err_status_clear(struct rsnd_mod *mod) +{ + struct rsnd_priv *priv = rsnd_mod_to_priv(mod); + struct device *dev = rsnd_priv_to_dev(priv); + u32 status; + bool stop = false; + int id = rsnd_mod_id(mod); + int i; + + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + for (i = 0; i < 4; i++) { + status = rsnd_mod_read(mod, SSI_SYS_STATUS(i * 2)); + status &= 0xf << (id * 4); + + if (status) { + rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n", + rsnd_mod_name(mod), status); + rsnd_mod_write(mod, + SSI_SYS_STATUS(i * 2), + 0xf << (id * 4)); + stop = true; + } + } + break; + case 9: + for (i = 0; i < 4; i++) { + status = rsnd_mod_read(mod, SSI_SYS_STATUS((i * 2) + 1)); + status &= 0xf << 4; + + if (status) { + rsnd_dbg_irq_status(dev, "%s err status : 0x%08x\n", + rsnd_mod_name(mod), status); + rsnd_mod_write(mod, + SSI_SYS_STATUS((i * 2) + 1), + 0xf << 4); + stop = true; + } + } + break; + } + + return stop; +} + static void rsnd_ssi_config_init(struct rsnd_mod *mod, struct rsnd_dai_stream *io) { @@ -748,8 +797,6 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, u32 status; bool elapsed = false; bool stop = false; - int id = rsnd_mod_id(mod); - int i; int is_tdm, is_tdm_split; is_tdm = rsnd_runtime_is_tdm(io); @@ -775,50 +822,8 @@ static void __rsnd_ssi_interrupt(struct rsnd_mod *mod, stop = true; } - status = 0; - - if (is_tdm || is_tdm_split) { - switch (id) { - case 0: - case 1: - case 2: - case 3: - case 4: - for (i = 0; i < 4; i++) { - status = rsnd_mod_read(mod, - SSI_SYS_STATUS(i * 2)); - status &= 0xf << (id * 4); - - if (status) { - rsnd_dbg_irq_status(dev, - "%s err status : 0x%08x\n", - rsnd_mod_name(mod), status); - rsnd_mod_write(mod, - SSI_SYS_STATUS(i * 2), - 0xf << (id * 4)); - stop = true; - } - } - break; - case 9: - for (i = 0; i < 4; i++) { - status = rsnd_mod_read(mod, - SSI_SYS_STATUS((i * 2) + 1)); - status &= 0xf << 4; - - if (status) { - rsnd_dbg_irq_status(dev, - "%s err status : 0x%08x\n", - rsnd_mod_name(mod), status); - rsnd_mod_write(mod, - SSI_SYS_STATUS((i * 2) + 1), - 0xf << 4); - stop = true; - } - } - break; - } - } + if (is_tdm || is_tdm_split) + stop |= rsnd_ssi_busif_err_status_clear(mod); rsnd_ssi_status_clear(mod); rsnd_ssi_interrupt_out: From 15c57ce07ce207069f1cd57ec117b11871f3afa6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Apr 2021 13:29:08 +0900 Subject: [PATCH 0969/1091] ASoC: rsnd: add rsnd_ssi_busif_err_irq_enable/disable() Current ssi.c has duplicated code to control BUSIF over/under run interrupt. This patch adds new rsnd_ssi_busif_err_irq_enable/disable() and share the code. Signed-off-by: Kuninori Morimoto Cc: Yongbo Zhang Cc: Chen Li Link: https://lore.kernel.org/r/871rbl1jsb.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/ssi.c | 112 ++++++++++++++++------------------------ 1 file changed, 45 insertions(+), 67 deletions(-) diff --git a/sound/soc/sh/rcar/ssi.c b/sound/soc/sh/rcar/ssi.c index 4af024917f03..e29482c26d6a 100644 --- a/sound/soc/sh/rcar/ssi.c +++ b/sound/soc/sh/rcar/ssi.c @@ -359,6 +359,47 @@ static void rsnd_ssi_master_clk_stop(struct rsnd_mod *mod, rsnd_adg_ssi_clk_stop(mod); } +/* enable busif buffer over/under run interrupt. */ +#define rsnd_ssi_busif_err_irq_enable(mod) rsnd_ssi_busif_err_irq_ctrl(mod, 1) +#define rsnd_ssi_busif_err_irq_disable(mod) rsnd_ssi_busif_err_irq_ctrl(mod, 0) +static void rsnd_ssi_busif_err_irq_ctrl(struct rsnd_mod *mod, int enable) +{ + u32 sys_int_enable = 0; + int id = rsnd_mod_id(mod); + int i; + + switch (id) { + case 0: + case 1: + case 2: + case 3: + case 4: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, SSI_SYS_INT_ENABLE(i * 2)); + if (enable) + sys_int_enable |= 0xf << (id * 4); + else + sys_int_enable &= ~(0xf << (id * 4)); + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE(i * 2), + sys_int_enable); + } + break; + case 9: + for (i = 0; i < 4; i++) { + sys_int_enable = rsnd_mod_read(mod, SSI_SYS_INT_ENABLE((i * 2) + 1)); + if (enable) + sys_int_enable |= 0xf << 4; + else + sys_int_enable &= ~(0xf << 4); + rsnd_mod_write(mod, + SSI_SYS_INT_ENABLE((i * 2) + 1), + sys_int_enable); + } + break; + } +} + static bool rsnd_ssi_busif_err_status_clear(struct rsnd_mod *mod) { struct rsnd_priv *priv = rsnd_mod_to_priv(mod); @@ -421,9 +462,6 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, u32 wsr = ssi->wsr; int width; int is_tdm, is_tdm_split; - int id = rsnd_mod_id(mod); - int i; - u32 sys_int_enable = 0; is_tdm = rsnd_runtime_is_tdm(io); is_tdm_split = rsnd_runtime_is_tdm_split(io); @@ -499,36 +537,8 @@ static void rsnd_ssi_config_init(struct rsnd_mod *mod, } /* enable busif buffer over/under run interrupt. */ - if (is_tdm || is_tdm_split) { - switch (id) { - case 0: - case 1: - case 2: - case 3: - case 4: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE(i * 2)); - sys_int_enable |= 0xf << (id * 4); - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE(i * 2), - sys_int_enable); - } - - break; - case 9: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1)); - sys_int_enable |= 0xf << 4; - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1), - sys_int_enable); - } - - break; - } - } + if (is_tdm || is_tdm_split) + rsnd_ssi_busif_err_irq_enable(mod); init_end: ssi->cr_own = cr_own; @@ -585,8 +595,6 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, struct rsnd_ssi *ssi = rsnd_mod_to_ssi(mod); struct device *dev = rsnd_priv_to_dev(priv); int is_tdm, is_tdm_split; - int id = rsnd_mod_id(mod); - u32 sys_int_enable = 0; is_tdm = rsnd_runtime_is_tdm(io); is_tdm_split = rsnd_runtime_is_tdm_split(io); @@ -612,38 +620,8 @@ static int rsnd_ssi_quit(struct rsnd_mod *mod, } /* disable busif buffer over/under run interrupt. */ - if (is_tdm || is_tdm_split) { - int i; - - switch (id) { - case 0: - case 1: - case 2: - case 3: - case 4: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE(i * 2)); - sys_int_enable &= ~(0xf << (id * 4)); - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE(i * 2), - sys_int_enable); - } - - break; - case 9: - for (i = 0; i < 4; i++) { - sys_int_enable = rsnd_mod_read(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1)); - sys_int_enable &= ~(0xf << 4); - rsnd_mod_write(mod, - SSI_SYS_INT_ENABLE((i * 2) + 1), - sys_int_enable); - } - - break; - } - } + if (is_tdm || is_tdm_split) + rsnd_ssi_busif_err_irq_disable(mod); return 0; } From 63346d3d2f7cd96746149b9710a4cc5401c0cb5c Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Thu, 8 Apr 2021 13:29:15 +0900 Subject: [PATCH 0970/1091] ASoC: rsnd: add usage for SRC This patch add missing usage comment for SRC. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zgy9z9es.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/sh/rcar/src.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/sound/soc/sh/rcar/src.c b/sound/soc/sh/rcar/src.c index 585ffba0244b..628af8f3920d 100644 --- a/sound/soc/sh/rcar/src.c +++ b/sound/soc/sh/rcar/src.c @@ -5,6 +5,15 @@ // Copyright (C) 2013 Renesas Solutions Corp. // Kuninori Morimoto +/* + * You can use Synchronous Sampling Rate Convert (if no DVC) + * + * amixer set "SRC Out Rate" on + * aplay xxx.wav & + * amixer set "SRC Out Rate" 96000 // convert rate to 96000Hz + * amixer set "SRC Out Rate" 22050 // convert rate to 22050Hz + */ + /* * you can enable below define if you don't need * SSI interrupt status debug message when debugging From 0b93bbc977af55fd10687f2c96c807cba95cb927 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 14 Apr 2021 14:33:43 +0800 Subject: [PATCH 0971/1091] ASoC: ak5558: correct reset polarity Reset (aka power off) happens when the reset gpio is made active. The reset gpio is GPIO_ACTIVE_LOW Fixes: 920884777480 ("ASoC: ak5558: Add support for AK5558 ADC driver") Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1618382024-31725-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index 8e4dca753f0b..f24d91b728dd 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -323,7 +323,7 @@ static void ak5558_power_off(struct ak5558_priv *ak5558) if (!ak5558->reset_gpiod) return; - gpiod_set_value_cansleep(ak5558->reset_gpiod, 0); + gpiod_set_value_cansleep(ak5558->reset_gpiod, 1); usleep_range(1000, 2000); } @@ -332,7 +332,7 @@ static void ak5558_power_on(struct ak5558_priv *ak5558) if (!ak5558->reset_gpiod) return; - gpiod_set_value_cansleep(ak5558->reset_gpiod, 1); + gpiod_set_value_cansleep(ak5558->reset_gpiod, 0); usleep_range(1000, 2000); } From 4d5d75ce2b32577afef26a233119d8ee1b764ea7 Mon Sep 17 00:00:00 2001 From: Shengjiu Wang Date: Wed, 14 Apr 2021 14:33:44 +0800 Subject: [PATCH 0972/1091] ASoC: ak5558: change function name to ak5558_reset Change function name to ak5558_reset to match devicetree property "reset-gpios". Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1618382024-31725-2-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak5558.c | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/ak5558.c b/sound/soc/codecs/ak5558.c index f24d91b728dd..34aed80db0eb 100644 --- a/sound/soc/codecs/ak5558.c +++ b/sound/soc/codecs/ak5558.c @@ -318,21 +318,12 @@ static struct snd_soc_dai_driver ak5552_dai = { .ops = &ak5558_dai_ops, }; -static void ak5558_power_off(struct ak5558_priv *ak5558) +static void ak5558_reset(struct ak5558_priv *ak5558, bool active) { if (!ak5558->reset_gpiod) return; - gpiod_set_value_cansleep(ak5558->reset_gpiod, 1); - usleep_range(1000, 2000); -} - -static void ak5558_power_on(struct ak5558_priv *ak5558) -{ - if (!ak5558->reset_gpiod) - return; - - gpiod_set_value_cansleep(ak5558->reset_gpiod, 0); + gpiod_set_value_cansleep(ak5558->reset_gpiod, active); usleep_range(1000, 2000); } @@ -340,7 +331,7 @@ static int ak5558_probe(struct snd_soc_component *component) { struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); - ak5558_power_on(ak5558); + ak5558_reset(ak5558, false); return ak5558_set_mcki(component); } @@ -348,7 +339,7 @@ static void ak5558_remove(struct snd_soc_component *component) { struct ak5558_priv *ak5558 = snd_soc_component_get_drvdata(component); - ak5558_power_off(ak5558); + ak5558_reset(ak5558, true); } static int __maybe_unused ak5558_runtime_suspend(struct device *dev) @@ -356,7 +347,7 @@ static int __maybe_unused ak5558_runtime_suspend(struct device *dev) struct ak5558_priv *ak5558 = dev_get_drvdata(dev); regcache_cache_only(ak5558->regmap, true); - ak5558_power_off(ak5558); + ak5558_reset(ak5558, true); regulator_bulk_disable(ARRAY_SIZE(ak5558->supplies), ak5558->supplies); @@ -375,8 +366,8 @@ static int __maybe_unused ak5558_runtime_resume(struct device *dev) return ret; } - ak5558_power_off(ak5558); - ak5558_power_on(ak5558); + ak5558_reset(ak5558, true); + ak5558_reset(ak5558, false); regcache_cache_only(ak5558->regmap, false); regcache_mark_dirty(ak5558->regmap); From e42b6e813f4231d3c38362fd800724bd41040ef9 Mon Sep 17 00:00:00 2001 From: Yang Li Date: Wed, 14 Apr 2021 14:14:43 +0800 Subject: [PATCH 0973/1091] ASoC: cs35l35: remove unused including Fix the following versioncheck warning: ./sound/soc/codecs/cs35l35.c: 12 linux/version.h not needed. Reported-by: Abaci Robot Signed-off-by: Yang Li Link: https://lore.kernel.org/r/1618380883-114841-1-git-send-email-yang.lee@linux.alibaba.com Signed-off-by: Mark Brown --- sound/soc/codecs/cs35l35.c | 1 - 1 file changed, 1 deletion(-) diff --git a/sound/soc/codecs/cs35l35.c b/sound/soc/codecs/cs35l35.c index 7b9f5498f8a7..f20ed838b958 100644 --- a/sound/soc/codecs/cs35l35.c +++ b/sound/soc/codecs/cs35l35.c @@ -9,7 +9,6 @@ #include #include -#include #include #include #include From b5fb388da472a69858355560d803602e0ace1006 Mon Sep 17 00:00:00 2001 From: Nico Pache Date: Wed, 14 Apr 2021 04:58:04 -0400 Subject: [PATCH 0974/1091] ASoC: topology: adhere to KUNIT formatting standard Drop 'S' from end of SND_SOC_TOPOLOGY_KUNIT_TESTS inorder to adhear to the KUNIT *_KUNIT_TEST config name format. Signed-off-by: Nico Pache Link: https://lore.kernel.org/r/dcf79e592f9a7e14483dde32ac561f6af2632e50.1618388989.git.npache@redhat.com Signed-off-by: Mark Brown --- sound/soc/Kconfig | 2 +- sound/soc/Makefile | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/Kconfig b/sound/soc/Kconfig index 640494f76cbd..8a13462e1a63 100644 --- a/sound/soc/Kconfig +++ b/sound/soc/Kconfig @@ -37,7 +37,7 @@ config SND_SOC_COMPRESS config SND_SOC_TOPOLOGY bool -config SND_SOC_TOPOLOGY_KUNIT_TESTS +config SND_SOC_TOPOLOGY_KUNIT_TEST tristate "KUnit tests for SoC topology" depends on KUNIT depends on SND_SOC_TOPOLOGY diff --git a/sound/soc/Makefile b/sound/soc/Makefile index f56ad996eae8..a7b37c06dc43 100644 --- a/sound/soc/Makefile +++ b/sound/soc/Makefile @@ -7,9 +7,9 @@ ifneq ($(CONFIG_SND_SOC_TOPOLOGY),) snd-soc-core-objs += soc-topology.o endif -ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS),) +ifneq ($(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST),) # snd-soc-test-objs := soc-topology-test.o -obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TESTS) := soc-topology-test.o +obj-$(CONFIG_SND_SOC_TOPOLOGY_KUNIT_TEST) := soc-topology-test.o endif ifneq ($(CONFIG_SND_SOC_GENERIC_DMAENGINE_PCM),) From 8ca7cab82bda4eb0b8064befeeeaa38106cac637 Mon Sep 17 00:00:00 2001 From: Jaegeuk Kim Date: Wed, 14 Apr 2021 08:28:28 -0700 Subject: [PATCH 0975/1091] dm verity fec: fix misaligned RS roots IO commit df7b59ba9245 ("dm verity: fix FEC for RS roots unaligned to block size") introduced the possibility for misaligned roots IO relative to the underlying device's logical block size. E.g. Android's default RS roots=2 results in dm_bufio->block_size=1024, which causes the following EIO if the logical block size of the device is 4096, given v->data_dev_block_bits=12: E sd 0 : 0:0:0: [sda] tag#30 request not aligned to the logical block size E blk_update_request: I/O error, dev sda, sector 10368424 op 0x0:(READ) flags 0x0 phys_seg 1 prio class 0 E device-mapper: verity-fec: 254:8: FEC 9244672: parity read failed (block 18056): -5 Fix this by onlu using f->roots for dm_bufio blocksize IFF it is aligned to v->data_dev_block_bits. Fixes: df7b59ba9245 ("dm verity: fix FEC for RS roots unaligned to block size") Cc: stable@vger.kernel.org Signed-off-by: Jaegeuk Kim Signed-off-by: Mike Snitzer --- drivers/md/dm-verity-fec.c | 11 ++++++++--- drivers/md/dm-verity-fec.h | 1 + 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/drivers/md/dm-verity-fec.c b/drivers/md/dm-verity-fec.c index 66f4c6398f67..cea2b3789736 100644 --- a/drivers/md/dm-verity-fec.c +++ b/drivers/md/dm-verity-fec.c @@ -65,7 +65,7 @@ static u8 *fec_read_parity(struct dm_verity *v, u64 rsb, int index, u8 *res; position = (index + rsb) * v->fec->roots; - block = div64_u64_rem(position, v->fec->roots << SECTOR_SHIFT, &rem); + block = div64_u64_rem(position, v->fec->io_size, &rem); *offset = (unsigned)rem; res = dm_bufio_read(v->fec->bufio, block, buf); @@ -154,7 +154,7 @@ static int fec_decode_bufs(struct dm_verity *v, struct dm_verity_fec_io *fio, /* read the next block when we run out of parity bytes */ offset += v->fec->roots; - if (offset >= v->fec->roots << SECTOR_SHIFT) { + if (offset >= v->fec->io_size) { dm_bufio_release(buf); par = fec_read_parity(v, rsb, block_offset, &offset, &buf); @@ -742,8 +742,13 @@ int verity_fec_ctr(struct dm_verity *v) return -E2BIG; } + if ((f->roots << SECTOR_SHIFT) & ((1 << v->data_dev_block_bits) - 1)) + f->io_size = 1 << v->data_dev_block_bits; + else + f->io_size = v->fec->roots << SECTOR_SHIFT; + f->bufio = dm_bufio_client_create(f->dev->bdev, - f->roots << SECTOR_SHIFT, + f->io_size, 1, 0, NULL, NULL); if (IS_ERR(f->bufio)) { ti->error = "Cannot initialize FEC bufio client"; diff --git a/drivers/md/dm-verity-fec.h b/drivers/md/dm-verity-fec.h index 42fbd3a7fc9f..3c46c8d61883 100644 --- a/drivers/md/dm-verity-fec.h +++ b/drivers/md/dm-verity-fec.h @@ -36,6 +36,7 @@ struct dm_verity_fec { struct dm_dev *dev; /* parity data device */ struct dm_bufio_client *data_bufio; /* for data dev access */ struct dm_bufio_client *bufio; /* for parity data access */ + size_t io_size; /* IO size for roots */ sector_t start; /* parity data start in blocks */ sector_t blocks; /* number of blocks covered */ sector_t rounds; /* number of interleaving rounds */ From c7d95613c7d6e003969722a290397b8271bdad17 Mon Sep 17 00:00:00 2001 From: Pavel Begunkov Date: Tue, 13 Apr 2021 11:43:00 +0100 Subject: [PATCH 0976/1091] io_uring: fix early sqd_list removal sqpoll hangs [ 245.463317] INFO: task iou-sqp-1374:1377 blocked for more than 122 seconds. [ 245.463334] task:iou-sqp-1374 state:D flags:0x00004000 [ 245.463345] Call Trace: [ 245.463352] __schedule+0x36b/0x950 [ 245.463376] schedule+0x68/0xe0 [ 245.463385] __io_uring_cancel+0xfb/0x1a0 [ 245.463407] do_exit+0xc0/0xb40 [ 245.463423] io_sq_thread+0x49b/0x710 [ 245.463445] ret_from_fork+0x22/0x30 It happens when sqpoll forgot to run park_task_work and goes to exit, then exiting user may remove ctx from sqd_list, and so corresponding io_sq_thread() -> io_uring_cancel_sqpoll() won't be executed. Hopefully it just stucks in do_exit() in this case. Fixes: dbe1bdbb39db ("io_uring: handle signals for IO threads like a normal thread") Reported-by: Joakim Hassila Signed-off-by: Pavel Begunkov Signed-off-by: Jens Axboe --- fs/io_uring.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/fs/io_uring.c b/fs/io_uring.c index bd14327c8e7e..dff34975d86b 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -6754,6 +6754,9 @@ static int io_sq_thread(void *data) current->flags |= PF_NO_SETAFFINITY; mutex_lock(&sqd->lock); + /* a user may had exited before the thread started */ + io_run_task_work_head(&sqd->park_task_work); + while (!test_bit(IO_SQ_THREAD_SHOULD_STOP, &sqd->state)) { int ret; bool cap_entries, sqt_spin, needs_sched; @@ -6770,10 +6773,10 @@ static int io_sq_thread(void *data) } cond_resched(); mutex_lock(&sqd->lock); - if (did_sig) - break; io_run_task_work(); io_run_task_work_head(&sqd->park_task_work); + if (did_sig) + break; timeout = jiffies + sqd->sq_thread_idle; continue; } From 16756d3e77ad58cd07e36cbed724aa13ae5a0278 Mon Sep 17 00:00:00 2001 From: Jakub Kicinski Date: Tue, 13 Apr 2021 20:46:14 -0700 Subject: [PATCH 0977/1091] ethtool: pause: make sure we init driver stats The intention was for pause statistics to not be reported when driver does not have the relevant callback (only report an empty netlink nest). What happens currently we report all 0s instead. Make sure statistics are initialized to "not set" (which is -1) so the dumping code skips them. Fixes: 9a27a33027f2 ("ethtool: add standard pause stats") Signed-off-by: Jakub Kicinski Signed-off-by: David S. Miller --- net/ethtool/pause.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/net/ethtool/pause.c b/net/ethtool/pause.c index 09998dc5c185..d4ac02718b72 100644 --- a/net/ethtool/pause.c +++ b/net/ethtool/pause.c @@ -38,16 +38,16 @@ static int pause_prepare_data(const struct ethnl_req_info *req_base, if (!dev->ethtool_ops->get_pauseparam) return -EOPNOTSUPP; + ethtool_stats_init((u64 *)&data->pausestat, + sizeof(data->pausestat) / 8); + ret = ethnl_ops_begin(dev); if (ret < 0) return ret; dev->ethtool_ops->get_pauseparam(dev, &data->pauseparam); if (req_base->flags & ETHTOOL_FLAG_STATS && - dev->ethtool_ops->get_pause_stats) { - ethtool_stats_init((u64 *)&data->pausestat, - sizeof(data->pausestat) / 8); + dev->ethtool_ops->get_pause_stats) dev->ethtool_ops->get_pause_stats(dev, &data->pausestat); - } ethnl_ops_complete(dev); return 0; From 453a77894efa4d9b6ef9644d74b9419c47ac427c Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Wed, 14 Apr 2021 10:47:10 +0200 Subject: [PATCH 0978/1091] r8169: don't advertise pause in jumbo mode It has been reported [0] that using pause frames in jumbo mode impacts performance. There's no available chip documentation, but vendor drivers r8168 and r8125 don't advertise pause in jumbo mode. So let's do the same, according to Roman it fixes the issue. [0] https://bugzilla.kernel.org/show_bug.cgi?id=212617 Fixes: 9cf9b84cc701 ("r8169: make use of phy_set_asym_pause") Reported-by: Roman Mamedov Tested-by: Roman Mamedov Signed-off-by: Heiner Kallweit Cc: stable@vger.kernel.org Signed-off-by: David S. Miller --- drivers/net/ethernet/realtek/r8169_main.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/realtek/r8169_main.c b/drivers/net/ethernet/realtek/r8169_main.c index 581a92fc3292..1df2c002c9f6 100644 --- a/drivers/net/ethernet/realtek/r8169_main.c +++ b/drivers/net/ethernet/realtek/r8169_main.c @@ -2350,6 +2350,13 @@ static void rtl_jumbo_config(struct rtl8169_private *tp) if (pci_is_pcie(tp->pci_dev) && tp->supports_gmii) pcie_set_readrq(tp->pci_dev, readrq); + + /* Chip doesn't support pause in jumbo mode */ + linkmode_mod_bit(ETHTOOL_LINK_MODE_Pause_BIT, + tp->phydev->advertising, !jumbo); + linkmode_mod_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT, + tp->phydev->advertising, !jumbo); + phy_start_aneg(tp->phydev); } DECLARE_RTL_COND(rtl_chipcmd_cond) @@ -4630,8 +4637,6 @@ static int r8169_phy_connect(struct rtl8169_private *tp) if (!tp->supports_gmii) phy_set_max_speed(phydev, SPEED_100); - phy_support_asym_pause(phydev); - phy_attached_info(phydev); return 0; From 0775ebc4cf8554bdcd2c212669a0868ab68df5c0 Mon Sep 17 00:00:00 2001 From: Lijun Pan Date: Wed, 14 Apr 2021 02:46:14 -0500 Subject: [PATCH 0979/1091] ibmvnic: avoid calling napi_disable() twice __ibmvnic_open calls napi_disable without checking whether NAPI polling has already been disabled or not. This could cause napi_disable being called twice, which could generate deadlock. For example, the first napi_disable will spin until NAPI_STATE_SCHED is cleared by napi_complete_done, then set it again. When napi_disable is called the second time, it will loop infinitely because no dev->poll will be running to clear NAPI_STATE_SCHED. To prevent above scenario from happening, call ibmvnic_napi_disable() which checks if napi is disabled or not before calling napi_disable. Fixes: bfc32f297337 ("ibmvnic: Move resource initialization to its own routine") Suggested-by: Thomas Falcon Signed-off-by: Lijun Pan Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 110a0d0eaabb..2d27f8aa0d4b 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1149,8 +1149,7 @@ static int __ibmvnic_open(struct net_device *netdev) rc = set_link_state(adapter, IBMVNIC_LOGICAL_LNK_UP); if (rc) { - for (i = 0; i < adapter->req_rx_queues; i++) - napi_disable(&adapter->napi[i]); + ibmvnic_napi_disable(adapter); release_resources(adapter); return rc; } From d3a6abccbd272aea7dc2c6f984bb5a2c11278e44 Mon Sep 17 00:00:00 2001 From: Lijun Pan Date: Wed, 14 Apr 2021 02:46:15 -0500 Subject: [PATCH 0980/1091] ibmvnic: remove duplicate napi_schedule call in do_reset function During adapter reset, do_reset/do_hard_reset calls ibmvnic_open(), which will calls napi_schedule if previous state is VNIC_CLOSED (i.e, the reset case, and "ifconfig down" case). So there is no need for do_reset to call napi_schedule again at the end of the function though napi_schedule will neglect the request if napi is already scheduled. Fixes: ed651a10875f ("ibmvnic: Updated reset handling") Signed-off-by: Lijun Pan Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index 2d27f8aa0d4b..f4bd63216672 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1921,7 +1921,7 @@ static int do_reset(struct ibmvnic_adapter *adapter, u64 old_num_rx_queues, old_num_tx_queues; u64 old_num_rx_slots, old_num_tx_slots; struct net_device *netdev = adapter->netdev; - int i, rc; + int rc; netdev_dbg(adapter->netdev, "[S:%d FOP:%d] Reset reason %d, reset_state %d\n", @@ -2110,10 +2110,6 @@ static int do_reset(struct ibmvnic_adapter *adapter, /* refresh device's multicast list */ ibmvnic_set_multi(netdev); - /* kick napi */ - for (i = 0; i < adapter->req_rx_queues; i++) - napi_schedule(&adapter->napi[i]); - if (adapter->reset_reason == VNIC_RESET_FAILOVER || adapter->reset_reason == VNIC_RESET_MOBILITY) __netdev_notify_peers(netdev); From 7c451f3ef676c805a4b77a743a01a5c21a250a73 Mon Sep 17 00:00:00 2001 From: Lijun Pan Date: Wed, 14 Apr 2021 02:46:16 -0500 Subject: [PATCH 0981/1091] ibmvnic: remove duplicate napi_schedule call in open function Remove the unnecessary napi_schedule() call in __ibmvnic_open() since interrupt_rx() calls napi_schedule_prep/__napi_schedule during every receive interrupt. Fixes: ed651a10875f ("ibmvnic: Updated reset handling") Signed-off-by: Lijun Pan Signed-off-by: David S. Miller --- drivers/net/ethernet/ibm/ibmvnic.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/drivers/net/ethernet/ibm/ibmvnic.c b/drivers/net/ethernet/ibm/ibmvnic.c index f4bd63216672..ffb2a91750c7 100644 --- a/drivers/net/ethernet/ibm/ibmvnic.c +++ b/drivers/net/ethernet/ibm/ibmvnic.c @@ -1156,11 +1156,6 @@ static int __ibmvnic_open(struct net_device *netdev) netif_tx_start_all_queues(netdev); - if (prev_state == VNIC_CLOSED) { - for (i = 0; i < adapter->req_rx_queues; i++) - napi_schedule(&adapter->napi[i]); - } - adapter->state = VNIC_OPEN; return rc; } From 292ecd9f5a94dd29d09fe03b5b669cb20b44f19e Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 14 Apr 2021 12:00:27 +0200 Subject: [PATCH 0982/1091] doc: move seg6_flowlabel to seg6-sysctl.rst Let's have all seg6 sysctl at the same place. Fixes: a6dc6670cd7e ("ipv6: sr: Add documentation for seg_flowlabel sysctl") Signed-off-by: Nicolas Dichtel Signed-off-by: David S. Miller --- Documentation/networking/ip-sysctl.rst | 15 --------------- Documentation/networking/seg6-sysctl.rst | 13 +++++++++++++ 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/Documentation/networking/ip-sysctl.rst b/Documentation/networking/ip-sysctl.rst index c7952ac5bd2f..3feb5e565b1a 100644 --- a/Documentation/networking/ip-sysctl.rst +++ b/Documentation/networking/ip-sysctl.rst @@ -1849,21 +1849,6 @@ ip6frag_low_thresh - INTEGER ip6frag_time - INTEGER Time in seconds to keep an IPv6 fragment in memory. -IPv6 Segment Routing: - -seg6_flowlabel - INTEGER - Controls the behaviour of computing the flowlabel of outer - IPv6 header in case of SR T.encaps - - == ======================================================= - -1 set flowlabel to zero. - 0 copy flowlabel from Inner packet in case of Inner IPv6 - (Set flowlabel to 0 in case IPv4/L2) - 1 Compute the flowlabel using seg6_make_flowlabel() - == ======================================================= - - Default is 0. - ``conf/default/*``: Change the interface-specific default settings. diff --git a/Documentation/networking/seg6-sysctl.rst b/Documentation/networking/seg6-sysctl.rst index ec73e1445030..07c20e470baf 100644 --- a/Documentation/networking/seg6-sysctl.rst +++ b/Documentation/networking/seg6-sysctl.rst @@ -24,3 +24,16 @@ seg6_require_hmac - INTEGER * 1 - Drop SR packets without HMAC, validate SR packets with HMAC Default is 0. + +seg6_flowlabel - INTEGER + Controls the behaviour of computing the flowlabel of outer + IPv6 header in case of SR T.encaps + + == ======================================================= + -1 set flowlabel to zero. + 0 copy flowlabel from Inner packet in case of Inner IPv6 + (Set flowlabel to 0 in case IPv4/L2) + 1 Compute the flowlabel using seg6_make_flowlabel() + == ======================================================= + + Default is 0. From 2e1534f395e73152e2051332034bff61a56a8368 Mon Sep 17 00:00:00 2001 From: Nicolas Dichtel Date: Wed, 14 Apr 2021 12:03:25 +0200 Subject: [PATCH 0983/1091] vrf: fix a comment about loopback device This is a leftover of the below commit. Fixes: 4f04256c983a ("net: vrf: Drop local rtable and rt6_info") Signed-off-by: Nicolas Dichtel Acked-by: David Ahern Signed-off-by: David S. Miller --- drivers/net/vrf.c | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/drivers/net/vrf.c b/drivers/net/vrf.c index 6d9130859c55..503e2fd7ce51 100644 --- a/drivers/net/vrf.c +++ b/drivers/net/vrf.c @@ -471,9 +471,8 @@ static netdev_tx_t vrf_process_v6_outbound(struct sk_buff *skb, skb_dst_drop(skb); - /* if dst.dev is loopback or the VRF device again this is locally - * originated traffic destined to a local address. Short circuit - * to Rx path + /* if dst.dev is the VRF device again this is locally originated traffic + * destined to a local address. Short circuit to Rx path. */ if (dst->dev == dev) return vrf_local_xmit(skb, dev, dst); @@ -547,9 +546,8 @@ static netdev_tx_t vrf_process_v4_outbound(struct sk_buff *skb, skb_dst_drop(skb); - /* if dst.dev is loopback or the VRF device again this is locally - * originated traffic destined to a local address. Short circuit - * to Rx path + /* if dst.dev is the VRF device again this is locally originated traffic + * destined to a local address. Short circuit to Rx path. */ if (rt->dst.dev == vrf_dev) return vrf_local_xmit(skb, vrf_dev, &rt->dst); From ab4d9913632b1e5ffcf3365783e98718b3c83c7f Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Thu, 14 Jan 2021 18:38:16 -0500 Subject: [PATCH 0984/1091] drm/vmwgfx: Make sure we unpin no longer needed buffers MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were not correctly unpinning no longer needed buffers. In particular vmw_buffer_object, which is internally often pinned on creation wasn't unpinned on destruction and none of the internal MOB buffers were unpinned before being put back. Technically this existed for a long time but commit 57fcd550eb15 ("drm/ttm: Warn on pinning without holding a reference") introduced a WARN_ON which was filling up the kernel logs rather quickly. Quite frankly internal usage of vmw_buffer_object and in general pinning needs to be refactored in vmwgfx but for now this makes it work. Signed-off-by: Zack Rusin Reviewed-by: Martin Krastev Reviewed-by: Roland Scheidegger Fixes: 57fcd550eb15 ("drm/ttm: Warn on pinning without holding a reference") Link: https://patchwork.freedesktop.org/patch/414984/?series=86052&rev=1 Cc: Huang Rui Cc: Christian König Cc: Daniel Vetter Cc: Christian Koenig Cc: dri-devel@lists.freedesktop.org --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 ++ drivers/gpu/drm/vmwgfx/vmwgfx_mob.c | 4 ++++ 2 files changed, 6 insertions(+) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 5fa5bcd20cc5..336f5086ca26 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1525,6 +1525,8 @@ static inline void vmw_bo_unreference(struct vmw_buffer_object **buf) *buf = NULL; if (tmp_buf != NULL) { + if (tmp_buf->base.pin_count > 0) + ttm_bo_unpin(&tmp_buf->base); ttm_bo_put(&tmp_buf->base); } } diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c index a372980fe6a5..a0b53141dded 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c @@ -277,6 +277,7 @@ out_no_setup: &batch->otables[i]); } + ttm_bo_unpin(batch->otable_bo); ttm_bo_put(batch->otable_bo); batch->otable_bo = NULL; return ret; @@ -342,6 +343,7 @@ static void vmw_otable_batch_takedown(struct vmw_private *dev_priv, vmw_bo_fence_single(bo, NULL); ttm_bo_unreserve(bo); + ttm_bo_unpin(batch->otable_bo); ttm_bo_put(batch->otable_bo); batch->otable_bo = NULL; } @@ -528,6 +530,7 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, void vmw_mob_destroy(struct vmw_mob *mob) { if (mob->pt_bo) { + ttm_bo_unpin(mob->pt_bo); ttm_bo_put(mob->pt_bo); mob->pt_bo = NULL; } @@ -643,6 +646,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv, out_no_cmd_space: vmw_fifo_resource_dec(dev_priv); if (pt_set_up) { + ttm_bo_unpin(mob->pt_bo); ttm_bo_put(mob->pt_bo); mob->pt_bo = NULL; } From 68ce556bd1643498080af310d4544f46f3c4f3df Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Mon, 22 Mar 2021 12:54:57 -0400 Subject: [PATCH 0985/1091] drm/vmwgfx: Fix the lockdep breakage Thomas has noticed that the lockdep was broken in vmwgfx. It was broken during the pci initialization rework. This fixes the breakage by making sure we initialize the locking code before doing anything else. This was independently spotted and fixed by Tetsuo Handa as well. Reviewed-by: Martin Krastev Reviewed-by: Roland Scheidegger Cc: Tetsuo Handa Cc: dri-devel@lists.freedesktop.org Signed-off-by: Zack Rusin Fixes: 8772c0bb58bbf98a ("drm/vmwgfx: Cleanup pci resource allocation") Link: https://patchwork.freedesktop.org/patch/msgid/20210408172245.673785-1-zackr@vmware.com --- drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | 19 +++++++++---------- drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 2 -- 2 files changed, 9 insertions(+), 12 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index dd69b51c40e4..6fa24645fbbf 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c @@ -712,6 +712,15 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) dev_priv->last_read_seqno = (uint32_t) -100; dev_priv->drm.dev_private = dev_priv; + mutex_init(&dev_priv->cmdbuf_mutex); + mutex_init(&dev_priv->binding_mutex); + ttm_lock_init(&dev_priv->reservation_sem); + spin_lock_init(&dev_priv->resource_lock); + spin_lock_init(&dev_priv->hw_lock); + spin_lock_init(&dev_priv->waiter_lock); + spin_lock_init(&dev_priv->cap_lock); + spin_lock_init(&dev_priv->cursor_lock); + ret = vmw_setup_pci_resources(dev_priv, pci_id); if (ret) return ret; @@ -719,16 +728,6 @@ static int vmw_driver_load(struct vmw_private *dev_priv, u32 pci_id) if (ret) goto out_no_pci_or_version; - mutex_init(&dev_priv->cmdbuf_mutex); - mutex_init(&dev_priv->release_mutex); - mutex_init(&dev_priv->binding_mutex); - mutex_init(&dev_priv->global_kms_state_mutex); - ttm_lock_init(&dev_priv->reservation_sem); - spin_lock_init(&dev_priv->resource_lock); - spin_lock_init(&dev_priv->hw_lock); - spin_lock_init(&dev_priv->waiter_lock); - spin_lock_init(&dev_priv->cap_lock); - spin_lock_init(&dev_priv->cursor_lock); for (i = vmw_res_context; i < vmw_res_max; ++i) { idr_init(&dev_priv->res_idr[i]); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 336f5086ca26..8087a9013455 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -529,7 +529,6 @@ struct vmw_private { struct vmw_overlay *overlay_priv; struct drm_property *hotplug_mode_update_property; struct drm_property *implicit_placement_property; - struct mutex global_kms_state_mutex; spinlock_t cursor_lock; struct drm_atomic_state *suspend_state; @@ -592,7 +591,6 @@ struct vmw_private { bool refuse_hibernation; bool suspend_locked; - struct mutex release_mutex; atomic_t num_fifo_resources; /* From 2ef4fb92363c44e8a6f93fd0877b6a7dee6f874d Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Mon, 22 Mar 2021 13:04:11 -0400 Subject: [PATCH 0986/1091] drm/vmwgfx: Make sure bo's are unpinned before putting them back MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit During cotable resize we pin the backup buffer to make sure the trylock doesn't fail. We were never unpinning the backup buffer resulting in every subsequent cotable resize trying to release a pinned bo. After we copy the old backup to the new we can release the pin. Mob's are always pinned so we just have to make sure we unpin them before releasing them. Reviewed-by: Thomas Hellström (Intel) Fixes: d1a73c641afd ("drm/vmwgfx: Make sure we unpin no longer needed buffers") Link: https://patchwork.freedesktop.org/patch/msgid/20210413205938.788366-1-zackr@vmware.com Signed-off-by: Zack Rusin --- drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c | 4 ++++ drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | 5 +---- drivers/gpu/drm/vmwgfx/vmwgfx_mob.c | 18 ++++++++++++++---- 3 files changed, 19 insertions(+), 8 deletions(-) diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c index ba658fa9cf6c..183571c387b7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_cotable.c @@ -481,11 +481,15 @@ static int vmw_cotable_resize(struct vmw_resource *res, size_t new_size) vmw_bo_unreference(&old_buf); res->id = vcotbl->type; + /* Release the pin acquired in vmw_bo_init */ + ttm_bo_unpin(bo); + return 0; out_map_new: ttm_bo_kunmap(&old_map); out_wait: + ttm_bo_unpin(bo); ttm_bo_unreserve(bo); vmw_bo_unreference(&buf); diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index 8087a9013455..eb76a6b9ebca 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h @@ -1522,11 +1522,8 @@ static inline void vmw_bo_unreference(struct vmw_buffer_object **buf) struct vmw_buffer_object *tmp_buf = *buf; *buf = NULL; - if (tmp_buf != NULL) { - if (tmp_buf->base.pin_count > 0) - ttm_bo_unpin(&tmp_buf->base); + if (tmp_buf != NULL) ttm_bo_put(&tmp_buf->base); - } } static inline struct vmw_buffer_object * diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c index a0b53141dded..f2d625415458 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_mob.c @@ -94,6 +94,16 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, struct vmw_piter data_iter, unsigned long num_data_pages); + +static inline void vmw_bo_unpin_unlocked(struct ttm_buffer_object *bo) +{ + int ret = ttm_bo_reserve(bo, false, true, NULL); + BUG_ON(ret != 0); + ttm_bo_unpin(bo); + ttm_bo_unreserve(bo); +} + + /* * vmw_setup_otable_base - Issue an object table base setup command to * the device @@ -277,7 +287,7 @@ out_no_setup: &batch->otables[i]); } - ttm_bo_unpin(batch->otable_bo); + vmw_bo_unpin_unlocked(batch->otable_bo); ttm_bo_put(batch->otable_bo); batch->otable_bo = NULL; return ret; @@ -341,9 +351,9 @@ static void vmw_otable_batch_takedown(struct vmw_private *dev_priv, BUG_ON(ret != 0); vmw_bo_fence_single(bo, NULL); + ttm_bo_unpin(bo); ttm_bo_unreserve(bo); - ttm_bo_unpin(batch->otable_bo); ttm_bo_put(batch->otable_bo); batch->otable_bo = NULL; } @@ -530,7 +540,7 @@ static void vmw_mob_pt_setup(struct vmw_mob *mob, void vmw_mob_destroy(struct vmw_mob *mob) { if (mob->pt_bo) { - ttm_bo_unpin(mob->pt_bo); + vmw_bo_unpin_unlocked(mob->pt_bo); ttm_bo_put(mob->pt_bo); mob->pt_bo = NULL; } @@ -646,7 +656,7 @@ int vmw_mob_bind(struct vmw_private *dev_priv, out_no_cmd_space: vmw_fifo_resource_dec(dev_priv); if (pt_set_up) { - ttm_bo_unpin(mob->pt_bo); + vmw_bo_unpin_unlocked(mob->pt_bo); ttm_bo_put(mob->pt_bo); mob->pt_bo = NULL; } From a714e27ea8bdee2b238748029d31472d0a65b611 Mon Sep 17 00:00:00 2001 From: Claudiu Beznea Date: Wed, 14 Apr 2021 14:20:29 +0300 Subject: [PATCH 0987/1091] net: macb: fix the restore of cmp registers Commit a14d273ba159 ("net: macb: restore cmp registers on resume path") introduces the restore of CMP registers on resume path. In case the IP doesn't support type 2 screeners (zero on DCFG8 register) the struct macb::rx_fs_list::list is not initialized and thus the list_for_each_entry(item, &bp->rx_fs_list.list, list) loop introduced in commit a14d273ba159 ("net: macb: restore cmp registers on resume path") will access an uninitialized list leading to crash. Thus, initialize the struct macb::rx_fs_list::list without taking into account if the IP supports type 2 screeners or not. Fixes: a14d273ba159 ("net: macb: restore cmp registers on resume path") Signed-off-by: Claudiu Beznea Signed-off-by: David S. Miller --- drivers/net/ethernet/cadence/macb_main.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 6e5cf490c01d..0f6a6cb7e98d 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3918,6 +3918,7 @@ static int macb_init(struct platform_device *pdev) reg = gem_readl(bp, DCFG8); bp->max_tuples = min((GEM_BFEXT(SCR2CMP, reg) / 3), GEM_BFEXT(T2SCR, reg)); + INIT_LIST_HEAD(&bp->rx_fs_list.list); if (bp->max_tuples > 0) { /* also needs one ethtype match to check IPv4 */ if (GEM_BFEXT(SCR2ETH, reg) > 0) { @@ -3928,7 +3929,6 @@ static int macb_init(struct platform_device *pdev) /* Filtering is supported in hw but don't enable it in kernel now */ dev->hw_features |= NETIF_F_NTUPLE; /* init Rx flow definitions */ - INIT_LIST_HEAD(&bp->rx_fs_list.list); bp->rx_fs_list.count = 0; spin_lock_init(&bp->rx_fs_lock); } else From 416dcc5ce9d2a810477171c62ffa061a98f87367 Mon Sep 17 00:00:00 2001 From: Wan Jiabing Date: Wed, 14 Apr 2021 19:31:48 +0800 Subject: [PATCH 0988/1091] cavium/liquidio: Fix duplicate argument Fix the following coccicheck warning: ./drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h:413:6-28: duplicated argument to & or | The CN6XXX_INTR_M1UPB0_ERR here is duplicate. Here should be CN6XXX_INTR_M1UNB0_ERR. Signed-off-by: Wan Jiabing Signed-off-by: David S. Miller --- drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h b/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h index b248966837b4..7aad40b2aa73 100644 --- a/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h +++ b/drivers/net/ethernet/cavium/liquidio/cn66xx_regs.h @@ -412,7 +412,7 @@ | CN6XXX_INTR_M0UNWI_ERR \ | CN6XXX_INTR_M1UPB0_ERR \ | CN6XXX_INTR_M1UPWI_ERR \ - | CN6XXX_INTR_M1UPB0_ERR \ + | CN6XXX_INTR_M1UNB0_ERR \ | CN6XXX_INTR_M1UNWI_ERR \ | CN6XXX_INTR_INSTR_DB_OF_ERR \ | CN6XXX_INTR_SLIST_DB_OF_ERR \ From 00423969d806d7169d16fa6314c570a472ca26c9 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Wed, 14 Apr 2021 17:10:07 +0200 Subject: [PATCH 0989/1091] Revert "net: stmmac: re-init rx buffers when mac resume back" This reverts commit 9c63faaa931e443e7abbbee9de0169f1d4710546, which introduces a suspend/resume regression on Jetson TX2 boards that can be reproduced every time. Given that the issue that this was supposed to fix only occurs very sporadically the safest course of action is to revert before v5.12 and then we can have another go at fixing the more rare issue in the next release (and perhaps backport it if necessary). The root cause of the observed problem seems to be that when the system is suspended, some packets are still in transit. When the descriptors for these buffers are cleared on resume, the descriptors become invalid and cause a fatal bus error. Link: https://lore.kernel.org/r/708edb92-a5df-ecc4-3126-5ab36707e275@nvidia.com/ Reported-by: Jonathan Hunter Signed-off-by: Thierry Reding Signed-off-by: David S. Miller --- .../net/ethernet/stmicro/stmmac/stmmac_main.c | 84 +------------------ 1 file changed, 1 insertion(+), 83 deletions(-) diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 208cae344ffa..4749bd0af160 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -1379,88 +1379,6 @@ static void stmmac_free_tx_buffer(struct stmmac_priv *priv, u32 queue, int i) } } -/** - * stmmac_reinit_rx_buffers - reinit the RX descriptor buffer. - * @priv: driver private structure - * Description: this function is called to re-allocate a receive buffer, perform - * the DMA mapping and init the descriptor. - */ -static void stmmac_reinit_rx_buffers(struct stmmac_priv *priv) -{ - u32 rx_count = priv->plat->rx_queues_to_use; - u32 queue; - int i; - - for (queue = 0; queue < rx_count; queue++) { - struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; - - for (i = 0; i < priv->dma_rx_size; i++) { - struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; - - if (buf->page) { - page_pool_recycle_direct(rx_q->page_pool, buf->page); - buf->page = NULL; - } - - if (priv->sph && buf->sec_page) { - page_pool_recycle_direct(rx_q->page_pool, buf->sec_page); - buf->sec_page = NULL; - } - } - } - - for (queue = 0; queue < rx_count; queue++) { - struct stmmac_rx_queue *rx_q = &priv->rx_queue[queue]; - - for (i = 0; i < priv->dma_rx_size; i++) { - struct stmmac_rx_buffer *buf = &rx_q->buf_pool[i]; - struct dma_desc *p; - - if (priv->extend_desc) - p = &((rx_q->dma_erx + i)->basic); - else - p = rx_q->dma_rx + i; - - if (!buf->page) { - buf->page = page_pool_dev_alloc_pages(rx_q->page_pool); - if (!buf->page) - goto err_reinit_rx_buffers; - - buf->addr = page_pool_get_dma_addr(buf->page); - } - - if (priv->sph && !buf->sec_page) { - buf->sec_page = page_pool_dev_alloc_pages(rx_q->page_pool); - if (!buf->sec_page) - goto err_reinit_rx_buffers; - - buf->sec_addr = page_pool_get_dma_addr(buf->sec_page); - } - - stmmac_set_desc_addr(priv, p, buf->addr); - if (priv->sph) - stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, true); - else - stmmac_set_desc_sec_addr(priv, p, buf->sec_addr, false); - if (priv->dma_buf_sz == BUF_SIZE_16KiB) - stmmac_init_desc3(priv, p); - } - } - - return; - -err_reinit_rx_buffers: - do { - while (--i >= 0) - stmmac_free_rx_buffer(priv, queue, i); - - if (queue == 0) - break; - - i = priv->dma_rx_size; - } while (queue-- > 0); -} - /** * init_dma_rx_desc_rings - init the RX descriptor rings * @dev: net device structure @@ -5428,7 +5346,7 @@ int stmmac_resume(struct device *dev) mutex_lock(&priv->lock); stmmac_reset_queues_param(priv); - stmmac_reinit_rx_buffers(priv); + stmmac_free_tx_skbufs(priv); stmmac_clear_descriptors(priv); From 41bafb31dcd58d834bdffa5db703f94fd2cec727 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Mon, 12 Apr 2021 17:50:08 +0300 Subject: [PATCH 0990/1091] net/mlx5: Fix setting of devlink traps in switchdev mode Prevent setting of devlink traps on the uplink while in switchdev mode. In this mode, it is the SW switch responsibility to handle both packets with a mismatch in destination MAC or VLAN ID. Therefore, there are no flow steering tables to trap undesirable packets and driver crashes upon setting a trap. Fixes: 241dc159391f ("net/mlx5: Notify on trap action by blocking event") Signed-off-by: Aya Levin Reviewed-by: Moshe Shemesh Reviewed-by: Roi Dayan Reviewed-by: Tariq Toukan Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/devlink.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c index d7d8a68ef23d..d0f9d3cee97d 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/devlink.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/devlink.c @@ -246,6 +246,11 @@ static int mlx5_devlink_trap_action_set(struct devlink *devlink, struct mlx5_devlink_trap *dl_trap; int err = 0; + if (is_mdev_switchdev_mode(dev)) { + NL_SET_ERR_MSG_MOD(extack, "Devlink traps can't be set in switchdev mode"); + return -EOPNOTSUPP; + } + dl_trap = mlx5_find_trap_by_id(dev, trap->id); if (!dl_trap) { mlx5_core_err(dev, "Devlink trap: Set action on invalid trap id 0x%x", trap->id); From 7a320c9db3e73fb6c4f9a331087df9df18767221 Mon Sep 17 00:00:00 2001 From: Aya Levin Date: Sun, 11 Apr 2021 09:33:12 +0300 Subject: [PATCH 0991/1091] net/mlx5e: Fix setting of RS FEC mode Change register setting from bit number to bit mask. Fixes: b5ede32d3329 ("net/mlx5e: Add support for FEC modes based on 50G per lane links") Signed-off-by: Aya Levin Reviewed-by: Eran Ben Elisha Signed-off-by: Saeed Mahameed --- .../net/ethernet/mellanox/mlx5/core/en/port.c | 23 ++++--------------- 1 file changed, 4 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c index 308fd279669e..89510cac46c2 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en/port.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en/port.c @@ -387,21 +387,6 @@ enum mlx5e_fec_supported_link_mode { *_policy = MLX5_GET(pplm_reg, _buf, fec_override_admin_##link); \ } while (0) -#define MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY(buf, policy, write, link) \ - do { \ - unsigned long policy_long; \ - u16 *__policy = &(policy); \ - bool _write = (write); \ - \ - policy_long = *__policy; \ - if (_write && *__policy) \ - *__policy = find_first_bit(&policy_long, \ - sizeof(policy_long) * BITS_PER_BYTE);\ - MLX5E_FEC_OVERRIDE_ADMIN_POLICY(buf, *__policy, _write, link); \ - if (!_write && *__policy) \ - *__policy = 1 << *__policy; \ - } while (0) - /* get/set FEC admin field for a given speed */ static int mlx5e_fec_admin_field(u32 *pplm, u16 *fec_policy, bool write, enum mlx5e_fec_supported_link_mode link_mode) @@ -423,16 +408,16 @@ static int mlx5e_fec_admin_field(u32 *pplm, u16 *fec_policy, bool write, MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g); break; case MLX5E_FEC_SUPPORTED_LINK_MODE_50G_1X: - MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY(pplm, *fec_policy, write, 50g_1x); + MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 50g_1x); break; case MLX5E_FEC_SUPPORTED_LINK_MODE_100G_2X: - MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY(pplm, *fec_policy, write, 100g_2x); + MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 100g_2x); break; case MLX5E_FEC_SUPPORTED_LINK_MODE_200G_4X: - MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY(pplm, *fec_policy, write, 200g_4x); + MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 200g_4x); break; case MLX5E_FEC_SUPPORTED_LINK_MODE_400G_8X: - MLX5E_FEC_OVERRIDE_ADMIN_50G_POLICY(pplm, *fec_policy, write, 400g_8x); + MLX5E_FEC_OVERRIDE_ADMIN_POLICY(pplm, *fec_policy, write, 400g_8x); break; default: return -EINVAL; From e3e0f9b279705154b951d579dc3d8b7041710e24 Mon Sep 17 00:00:00 2001 From: wenxu Date: Fri, 9 Apr 2021 13:33:48 +0800 Subject: [PATCH 0992/1091] net/mlx5e: fix ingress_ifindex check in mlx5e_flower_parse_meta In the nft_offload there is the mate flow_dissector with no ingress_ifindex but with ingress_iftype that only be used in the software. So if the mask of ingress_ifindex in meta is 0, this meta check should be bypass. Fixes: 6d65bc64e232 ("net/mlx5e: Add mlx5e_flower_parse_meta support") Signed-off-by: wenxu Acked-by: Pablo Neira Ayuso Signed-off-by: Saeed Mahameed --- drivers/net/ethernet/mellanox/mlx5/core/en_tc.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c index df2a0af854bb..d675107d9eca 100644 --- a/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c +++ b/drivers/net/ethernet/mellanox/mlx5/core/en_tc.c @@ -1895,6 +1895,9 @@ static int mlx5e_flower_parse_meta(struct net_device *filter_dev, return 0; flow_rule_match_meta(rule, &match); + if (!match.mask->ingress_ifindex) + return 0; + if (match.mask->ingress_ifindex != 0xFFFFFFFF) { NL_SET_ERR_MSG_MOD(extack, "Unsupported ingress ifindex mask"); return -EOPNOTSUPP; From 8cbea89e2fba2f92937cd15211490b62f14a46ff Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 14 Apr 2021 08:19:55 +0900 Subject: [PATCH 0993/1091] ASoC: simple-card: remove unused variable from simple_parse_of() commit d9ffff696c5b4 ("ASoC: simple-card: Use snd_soc_of_parse_aux_devs()") switched to use snd_soc_of_parse_aux_devs() on simple_parse_of(). Thus noone is using *top anymore. Let's cleanup unused variable. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87pmyxzs9w.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index bf5ddf1ea65f..7a87cd56d513 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -441,15 +441,10 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, static int simple_parse_of(struct asoc_simple_priv *priv) { - struct device *dev = simple_priv_to_dev(priv); - struct device_node *top = dev->of_node; struct snd_soc_card *card = simple_priv_to_card(priv); struct link_info li; int ret; - if (!top) - return -EINVAL; - ret = asoc_simple_parse_widgets(card, PREFIX); if (ret < 0) return ret; From 5bb5ac71e3f4f85500b96ea03e54bf6e2d8be3f2 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 14 Apr 2021 08:20:04 +0900 Subject: [PATCH 0994/1091] ASoC: simple-card: use asoc_link_to_xxx() macro We shouldn't use dai_link->cpus/codecs/platforms directly, because these are array now to supporting multi CPU/Codec/Platform. This patch uses asoc_link_to_xxx() macro for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87o8ehzs9n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 35 ++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 16 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 7a87cd56d513..9462b0d21486 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -122,9 +122,9 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct asoc_simple_dai *dai; - struct snd_soc_dai_link_component *cpus = dai_link->cpus; - struct snd_soc_dai_link_component *codecs = dai_link->codecs; - struct snd_soc_dai_link_component *platforms = dai_link->platforms; + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); struct device_node *top = dev->of_node; struct device_node *node = of_get_parent(np); char *prefix = ""; @@ -149,11 +149,11 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->cpu_dai; - ret = asoc_simple_parse_dai(np, dai_link->cpus, &is_single_links); + ret = asoc_simple_parse_dai(np, cpus, &is_single_links); if (ret) goto out_put_node; - ret = asoc_simple_parse_clk(dev, np, dai, dai_link->cpus); + ret = asoc_simple_parse_clk(dev, np, dai, cpus); if (ret < 0) goto out_put_node; @@ -177,11 +177,11 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->codec_dai; cconf = dai_props->codec_conf; - ret = asoc_simple_parse_dai(np, dai_link->codecs, NULL); + ret = asoc_simple_parse_dai(np, codecs, NULL); if (ret < 0) goto out_put_node; - ret = asoc_simple_parse_clk(dev, np, dai, dai_link->codecs); + ret = asoc_simple_parse_clk(dev, np, dai, codecs); if (ret < 0) goto out_put_node; @@ -233,6 +233,9 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct asoc_simple_dai *cpu_dai = dai_props->cpu_dai; struct asoc_simple_dai *codec_dai = dai_props->codec_dai; + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); struct device_node *top = dev->of_node; struct device_node *cpu = NULL; struct device_node *node = NULL; @@ -261,15 +264,15 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix); - ret = asoc_simple_parse_dai(cpu, dai_link->cpus, &single_cpu); + ret = asoc_simple_parse_dai(cpu, cpus, &single_cpu); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_dai(codec, dai_link->codecs, NULL); + ret = asoc_simple_parse_dai(codec, codecs, NULL); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_dai(plat, dai_link->platforms, NULL); + ret = asoc_simple_parse_dai(plat, platforms, NULL); if (ret < 0) goto dai_link_of_err; @@ -281,26 +284,26 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_clk(dev, cpu, cpu_dai, dai_link->cpus); + ret = asoc_simple_parse_clk(dev, cpu, cpu_dai, cpus); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_clk(dev, codec, codec_dai, dai_link->codecs); + ret = asoc_simple_parse_clk(dev, codec, codec_dai, codecs); if (ret < 0) goto dai_link_of_err; ret = asoc_simple_set_dailink_name(dev, dai_link, "%s-%s", - dai_link->cpus->dai_name, - dai_link->codecs->dai_name); + cpus->dai_name, + codecs->dai_name); if (ret < 0) goto dai_link_of_err; dai_link->ops = &simple_ops; dai_link->init = asoc_simple_dai_init; - asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu); - asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus); + asoc_simple_canonicalize_cpu(cpus, single_cpu); + asoc_simple_canonicalize_platform(platforms, cpus); dai_link_of_err: of_node_put(plat); From 2c33e20ffd68df097d61fad9b87dc6276354b139 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 14 Apr 2021 08:20:10 +0900 Subject: [PATCH 0995/1091] ASoC: simple-card: use simple_props_to_xxx() macro We shouldn't use dai_props->cpus/codecs directly, because these are array now to supporting multi CPU/Codec/Platform. This patch uses simple_props_to_xxx() macro for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87mtu1zs9i.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 9462b0d21486..5a686f82d1b4 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -147,7 +147,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - dai = dai_props->cpu_dai; + dai = simple_props_to_dai_cpu(dai_props, 0); ret = asoc_simple_parse_dai(np, cpus, &is_single_links); if (ret) @@ -174,8 +174,8 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; - dai = dai_props->codec_dai; - cconf = dai_props->codec_conf; + dai = simple_props_to_dai_codec(dai_props, 0); + cconf = simple_props_to_codec_conf(dai_props, 0); ret = asoc_simple_parse_dai(np, codecs, NULL); if (ret < 0) @@ -231,8 +231,8 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); - struct asoc_simple_dai *cpu_dai = dai_props->cpu_dai; - struct asoc_simple_dai *codec_dai = dai_props->codec_dai; + struct asoc_simple_dai *cpu_dai = simple_props_to_dai_cpu(dai_props, 0); + struct asoc_simple_dai *codec_dai = simple_props_to_dai_codec(dai_props, 0); struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); From 7ed5920995cea34d66e4af00c7f468cc933251cf Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 14 Apr 2021 08:20:15 +0900 Subject: [PATCH 0996/1091] ASoC: audio-graph: use asoc_link_to_xxx() macro We shouldn't use dai_link->cpus/codecs/platforms directly, because these are array now to supporting multi CPU/Codec/Platform. This patch uses asoc_link_to_xxx() macro for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87lf9lzs9c.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 33 +++++++++++++++------------- 1 file changed, 18 insertions(+), 15 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 0582fe296471..55384f1415b3 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -224,9 +224,9 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *ports; struct device_node *node; struct asoc_simple_dai *dai; - struct snd_soc_dai_link_component *cpus = dai_link->cpus; - struct snd_soc_dai_link_component *codecs = dai_link->codecs; - struct snd_soc_dai_link_component *platforms = dai_link->platforms; + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); int ret; port = of_get_parent(ep); @@ -248,11 +248,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->cpu_dai; - ret = asoc_simple_parse_dai(ep, dai_link->cpus, &is_single_links); + ret = asoc_simple_parse_dai(ep, cpus, &is_single_links); if (ret) goto out_put_node; - ret = asoc_simple_parse_clk(dev, ep, dai, dai_link->cpus); + ret = asoc_simple_parse_clk(dev, ep, dai, cpus); if (ret < 0) goto out_put_node; @@ -291,11 +291,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai = dai_props->codec_dai; cconf = dai_props->codec_conf; - ret = asoc_simple_parse_dai(ep, dai_link->codecs, NULL); + ret = asoc_simple_parse_dai(ep, codecs, NULL); if (ret < 0) goto out_put_node; - ret = asoc_simple_parse_clk(dev, ep, dai, dai_link->codecs); + ret = asoc_simple_parse_clk(dev, ep, dai, codecs); if (ret < 0) goto out_put_node; @@ -357,6 +357,9 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, struct device_node *top = dev->of_node; struct asoc_simple_dai *cpu_dai = dai_props->cpu_dai; struct asoc_simple_dai *codec_dai = dai_props->codec_dai; + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); int ret, single_cpu = 0; dev_dbg(dev, "link_of (%pOF)\n", cpu_ep); @@ -372,11 +375,11 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) return ret; - ret = asoc_simple_parse_dai(cpu_ep, dai_link->cpus, &single_cpu); + ret = asoc_simple_parse_dai(cpu_ep, cpus, &single_cpu); if (ret < 0) return ret; - ret = asoc_simple_parse_dai(codec_ep, dai_link->codecs, NULL); + ret = asoc_simple_parse_dai(codec_ep, codecs, NULL); if (ret < 0) return ret; @@ -388,26 +391,26 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) return ret; - ret = asoc_simple_parse_clk(dev, cpu_ep, cpu_dai, dai_link->cpus); + ret = asoc_simple_parse_clk(dev, cpu_ep, cpu_dai, cpus); if (ret < 0) return ret; - ret = asoc_simple_parse_clk(dev, codec_ep, codec_dai, dai_link->codecs); + ret = asoc_simple_parse_clk(dev, codec_ep, codec_dai, codecs); if (ret < 0) return ret; ret = asoc_simple_set_dailink_name(dev, dai_link, "%s-%s", - dai_link->cpus->dai_name, - dai_link->codecs->dai_name); + cpus->dai_name, + codecs->dai_name); if (ret < 0) return ret; dai_link->ops = &graph_ops; dai_link->init = asoc_simple_dai_init; - asoc_simple_canonicalize_cpu(dai_link->cpus, single_cpu); - asoc_simple_canonicalize_platform(dai_link->platforms, dai_link->cpus); + asoc_simple_canonicalize_cpu(cpus, single_cpu); + asoc_simple_canonicalize_platform(platforms, cpus); return 0; } From ae0727ab77419d550d6f68b698ce37ef2bf315df Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 14 Apr 2021 08:20:20 +0900 Subject: [PATCH 0997/1091] ASoC: audio-graph: use simple_props_to_xxx() macro We shouldn't use dai_props->cpus/codecs directly, because these are array now to supporting multi CPU/Codec/Platform. This patch uses simple_props_to_xxx() macro for it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87k0p5zs97.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 55384f1415b3..36b2ad7dd283 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -246,7 +246,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - dai = dai_props->cpu_dai; + dai = simple_props_to_dai_cpu(dai_props, 0); ret = asoc_simple_parse_dai(ep, cpus, &is_single_links); if (ret) @@ -288,8 +288,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; - dai = dai_props->codec_dai; - cconf = dai_props->codec_conf; + dai = simple_props_to_dai_codec(dai_props, 0); + cconf = simple_props_to_codec_conf(dai_props, 0); ret = asoc_simple_parse_dai(ep, codecs, NULL); if (ret < 0) @@ -355,8 +355,8 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct device_node *top = dev->of_node; - struct asoc_simple_dai *cpu_dai = dai_props->cpu_dai; - struct asoc_simple_dai *codec_dai = dai_props->codec_dai; + struct asoc_simple_dai *cpu_dai = simple_props_to_dai_cpu(dai_props, 0); + struct asoc_simple_dai *codec_dai = simple_props_to_dai_codec(dai_props, 0); struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); From 22ff9c4230bd09ade8971c05463b90ec1d513245 Mon Sep 17 00:00:00 2001 From: Guangqing Zhu Date: Thu, 15 Apr 2021 15:38:29 +0800 Subject: [PATCH 0998/1091] ASoC: codecs: wcd934x: Fix missing IRQF_ONESHOT as only threaded handler Coccinelle noticed: sound/soc/codecs/wcd934x.c:5041:7-32: ERROR: Threaded IRQ with no primary handler requested without IRQF_ONESHOT Signed-off-by: Guangqing Zhu Reviewed-by: Srinivas Kandagatla Link: https://lore.kernel.org/r/20210415073829.22750-1-zhuguangqing83@gmail.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index 5fe403307b72..cddc49bbb7f6 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -5040,7 +5040,7 @@ static int wcd934x_codec_probe(struct platform_device *pdev) ret = devm_request_threaded_irq(dev, irq, NULL, wcd934x_slim_irq_handler, - IRQF_TRIGGER_RISING, + IRQF_TRIGGER_RISING | IRQF_ONESHOT, "slim", wcd); if (ret) { dev_err(dev, "Failed to request slimbus irq\n"); From a523ef731ac6674dc07574f31bf44cc5bfa14e4d Mon Sep 17 00:00:00 2001 From: Lukasz Majczak Date: Thu, 15 Apr 2021 14:43:47 +0200 Subject: [PATCH 0999/1091] ASoC: Intel: kbl_da7219_max98927: Fix kabylake_ssp_fixup function kabylake_ssp_fixup function uses snd_soc_dpcm to identify the codecs DAIs. The HW parameters are changed based on the codec DAI of the stream. The earlier approach to get snd_soc_dpcm was using container_of() macro on snd_pcm_hw_params. The structures have been modified over time and snd_soc_dpcm does not have snd_pcm_hw_params as a reference but as a copy. This causes the current driver to crash when used. This patch changes the way snd_soc_dpcm is extracted. snd_soc_pcm_runtime holds 2 dpcm instances (one for playback and one for capture). 2 codecs on the SSP are dmic (capture) and speakers (playback). Based on the stream direction, snd_soc_dpcm is extracted from snd_soc_pcm_runtime. Tested for all use cases of the driver. Based on similar fix in kbl_rt5663_rt5514_max98927.c from Harsha Priya and Vamshi Krishna Gopal Cc: # 5.4+ Signed-off-by: Lukasz Majczak Acked-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210415124347.475432-1-lma@semihalf.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/kbl_da7219_max98927.c | 38 +++++++++++++++----- 1 file changed, 30 insertions(+), 8 deletions(-) diff --git a/sound/soc/intel/boards/kbl_da7219_max98927.c b/sound/soc/intel/boards/kbl_da7219_max98927.c index cc9a2509ace2..e0149cf6127d 100644 --- a/sound/soc/intel/boards/kbl_da7219_max98927.c +++ b/sound/soc/intel/boards/kbl_da7219_max98927.c @@ -282,11 +282,33 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, struct snd_interval *chan = hw_param_interval(params, SNDRV_PCM_HW_PARAM_CHANNELS); struct snd_mask *fmt = hw_param_mask(params, SNDRV_PCM_HW_PARAM_FORMAT); - struct snd_soc_dpcm *dpcm = container_of( - params, struct snd_soc_dpcm, hw_params); - struct snd_soc_dai_link *fe_dai_link = dpcm->fe->dai_link; - struct snd_soc_dai_link *be_dai_link = dpcm->be->dai_link; + struct snd_soc_dpcm *dpcm, *rtd_dpcm = NULL; + /* + * The following loop will be called only for playback stream + * In this platform, there is only one playback device on every SSP + */ + for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_PLAYBACK, dpcm) { + rtd_dpcm = dpcm; + break; + } + + /* + * This following loop will be called only for capture stream + * In this platform, there is only one capture device on every SSP + */ + for_each_dpcm_fe(rtd, SNDRV_PCM_STREAM_CAPTURE, dpcm) { + rtd_dpcm = dpcm; + break; + } + + if (!rtd_dpcm) + return -EINVAL; + + /* + * The above 2 loops are mutually exclusive based on the stream direction, + * thus rtd_dpcm variable will never be overwritten + */ /* * Topology for kblda7219m98373 & kblmax98373 supports only S24_LE, * where as kblda7219m98927 & kblmax98927 supports S16_LE by default. @@ -309,9 +331,9 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, /* * The ADSP will convert the FE rate to 48k, stereo, 24 bit */ - if (!strcmp(fe_dai_link->name, "Kbl Audio Port") || - !strcmp(fe_dai_link->name, "Kbl Audio Headset Playback") || - !strcmp(fe_dai_link->name, "Kbl Audio Capture Port")) { + if (!strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Port") || + !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Headset Playback") || + !strcmp(rtd_dpcm->fe->dai_link->name, "Kbl Audio Capture Port")) { rate->min = rate->max = 48000; chan->min = chan->max = 2; snd_mask_none(fmt); @@ -322,7 +344,7 @@ static int kabylake_ssp_fixup(struct snd_soc_pcm_runtime *rtd, * The speaker on the SSP0 supports S16_LE and not S24_LE. * thus changing the mask here */ - if (!strcmp(be_dai_link->name, "SSP0-Codec")) + if (!strcmp(rtd_dpcm->be->dai_link->name, "SSP0-Codec")) snd_mask_set_format(fmt, SNDRV_PCM_FORMAT_S16_LE); return 0; From eea1d18e9b2d959df908746b193f66dba3078473 Mon Sep 17 00:00:00 2001 From: Ranjani Sridharan Date: Thu, 15 Apr 2021 11:21:07 -0500 Subject: [PATCH 1000/1091] ASoC: SOF: use current DAI config during resume Recently, the sof_pcm_dai_link_fixup() function was updated to match SSP config with the PCM hw_params and set the current_config for the DAI widget. But the sof_restore_pipelines() function still chooses the default config for the DAI widget upon resuming. Fix this to use the last used config when setting up the DAI widget during resume. Fixes: c943a586f6e49 ("ASoC: SOF: match SSP config with pcm hw params") Reviewed-by: Kai Vehmanen Signed-off-by: Ranjani Sridharan Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210415162107.130963-1-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/sof/sof-audio.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/sof/sof-audio.c b/sound/soc/sof/sof-audio.c index 0d0d47dc0246..510883cd9107 100644 --- a/sound/soc/sof/sof-audio.c +++ b/sound/soc/sof/sof-audio.c @@ -267,7 +267,7 @@ int sof_restore_pipelines(struct device *dev) /* restore dai links */ list_for_each_entry_reverse(dai, &sdev->dai_list, list) { struct sof_ipc_reply reply; - struct sof_ipc_dai_config *config = dai->dai_config; + struct sof_ipc_dai_config *config = &dai->dai_config[dai->current_config]; if (!config) { dev_err(dev, "error: no config for DAI %s\n", From 22315a2296f4c251fa92aec45fbbae37e9301b6c Mon Sep 17 00:00:00 2001 From: Nathan Chancellor Date: Tue, 13 Apr 2021 17:08:04 -0700 Subject: [PATCH 1001/1091] arm64: alternatives: Move length validation in alternative_{insn, endif} After commit 2decad92f473 ("arm64: mte: Ensure TIF_MTE_ASYNC_FAULT is set atomically"), LLVM's integrated assembler fails to build entry.S: :5:7: error: expected assembly-time absolute expression .org . - (664b-663b) + (662b-661b) ^ :6:7: error: expected assembly-time absolute expression .org . - (662b-661b) + (664b-663b) ^ The root cause is LLVM's assembler has a one-pass design, meaning it cannot figure out these instruction lengths when the .org directive is outside of the subsection that they are in, which was changed by the .arch_extension directive added in the above commit. Apply the same fix from commit 966a0acce2fc ("arm64/alternatives: move length validation inside the subsection") to the alternative_endif macro, shuffling the .org directives so that the length validation happen will always happen in the same subsections. alternative_insn has not shown any issue yet but it appears that it could have the same issue in the future so just preemptively change it. Fixes: f7b93d42945c ("arm64/alternatives: use subsections for replacement sequences") Cc: # 5.8.x Link: https://github.com/ClangBuiltLinux/linux/issues/1347 Signed-off-by: Nathan Chancellor Reviewed-by: Sami Tolvanen Tested-by: Sami Tolvanen Reviewed-by: Nick Desaulniers Tested-by: Nick Desaulniers Link: https://lore.kernel.org/r/20210414000803.662534-1-nathan@kernel.org Signed-off-by: Catalin Marinas --- arch/arm64/include/asm/alternative-macros.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/arch/arm64/include/asm/alternative-macros.h b/arch/arm64/include/asm/alternative-macros.h index 5df500dcc627..8a078fc662ac 100644 --- a/arch/arm64/include/asm/alternative-macros.h +++ b/arch/arm64/include/asm/alternative-macros.h @@ -97,9 +97,9 @@ .popsection .subsection 1 663: \insn2 -664: .previous - .org . - (664b-663b) + (662b-661b) +664: .org . - (664b-663b) + (662b-661b) .org . - (662b-661b) + (664b-663b) + .previous .endif .endm @@ -169,11 +169,11 @@ */ .macro alternative_endif 664: + .org . - (664b-663b) + (662b-661b) + .org . - (662b-661b) + (664b-663b) .if .Lasm_alt_mode==0 .previous .endif - .org . - (664b-663b) + (662b-661b) - .org . - (662b-661b) + (664b-663b) .endm /* From 39930213e7779b9c4257499972b8afb8858f1a2d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Beh=C3=BAn?= Date: Thu, 8 Apr 2021 04:00:00 +0200 Subject: [PATCH 1002/1091] i2c: mv64xxx: Fix random system lock caused by runtime PM MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit I noticed a weird bug with this driver on Marvell CN9130 Customer Reference Board. Sometime after boot, the system locks with the following message: [104.071363] i2c i2c-0: mv64xxx: I2C bus locked, block: 1, time_left: 0 The system does not respond afterwards, only warns about RCU stalls. This first appeared with commit e5c02cf54154 ("i2c: mv64xxx: Add runtime PM support"). With further experimentation I discovered that adding a delay into mv64xxx_i2c_hw_init() fixes this issue. This function is called before every xfer, due to how runtime PM works in this driver. It seems that in order to work correctly, a delay is needed after the bus is reset in this function. Since there already is a known erratum with this controller needing a delay, I assume that this is just another place this needs to be applied. Therefore I apply the delay only if errata_delay is true. Signed-off-by: Marek Behún Acked-by: Gregory CLEMENT Reviewed-by: Samuel Holland Signed-off-by: Wolfram Sang --- drivers/i2c/busses/i2c-mv64xxx.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c index c590d36b5fd1..5c8e94b6cdb5 100644 --- a/drivers/i2c/busses/i2c-mv64xxx.c +++ b/drivers/i2c/busses/i2c-mv64xxx.c @@ -221,6 +221,10 @@ mv64xxx_i2c_hw_init(struct mv64xxx_i2c_data *drv_data) writel(0, drv_data->reg_base + drv_data->reg_offsets.ext_addr); writel(MV64XXX_I2C_REG_CONTROL_TWSIEN | MV64XXX_I2C_REG_CONTROL_STOP, drv_data->reg_base + drv_data->reg_offsets.control); + + if (drv_data->errata_delay) + udelay(5); + drv_data->state = MV64XXX_I2C_STATE_IDLE; } From 4e39a072a6a0fc422ba7da5e4336bdc295d70211 Mon Sep 17 00:00:00 2001 From: Jason Xing Date: Wed, 14 Apr 2021 10:34:28 +0800 Subject: [PATCH 1003/1091] i40e: fix the panic when running bpf in xdpdrv mode Fix this panic by adding more rules to calculate the value of @rss_size_max which could be used in allocating the queues when bpf is loaded, which, however, could cause the failure and then trigger the NULL pointer of vsi->rx_rings. Prio to this fix, the machine doesn't care about how many cpus are online and then allocates 256 queues on the machine with 32 cpus online actually. Once the load of bpf begins, the log will go like this "failed to get tracking for 256 queues for VSI 0 err -12" and this "setup of MAIN VSI failed". Thus, I attach the key information of the crash-log here. BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 RIP: 0010:i40e_xdp+0xdd/0x1b0 [i40e] Call Trace: [2160294.717292] ? i40e_reconfig_rss_queues+0x170/0x170 [i40e] [2160294.717666] dev_xdp_install+0x4f/0x70 [2160294.718036] dev_change_xdp_fd+0x11f/0x230 [2160294.718380] ? dev_disable_lro+0xe0/0xe0 [2160294.718705] do_setlink+0xac7/0xe70 [2160294.719035] ? __nla_parse+0xed/0x120 [2160294.719365] rtnl_newlink+0x73b/0x860 Fixes: 41c445ff0f48 ("i40e: main driver core") Co-developed-by: Shujin Li Signed-off-by: Shujin Li Signed-off-by: Jason Xing Reviewed-by: Jesse Brandeburg Acked-by: Jesper Dangaard Brouer Signed-off-by: David S. Miller --- drivers/net/ethernet/intel/i40e/i40e_main.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/intel/i40e/i40e_main.c b/drivers/net/ethernet/intel/i40e/i40e_main.c index 30ad7c08d0fb..527023ee4c07 100644 --- a/drivers/net/ethernet/intel/i40e/i40e_main.c +++ b/drivers/net/ethernet/intel/i40e/i40e_main.c @@ -12357,6 +12357,7 @@ static int i40e_sw_init(struct i40e_pf *pf) { int err = 0; int size; + u16 pow; /* Set default capability flags */ pf->flags = I40E_FLAG_RX_CSUM_ENABLED | @@ -12375,6 +12376,11 @@ static int i40e_sw_init(struct i40e_pf *pf) pf->rss_table_size = pf->hw.func_caps.rss_table_size; pf->rss_size_max = min_t(int, pf->rss_size_max, pf->hw.func_caps.num_tx_qp); + + /* find the next higher power-of-2 of num cpus */ + pow = roundup_pow_of_two(num_online_cpus()); + pf->rss_size_max = min_t(int, pf->rss_size_max, pow); + if (pf->hw.func_caps.rss) { pf->flags |= I40E_FLAG_RSS_ENABLED; pf->alloc_rss_size = min_t(int, pf->rss_size_max, From 1a73e427b824133940c2dd95ebe26b6dce1cbf10 Mon Sep 17 00:00:00 2001 From: Vinay Kumar Yadav Date: Thu, 15 Apr 2021 13:17:45 +0530 Subject: [PATCH 1004/1091] ch_ktls: Fix kernel panic Taking page refcount is not ideal and causes kernel panic sometimes. It's better to take tx_ctx lock for the complete skb transmit, to avoid page cleanup if ACK received in middle. Fixes: 5a4b9fe7fece ("cxgb4/chcr: complete record tx handling") Signed-off-by: Vinay Kumar Yadav Signed-off-by: Rohit Maheshwari Signed-off-by: David S. Miller --- .../chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 24 ++++--------------- 1 file changed, 5 insertions(+), 19 deletions(-) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c index 1115b8f9ea4e..e39fa0940367 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c @@ -2010,12 +2010,11 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev) * we will send the complete record again. */ + spin_lock_irqsave(&tx_ctx->base.lock, flags); + do { - int i; cxgb4_reclaim_completed_tx(adap, &q->q, true); - /* lock taken */ - spin_lock_irqsave(&tx_ctx->base.lock, flags); /* fetch the tls record */ record = tls_get_record(&tx_ctx->base, tcp_seq, &tx_info->record_no); @@ -2074,11 +2073,11 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev) tls_end_offset, skb_offset, 0); - spin_unlock_irqrestore(&tx_ctx->base.lock, flags); if (ret) { /* free the refcount taken earlier */ if (tls_end_offset < data_len) dev_kfree_skb_any(skb); + spin_unlock_irqrestore(&tx_ctx->base.lock, flags); goto out; } @@ -2088,16 +2087,6 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev) continue; } - /* increase page reference count of the record, so that there - * won't be any chance of page free in middle if in case stack - * receives ACK and try to delete the record. - */ - for (i = 0; i < record->num_frags; i++) - __skb_frag_ref(&record->frags[i]); - /* lock cleared */ - spin_unlock_irqrestore(&tx_ctx->base.lock, flags); - - /* if a tls record is finishing in this SKB */ if (tls_end_offset <= data_len) { ret = chcr_end_part_handler(tx_info, skb, record, @@ -2122,13 +2111,9 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev) data_len = 0; } - /* clear the frag ref count which increased locally before */ - for (i = 0; i < record->num_frags; i++) { - /* clear the frag ref count */ - __skb_frag_unref(&record->frags[i]); - } /* if any failure, come out from the loop. */ if (ret) { + spin_unlock_irqrestore(&tx_ctx->base.lock, flags); if (th->fin) dev_kfree_skb_any(skb); @@ -2143,6 +2128,7 @@ static int chcr_ktls_xmit(struct sk_buff *skb, struct net_device *dev) } while (data_len > 0); + spin_unlock_irqrestore(&tx_ctx->base.lock, flags); atomic64_inc(&port_stats->ktls_tx_encrypted_packets); atomic64_add(skb_data_len, &port_stats->ktls_tx_encrypted_bytes); From bc16efd2430652f894ae34b1de5eccc3bf0d2810 Mon Sep 17 00:00:00 2001 From: Vinay Kumar Yadav Date: Thu, 15 Apr 2021 13:17:46 +0530 Subject: [PATCH 1005/1091] ch_ktls: fix device connection close When sge queue is full and chcr_ktls_xmit_wr_complete() returns failure, skb is not freed if it is not the last tls record in this skb, causes refcount never gets freed and tls_dev_del() never gets called on this connection. Fixes: 5a4b9fe7fece ("cxgb4/chcr: complete record tx handling") Signed-off-by: Vinay Kumar Yadav Signed-off-by: Rohit Maheshwari Signed-off-by: David S. Miller --- .../net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c index e39fa0940367..a626560f8365 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c @@ -1735,7 +1735,9 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info, struct sge_eth_txq *q, u32 skb_offset, u32 tls_end_offset, bool last_wr) { + bool free_skb_if_tx_fails = false; struct sk_buff *nskb = NULL; + /* check if it is a complete record */ if (tls_end_offset == record->len) { nskb = skb; @@ -1758,6 +1760,8 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info, if (last_wr) dev_kfree_skb_any(skb); + else + free_skb_if_tx_fails = true; last_wr = true; @@ -1769,6 +1773,8 @@ static int chcr_end_part_handler(struct chcr_ktls_info *tx_info, record->num_frags, (last_wr && tcp_push_no_fin), mss)) { + if (free_skb_if_tx_fails) + dev_kfree_skb_any(skb); goto out; } tx_info->prev_seq = record->end_seq; From 21d8c25e3f4b9052a471ced8f47b531956eb9963 Mon Sep 17 00:00:00 2001 From: Vinay Kumar Yadav Date: Thu, 15 Apr 2021 13:17:47 +0530 Subject: [PATCH 1006/1091] ch_ktls: tcb close causes tls connection failure HW doesn't need marking TCB closed. This TCB state change sometimes causes problem to the new connection which gets the same tid. Fixes: 34aba2c45024 ("cxgb4/chcr : Register to tls add and del callback") Signed-off-by: Vinay Kumar Yadav Signed-off-by: Rohit Maheshwari Signed-off-by: David S. Miller --- .../chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 19 ------------------- 1 file changed, 19 deletions(-) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c index a626560f8365..8559eec161f0 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c @@ -349,18 +349,6 @@ static int chcr_set_tcb_field(struct chcr_ktls_info *tx_info, u16 word, return cxgb4_ofld_send(tx_info->netdev, skb); } -/* - * chcr_ktls_mark_tcb_close: mark tcb state to CLOSE - * @tx_info - driver specific tls info. - * return: NET_TX_OK/NET_XMIT_DROP. - */ -static int chcr_ktls_mark_tcb_close(struct chcr_ktls_info *tx_info) -{ - return chcr_set_tcb_field(tx_info, TCB_T_STATE_W, - TCB_T_STATE_V(TCB_T_STATE_M), - CHCR_TCB_STATE_CLOSED, 1); -} - /* * chcr_ktls_dev_del: call back for tls_dev_del. * Remove the tid and l2t entry and close the connection. @@ -395,8 +383,6 @@ static void chcr_ktls_dev_del(struct net_device *netdev, /* clear tid */ if (tx_info->tid != -1) { - /* clear tcb state and then release tid */ - chcr_ktls_mark_tcb_close(tx_info); cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan, tx_info->tid, tx_info->ip_family); } @@ -574,7 +560,6 @@ static int chcr_ktls_dev_add(struct net_device *netdev, struct sock *sk, return 0; free_tid: - chcr_ktls_mark_tcb_close(tx_info); #if IS_ENABLED(CONFIG_IPV6) /* clear clip entry */ if (tx_info->ip_family == AF_INET6) @@ -672,10 +657,6 @@ static int chcr_ktls_cpl_act_open_rpl(struct adapter *adap, if (tx_info->pending_close) { spin_unlock(&tx_info->lock); if (!status) { - /* it's a late success, tcb status is established, - * mark it close. - */ - chcr_ktls_mark_tcb_close(tx_info); cxgb4_remove_tid(&tx_info->adap->tids, tx_info->tx_chan, tid, tx_info->ip_family); } From e8a4155567b3c903f49cbf89b8017e9cc22c4fe4 Mon Sep 17 00:00:00 2001 From: Vinay Kumar Yadav Date: Thu, 15 Apr 2021 13:17:48 +0530 Subject: [PATCH 1007/1091] ch_ktls: do not send snd_una update to TCB in middle snd_una update should not be done when the same skb is being sent out.chcr_short_record_handler() sends it again even though SND_UNA update is already sent for the skb in chcr_ktls_xmit(), which causes mismatch in un-acked TCP seq number, later causes problem in sending out complete record. Fixes: 429765a149f1 ("chcr: handle partial end part of a record") Signed-off-by: Vinay Kumar Yadav Signed-off-by: Rohit Maheshwari Signed-off-by: David S. Miller --- .../chelsio/inline_crypto/ch_ktls/chcr_ktls.c | 53 ------------------- 1 file changed, 53 deletions(-) diff --git a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c index 8559eec161f0..a3f5b80888e5 100644 --- a/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c +++ b/drivers/net/ethernet/chelsio/inline_crypto/ch_ktls/chcr_ktls.c @@ -1644,54 +1644,6 @@ static void chcr_ktls_copy_record_in_skb(struct sk_buff *nskb, refcount_add(nskb->truesize, &nskb->sk->sk_wmem_alloc); } -/* - * chcr_ktls_update_snd_una: Reset the SEND_UNA. It will be done to avoid - * sending the same segment again. It will discard the segment which is before - * the current tx max. - * @tx_info - driver specific tls info. - * @q - TX queue. - * return: NET_TX_OK/NET_XMIT_DROP. - */ -static int chcr_ktls_update_snd_una(struct chcr_ktls_info *tx_info, - struct sge_eth_txq *q) -{ - struct fw_ulptx_wr *wr; - unsigned int ndesc; - int credits; - void *pos; - u32 len; - - len = sizeof(*wr) + roundup(CHCR_SET_TCB_FIELD_LEN, 16); - ndesc = DIV_ROUND_UP(len, 64); - - credits = chcr_txq_avail(&q->q) - ndesc; - if (unlikely(credits < 0)) { - chcr_eth_txq_stop(q); - return NETDEV_TX_BUSY; - } - - pos = &q->q.desc[q->q.pidx]; - - wr = pos; - /* ULPTX wr */ - wr->op_to_compl = htonl(FW_WR_OP_V(FW_ULPTX_WR)); - wr->cookie = 0; - /* fill len in wr field */ - wr->flowid_len16 = htonl(FW_WR_LEN16_V(DIV_ROUND_UP(len, 16))); - - pos += sizeof(*wr); - - pos = chcr_write_cpl_set_tcb_ulp(tx_info, q, tx_info->tid, pos, - TCB_SND_UNA_RAW_W, - TCB_SND_UNA_RAW_V(TCB_SND_UNA_RAW_M), - TCB_SND_UNA_RAW_V(0), 0); - - chcr_txq_advance(&q->q, ndesc); - cxgb4_ring_tx_db(tx_info->adap, &q->q, ndesc); - - return 0; -} - /* * chcr_end_part_handler: This handler will handle the record which * is complete or if record's end part is received. T6 adapter has a issue that @@ -1892,11 +1844,6 @@ static int chcr_short_record_handler(struct chcr_ktls_info *tx_info, /* reset tcp_seq as per the prior_data_required len */ tcp_seq -= prior_data_len; } - /* reset snd una, so the middle record won't send the already - * sent part. - */ - if (chcr_ktls_update_snd_una(tx_info, q)) - goto out; atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_middle_pkts); } else { atomic64_inc(&tx_info->adap->ch_ktls_stats.ktls_tx_start_pkts); From b21bb4cd1102dd9e24a169d09cf4e6f3c8a46bcf Mon Sep 17 00:00:00 2001 From: Ben Widawsky Date: Thu, 15 Apr 2021 16:26:08 -0700 Subject: [PATCH 1008/1091] cxl/mem: Fix register block offset calculation The "Register Offset Low" register of a "DVSEC Register Locator" contains the 64K aligned offset for the registers along with the BAR indicator and an id. The implementation was treating the "Register Block Offset Low" field a value rather than as a pre-aligned component of the 64-bit offset. So, just mask, don't mask and shift (FIELD_GET). The user visible result of this bug is that the driver fails to bind to the device after none of the required blocks are found. This was missed earlier because the primary development done in the QEMU environment only uses 0 offsets, i.e. 0 shifted is still 0. Fixes: 8adaf747c9f0 ("cxl/mem: Find device capabilities") Reported-by: Vishal Verma Signed-off-by: Ben Widawsky Link: https://lore.kernel.org/r/20210415232610.603273-1-ben.widawsky@intel.com Signed-off-by: Dan Williams --- drivers/cxl/mem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index e3003f49b329..1b5078311f7d 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -998,7 +998,7 @@ static struct cxl_mem *cxl_mem_create(struct pci_dev *pdev, u32 reg_lo, return NULL; } - offset = ((u64)reg_hi << 32) | FIELD_GET(CXL_REGLOC_ADDR_MASK, reg_lo); + offset = ((u64)reg_hi << 32) | (reg_lo & CXL_REGLOC_ADDR_MASK); bar = FIELD_GET(CXL_REGLOC_BIR_MASK, reg_lo); /* Basic sanity check that BAR is big enough */ From 199fc6b8dee7d6d50467a57e0dc7e3e1b7d59966 Mon Sep 17 00:00:00 2001 From: Kefeng Wang Date: Mon, 29 Mar 2021 11:13:07 +0800 Subject: [PATCH 1009/1091] riscv: Fix spelling mistake "SPARSEMEM" to "SPARSMEM" There is a spelling mistake when SPARSEMEM Kconfig copy. Fixes: a5406a7ff56e ("riscv: Correct SPARSEMEM configuration") Cc: stable@vger.kernel.org Signed-off-by: Kefeng Wang Signed-off-by: Palmer Dabbelt --- arch/riscv/Kconfig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/arch/riscv/Kconfig b/arch/riscv/Kconfig index 0d0cf67359cb..4515a10c5d22 100644 --- a/arch/riscv/Kconfig +++ b/arch/riscv/Kconfig @@ -153,7 +153,7 @@ config ARCH_FLATMEM_ENABLE config ARCH_SPARSEMEM_ENABLE def_bool y depends on MMU - select SPARSEMEM_STATIC if 32BIT && SPARSMEM + select SPARSEMEM_STATIC if 32BIT && SPARSEMEM select SPARSEMEM_VMEMMAP_ENABLE if 64BIT config ARCH_SELECT_MEMORY_MODEL From 2349a3b26e29b8d860466bafda2e02b4b87a9e40 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 30 Mar 2021 02:12:26 +0800 Subject: [PATCH 1010/1091] riscv: add do_page_fault and do_trap_break into the kprobes blacklist These two functions are used to implement the kprobes feature so they can't be kprobed. Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported") Cc: stable@vger.kernel.org Signed-off-by: Jisheng Zhang Reviewed-by: Masami Hiramatsu Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/traps.c | 1 + arch/riscv/mm/fault.c | 1 + 2 files changed, 2 insertions(+) diff --git a/arch/riscv/kernel/traps.c b/arch/riscv/kernel/traps.c index 0879b5df11b9..1357abf79570 100644 --- a/arch/riscv/kernel/traps.c +++ b/arch/riscv/kernel/traps.c @@ -178,6 +178,7 @@ asmlinkage __visible void do_trap_break(struct pt_regs *regs) else die(regs, "Kernel BUG"); } +NOKPROBE_SYMBOL(do_trap_break); #ifdef CONFIG_GENERIC_BUG int is_valid_bugaddr(unsigned long pc) diff --git a/arch/riscv/mm/fault.c b/arch/riscv/mm/fault.c index 8f17519208c7..c5dbd55cbf7c 100644 --- a/arch/riscv/mm/fault.c +++ b/arch/riscv/mm/fault.c @@ -328,3 +328,4 @@ good_area: } return; } +NOKPROBE_SYMBOL(do_page_fault); From e31be8d343e64e7ab17aef55c1d1b36dc504da67 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 30 Mar 2021 02:14:40 +0800 Subject: [PATCH 1011/1091] riscv: kprobes/ftrace: Add recursion protection to the ftrace callback Currently, the riscv's kprobes(powerred by ftrace) handler is preemptible. Futher check indicates we miss something similar as the commit c536aa1c5b17 ("kprobes/ftrace: Add recursion protection to the ftrace callback"), so do similar modifications as the commit does. Fixes: 829adda597fe ("riscv: Add KPROBES_ON_FTRACE supported") Cc: stable@vger.kernel.org Signed-off-by: Jisheng Zhang Reviewed-by: Steven Rostedt (VMware) Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/probes/ftrace.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/arch/riscv/kernel/probes/ftrace.c b/arch/riscv/kernel/probes/ftrace.c index 17ca5e923bb0..aab85a82f419 100644 --- a/arch/riscv/kernel/probes/ftrace.c +++ b/arch/riscv/kernel/probes/ftrace.c @@ -9,10 +9,16 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, struct kprobe *p; struct pt_regs *regs; struct kprobe_ctlblk *kcb; + int bit; + bit = ftrace_test_recursion_trylock(ip, parent_ip); + if (bit < 0) + return; + + preempt_disable_notrace(); p = get_kprobe((kprobe_opcode_t *)ip); if (unlikely(!p) || kprobe_disabled(p)) - return; + goto out; regs = ftrace_get_regs(fregs); kcb = get_kprobe_ctlblk(); @@ -45,6 +51,9 @@ void kprobe_ftrace_handler(unsigned long ip, unsigned long parent_ip, */ __this_cpu_write(current_kprobe, NULL); } +out: + preempt_enable_notrace(); + ftrace_test_recursion_unlock(bit); } NOKPROBE_SYMBOL(kprobe_ftrace_handler); From 7ae11635ec90072083503c6b6485cdffe46203b3 Mon Sep 17 00:00:00 2001 From: Jisheng Zhang Date: Tue, 30 Mar 2021 02:16:24 +0800 Subject: [PATCH 1012/1091] riscv: keep interrupts disabled for BREAKPOINT exception Current riscv's kprobe handlers are run with both preemption and interrupt enabled, this violates kprobe requirements. Fix this issue by keeping interrupts disabled for BREAKPOINT exception. Fixes: c22b0bcb1dd0 ("riscv: Add kprobes supported") Cc: stable@vger.kernel.org Signed-off-by: Jisheng Zhang Reviewed-by: Masami Hiramatsu [Palmer: add a comment] Signed-off-by: Palmer Dabbelt --- arch/riscv/kernel/entry.S | 3 +++ 1 file changed, 3 insertions(+) diff --git a/arch/riscv/kernel/entry.S b/arch/riscv/kernel/entry.S index 76274a4a1d8e..83095faa680e 100644 --- a/arch/riscv/kernel/entry.S +++ b/arch/riscv/kernel/entry.S @@ -130,6 +130,9 @@ skip_context_tracking: */ andi t0, s1, SR_PIE beqz t0, 1f + /* kprobes, entered via ebreak, must have interrupts disabled. */ + li t0, EXC_BREAKPOINT + beq s4, t0, 1f #ifdef CONFIG_TRACE_IRQFLAGS call trace_hardirqs_on #endif From 093b9dcb597611ce65f8c5610ee446616c0be304 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 15 Apr 2021 12:50:05 -0500 Subject: [PATCH 1013/1091] ASoC: Intel: soc-acpi: add ADL SoundWire base configurations Add configurations ported over from TGL. The topology names need to include link information given all the hardware permutations. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Libin Yang Link: https://lore.kernel.org/r/20210415175013.192862-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-adl-match.c | 185 ++++++++++++++++++ 1 file changed, 185 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index 0aca340ebc25..d935745322b6 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -15,6 +15,20 @@ static const struct snd_soc_acpi_endpoint single_endpoint = { .group_id = 0, }; +static const struct snd_soc_acpi_endpoint spk_l_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 0, + .group_id = 1, +}; + +static const struct snd_soc_acpi_endpoint spk_r_endpoint = { + .num = 0, + .aggregated = 1, + .group_position = 1, + .group_id = 1, +}; + static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { { .adr = 0x000020025D071100, @@ -24,6 +38,159 @@ static const struct snd_soc_acpi_adr_device rt711_0_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1308_1_group1_adr[] = { + { + .adr = 0x000120025D130800, + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "rt1308-1" + } +}; + +static const struct snd_soc_acpi_adr_device rt1308_2_group1_adr[] = { + { + .adr = 0x000220025D130800, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1308-2" + } +}; + +static const struct snd_soc_acpi_adr_device rt715_3_adr[] = { + { + .adr = 0x000320025D071500, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt715" + } +}; + +static const struct snd_soc_acpi_adr_device rt711_sdca_0_adr[] = { + { + .adr = 0x000030025D071101, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt711" + } +}; + +static const struct snd_soc_acpi_adr_device rt1316_1_group1_adr[] = { + { + .adr = 0x000131025D131601, /* unique ID is set for some reason */ + .num_endpoints = 1, + .endpoints = &spk_l_endpoint, + .name_prefix = "rt1316-1" + } +}; + +static const struct snd_soc_acpi_adr_device rt1316_2_group1_adr[] = { + { + .adr = 0x000230025D131601, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1316-2" + } +}; + +static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = { + { + .adr = 0x000330025D131601, + .num_endpoints = 1, + .endpoints = &spk_r_endpoint, + .name_prefix = "rt1316-2" + } +}; + +static const struct snd_soc_acpi_adr_device rt714_2_adr[] = { + { + .adr = 0x000230025D071401, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt714" + } +}; + +static const struct snd_soc_acpi_adr_device rt714_3_adr[] = { + { + .adr = 0x000330025D071401, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt714" + } +}; + +static const struct snd_soc_acpi_link_adr adl_default[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_0_adr), + .adr_d = rt711_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1308_1_group1_adr), + .adr_d = rt1308_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1308_2_group1_adr), + .adr_d = rt1308_2_group1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt715_3_adr), + .adr_d = rt715_3_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr adl_sdca_default[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1316_1_group1_adr), + .adr_d = rt1316_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1316_2_group1_adr), + .adr_d = rt1316_2_group1_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt714_3_adr), + .adr_d = rt714_3_adr, + }, + {} +}; + +static const struct snd_soc_acpi_link_adr adl_sdca_3_in_1[] = { + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt711_sdca_0_adr), + .adr_d = rt711_sdca_0_adr, + }, + { + .mask = BIT(1), + .num_adr = ARRAY_SIZE(rt1316_1_group1_adr), + .adr_d = rt1316_1_group1_adr, + }, + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt714_2_adr), + .adr_d = rt714_2_adr, + }, + { + .mask = BIT(3), + .num_adr = ARRAY_SIZE(rt1316_3_group1_adr), + .adr_d = rt1316_3_group1_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr adl_rvp[] = { { .mask = BIT(0), @@ -40,6 +207,24 @@ EXPORT_SYMBOL_GPL(snd_soc_acpi_intel_adl_machines); /* this table is used when there is no I2S codec present */ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { + { + .link_mask = 0xF, /* 4 active links required */ + .links = adl_default, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt711-l0-rt1308-l12-rt715-l3.tplg", + }, + { + .link_mask = 0xF, /* 4 active links required */ + .links = adl_sdca_default, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l12-rt714-l3.tplg", + }, + { + .link_mask = 0xF, /* 4 active links required */ + .links = adl_sdca_3_in_1, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l13-rt714-l2.tplg", + }, { .link_mask = 0x1, /* link0 required */ .links = adl_rvp, From 870dc42fe8311ef5b291ccb21eda3f7069b6f599 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Thu, 15 Apr 2021 12:50:06 -0500 Subject: [PATCH 1014/1091] ASoC: Intel: soc-acpi: add ADL jack-less SoundWire configurations Add one configuration with no RT711. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Rander Wang Reviewed-by: Libin Yang Link: https://lore.kernel.org/r/20210415175013.192862-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- .../intel/common/soc-acpi-intel-adl-match.c | 38 +++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/sound/soc/intel/common/soc-acpi-intel-adl-match.c b/sound/soc/intel/common/soc-acpi-intel-adl-match.c index d935745322b6..692c4c479ed8 100644 --- a/sound/soc/intel/common/soc-acpi-intel-adl-match.c +++ b/sound/soc/intel/common/soc-acpi-intel-adl-match.c @@ -101,6 +101,24 @@ static const struct snd_soc_acpi_adr_device rt1316_3_group1_adr[] = { } }; +static const struct snd_soc_acpi_adr_device rt1316_2_single_adr[] = { + { + .adr = 0x000230025D131601, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt1316-1" + } +}; + +static const struct snd_soc_acpi_adr_device rt714_0_adr[] = { + { + .adr = 0x000030025D071401, + .num_endpoints = 1, + .endpoints = &single_endpoint, + .name_prefix = "rt714" + } +}; + static const struct snd_soc_acpi_adr_device rt714_2_adr[] = { { .adr = 0x000230025D071401, @@ -191,6 +209,20 @@ static const struct snd_soc_acpi_link_adr adl_sdca_3_in_1[] = { {} }; +static const struct snd_soc_acpi_link_adr adl_sdw_rt1316_link2_rt714_link0[] = { + { + .mask = BIT(2), + .num_adr = ARRAY_SIZE(rt1316_2_single_adr), + .adr_d = rt1316_2_single_adr, + }, + { + .mask = BIT(0), + .num_adr = ARRAY_SIZE(rt714_0_adr), + .adr_d = rt714_0_adr, + }, + {} +}; + static const struct snd_soc_acpi_link_adr adl_rvp[] = { { .mask = BIT(0), @@ -225,6 +257,12 @@ struct snd_soc_acpi_mach snd_soc_acpi_intel_adl_sdw_machines[] = { .drv_name = "sof_sdw", .sof_tplg_filename = "sof-adl-rt711-l0-rt1316-l13-rt714-l2.tplg", }, + { + .link_mask = 0x5, /* 2 active links required */ + .links = adl_sdw_rt1316_link2_rt714_link0, + .drv_name = "sof_sdw", + .sof_tplg_filename = "sof-adl-rt1316-l2-mono-rt714-l0.tplg", + }, { .link_mask = 0x1, /* link0 required */ .links = adl_rvp, From d25bbe80485f8bcbbeb91a2a6cd8798c124b27b7 Mon Sep 17 00:00:00 2001 From: Vamshi Krishna Gopal Date: Thu, 15 Apr 2021 12:50:09 -0500 Subject: [PATCH 1015/1091] ASoC: Intel: sof_sdw: add quirk for new ADL-P Rvp Add quirks for jack detection, rt711 DAI and DMIC Reviewed-by: Bard Liao Reviewed-by: Kai Vehmanen Signed-off-by: Vamshi Krishna Gopal Signed-off-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210415175013.192862-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/intel/boards/sof_sdw.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sound/soc/intel/boards/sof_sdw.c b/sound/soc/intel/boards/sof_sdw.c index 8adce6417b02..ecd3f90f4bbe 100644 --- a/sound/soc/intel/boards/sof_sdw.c +++ b/sound/soc/intel/boards/sof_sdw.c @@ -187,6 +187,17 @@ static const struct dmi_system_id sof_sdw_quirk_table[] = { SOF_RT715_DAI_ID_FIX | SOF_SDW_FOUR_SPK), }, + /* AlderLake devices */ + { + .callback = sof_sdw_quirk_cb, + .matches = { + DMI_MATCH(DMI_SYS_VENDOR, "Intel Corporation"), + DMI_MATCH(DMI_PRODUCT_NAME, "Alder Lake Client Platform"), + }, + .driver_data = (void *)(SOF_RT711_JD_SRC_JD1 | + SOF_SDW_TGL_HDMI | + SOF_SDW_PCH_DMIC), + }, {} }; From d97140033948363ffdf5ed71dd2366f717e120e7 Mon Sep 17 00:00:00 2001 From: Daniel Baluta Date: Wed, 14 Apr 2021 13:12:12 +0300 Subject: [PATCH 1016/1091] ASoC: core: Don't set platform name when of_node is set A DAI link has 3 components: * CPU * platform * codec(s) A component is specified via: * name * of_node * dai_name In order to avoid confusion when building a sound card we disallow matching by both name and of_node (1). soc_check_tplg_fes allows overriding certain BE links by overriding BE link name. This doesn't work well if BE link was specified via DT, because we end up with a link with both name and of_node specified which is conflicting with (1). In order to fix this we need to: * override of_node if component was specified via DT * override name, otherwise. Signed-off-by: Daniel Baluta Link: https://lore.kernel.org/r/20210414101212.65573-1-daniel.baluta@oss.nxp.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 236e075b9e57..56bda3b9f691 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1658,7 +1658,11 @@ match: dev_err(card->dev, "init platform error"); continue; } - dai_link->platforms->name = component->name; + + if (component->dev->of_node) + dai_link->platforms->of_node = component->dev->of_node; + else + dai_link->platforms->name = component->name; /* convert non BE into BE */ if (!dai_link->no_pcm) { From 1cacbac447d9b29a4057d7bbffe8c3d4125ec82a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 16 Apr 2021 10:59:48 +0900 Subject: [PATCH 1017/1091] ASoC: soc-pcm: don't use "name" on __soc_pcm_params_symmetry() macro __soc_pcm_params_symmetry() macro is using "name" as parameter which will be exchanged to rate/channles/sample_bit, like below dai->name => dai->rate dai->name => dai->channels dai->name => dai->sample_bit But, dai itself has "name". This means 1) It is very confusable naming 2) It can't use dai->name This patch use "xxx" instead of "name" Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/8735vryoob.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 02968a4e52b4..a3fc27fc156f 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -386,16 +386,16 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, soc_pcm_set_dai_params(&d, params); -#define __soc_pcm_params_symmetry(name) \ - symmetry = rtd->dai_link->symmetric_##name; \ +#define __soc_pcm_params_symmetry(xxx) \ + symmetry = rtd->dai_link->symmetric_##xxx; \ for_each_rtd_dais(rtd, i, dai) \ - symmetry |= dai->driver->symmetric_##name; \ + symmetry |= dai->driver->symmetric_##xxx; \ \ if (symmetry) \ for_each_rtd_cpu_dais(rtd, i, cpu_dai) \ - if (cpu_dai->name && cpu_dai->name != d.name) { \ + if (cpu_dai->xxx && cpu_dai->xxx != d.xxx) { \ dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %d - %d\n", \ - #name, cpu_dai->name, d.name); \ + #xxx, cpu_dai->xxx, d.xxx); \ return -EINVAL; \ } From ee39d77ed91f220b1458137118dea158a095d5c5 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 16 Apr 2021 11:00:11 +0900 Subject: [PATCH 1018/1091] ASoC: soc-pcm: indicate DAI name if soc_pcm_params_symmetry() failed It indicates unmatched symmetry value, but not indicates on which DAI. This patch indicates it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/871rbbyono.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index a3fc27fc156f..72a797b2d1a7 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -384,6 +384,7 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, struct snd_soc_dai *cpu_dai; unsigned int symmetry, i; + d.name = __func__; soc_pcm_set_dai_params(&d, params); #define __soc_pcm_params_symmetry(xxx) \ @@ -394,8 +395,8 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, if (symmetry) \ for_each_rtd_cpu_dais(rtd, i, cpu_dai) \ if (cpu_dai->xxx && cpu_dai->xxx != d.xxx) { \ - dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %d - %d\n", \ - #xxx, cpu_dai->xxx, d.xxx); \ + dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \ + #xxx, cpu_dai->name, cpu_dai->xxx, d.name, d.xxx); \ return -EINVAL; \ } From 8f1a16818a08047c83bc6e29efc07b15fd11fa29 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 16 Apr 2021 11:00:26 +0900 Subject: [PATCH 1019/1091] ASoC: soc-utils: add snd_soc_component_is_dummy() There is snd_soc_dai_is_dummy(), but not for component. This patch adds it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zgxzxa2t.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/soc-component.h | 1 + sound/soc/soc-core.c | 2 +- sound/soc/soc-utils.c | 6 ++++++ 3 files changed, 8 insertions(+), 1 deletion(-) diff --git a/include/sound/soc-component.h b/include/sound/soc-component.h index 722cfab28d29..8c4d6830597f 100644 --- a/include/sound/soc-component.h +++ b/include/sound/soc-component.h @@ -338,6 +338,7 @@ static inline int snd_soc_component_cache_sync( void snd_soc_component_set_aux(struct snd_soc_component *component, struct snd_soc_aux_dev *aux); int snd_soc_component_init(struct snd_soc_component *component); +int snd_soc_component_is_dummy(struct snd_soc_component *component); /* component IO */ unsigned int snd_soc_component_read(struct snd_soc_component *component, diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 236e075b9e57..762fb5c23f21 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -1169,7 +1169,7 @@ static int soc_probe_component(struct snd_soc_card *card, int probed = 0; int ret; - if (!strcmp(component->name, "snd-soc-dummy")) + if (snd_soc_component_is_dummy(component)) return 0; if (component->card) { diff --git a/sound/soc/soc-utils.c b/sound/soc/soc-utils.c index f27f94ca064b..98383fd76224 100644 --- a/sound/soc/soc-utils.c +++ b/sound/soc/soc-utils.c @@ -131,6 +131,12 @@ int snd_soc_dai_is_dummy(struct snd_soc_dai *dai) return 0; } +int snd_soc_component_is_dummy(struct snd_soc_component *component) +{ + return ((component->driver == &dummy_platform) || + (component->driver == &dummy_codec)); +} + static int snd_soc_dummy_probe(struct platform_device *pdev) { int ret; From 9c2ae363f3347baacd2353a017eb62363420a1ea Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Fri, 16 Apr 2021 11:00:32 +0900 Subject: [PATCH 1020/1091] ASoC: soc-pcm: ignore dummy-DAI at soc_pcm_params_symmetry() soc_pcm_params_symmetry() checks CPU / Codec symmetry. Unfortunately there was bug on it (= A) which didn't check Codec. But is back by (B). A: v5.7: commit c840f7698d26 ("ASoC: soc-pcm: Merge for_each_rtd_cpu/codec_dais()") B: v5.12: commit 3a9067211122 ("ASoC: soc-pcm: cleanup soc_pcm_params_symmetry()") In total, old - v5.6 (= Generation-1): symmetric_rate : DAI_Link / CPU / Codec symmetric_channels : DAI_Link / CPU / Codec symmetric_sample_bits : DAI_Link / CPU / Codec v5.7 - v5.11 (= Generation-2): (= because of bug by (A)) symmetric_rate : DAI_Link / CPU symmetric_channels : DAI_Link / CPU / Codec symmetric_sample_bits : DAI_Link / CPU / Codec v5.12 - (= Generation-3): (= back by (B)) symmetric_rate : DAI_Link / CPU / Codec symmetric_channels : DAI_Link / CPU / Codec symmetric_sample_bits : DAI_Link / CPU / Codec OTOH, we can use DPCM which is configured by FE / BE. Both FE / BE uses dummy-DAI. FE: CPU <-> dummy-DAI BE: dummy-DAI <-> Codec One note is that we can use .be_hw_params_fixup in DPCM case. This means BE settings might be fixuped/updated by FE. This feature is used for example on MIXer case. It can be happen not only for rate, but for channels/sample_bits too. Because of these reasons, below issue happen on Generation-1 / Generation-3, if... 1) Sound Card used DPCM 2) It exchanges rate to 48kHz by using .be_hw_params_fixup() 3) Codec had symmetric_rate = 1 I didn't confirm, but maybe same things happen if it exchanged channels/sample_bits at Generation-1/2/3 too. # aplay 44100.wav # aplay 44100.wav => [kernel] be.ak4613-hifi: ASoC: unmatched rate symmetry: snd-soc-dummy-dai:44100 - soc_pcm_params_symmetry:48000 [kernel] be.ak4613-hifi: ASoC: hw_params BE failed -22 [kernel] fe.rsnd-dai.0: ASoC: hw_params BE failed -22 aplay: set_params:1407: Unable to install hw params: ACCESS: RW_INTERLEAVED FORMAT: S16_LE SUBFORMAT: STD SAMPLE_BITS: 16 FRAME_BITS: 32 CHANNELS: 2 RATE: 44100 PERIOD_TIME: (23219 23220) PERIOD_SIZE: 1024 PERIOD_BYTES: 4096 PERIODS: 4 BUFFER_TIME: (92879 92880) BUFFER_SIZE: 4096 BUFFER_BYTES: 16384 TICK_TIME: 0 soc_pcm_params_symmetry() checks by below if (symmetry) for_each_rtd_cpu_dais(rtd, i, cpu_dai) if (cpu_dai->xxx && cpu_dai->xxx != d.xxx) { dev_err(rtd->dev, "..."); return -EINVAL; } Because of above reason 3) (= Codec had symmetric_rate = 1) BE can't ignore "if (symmetric)". At 1st aplay, soc_pcm_params_symmetry() ignores it, because dummy-DAI->rate is 0. After this check, each DAI sets/keep settings. In above sample case, BE gets 48000 and FE gets 44100, and it happen BE -> FE order. Because DPCM is sharing *same* dummy-DAI, dummy-DAI sets as 48000 by BE, and is overwrote by 44100 by FE. This settings never be cleaned (= a) after 1st aplay, because dummy-DAI is used from FE/BE, never be last user (b). static int soc_pcm_hw_clean(...) { ... for_each_rtd_dais(rtd, i, dai) { ... (b) if (snd_soc_dai_active(dai) == 1) (a) soc_pcm_set_dai_params(dai, NULL); ... } ... } At 2nd aplay, BE gets 48000 but dummy-DAI is keeping 44100, soc_pcm_params_symmetry() checks will fail. To solve this issue, this patch ignores dummy-DAI at soc_pcm_params_symmetry() Link: https://lore.kernel.org/r/87a6q0z4xt.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y2djxa2n.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/soc-pcm.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/soc-pcm.c b/sound/soc/soc-pcm.c index 72a797b2d1a7..8659089a87a0 100644 --- a/sound/soc/soc-pcm.c +++ b/sound/soc/soc-pcm.c @@ -394,7 +394,8 @@ static int soc_pcm_params_symmetry(struct snd_pcm_substream *substream, \ if (symmetry) \ for_each_rtd_cpu_dais(rtd, i, cpu_dai) \ - if (cpu_dai->xxx && cpu_dai->xxx != d.xxx) { \ + if (!snd_soc_dai_is_dummy(cpu_dai) && \ + cpu_dai->xxx && cpu_dai->xxx != d.xxx) { \ dev_err(rtd->dev, "ASoC: unmatched %s symmetry: %s:%d - %s:%d\n", \ #xxx, cpu_dai->name, cpu_dai->xxx, d.name, d.xxx); \ return -EINVAL; \ From 0f687d826736a5b4eee03170382fe54d413b912a Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 16 Apr 2021 09:11:46 +0200 Subject: [PATCH 1021/1091] ASoC: simple-card-utils: Propagate errors on too many links The DAI counting code doesn't propagate errors when the number of maximum links is exceeded, which causes subsequent initialization code to continue to run and that eventually leads to memory corruption with the code trying to access memory that is out of bounds. Fix this by propagating errors when the maximum number of links is reached, which ensures that the driver fails to load and prevents the memory corruption. Fixes: f2138aed231c ("ASoC: simple-card-utils: enable flexible CPU/Codec/Platform") Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20210416071147.2149109-1-thierry.reding@gmail.com Reviewed-by: Jon Hunter Tested-by: Jon Hunter Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 19 +++++++++++-------- sound/soc/generic/simple-card.c | 17 ++++++++++------- 2 files changed, 21 insertions(+), 15 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 36b2ad7dd283..080c1a22bfc2 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -542,8 +542,8 @@ static int graph_for_each_link(struct asoc_simple_priv *priv, return ret; } -static void graph_get_dais_count(struct asoc_simple_priv *priv, - struct link_info *li); +static int graph_get_dais_count(struct asoc_simple_priv *priv, + struct link_info *li); int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) { @@ -555,7 +555,10 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) card->dev = dev; memset(&li, 0, sizeof(li)); - graph_get_dais_count(priv, &li); + ret = graph_get_dais_count(priv, &li); + if (ret < 0) + return ret; + if (!li.link) return -EINVAL; @@ -660,8 +663,8 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, return 0; } -static void graph_get_dais_count(struct asoc_simple_priv *priv, - struct link_info *li) +static int graph_get_dais_count(struct asoc_simple_priv *priv, + struct link_info *li) { /* * link_num : number of links. @@ -709,9 +712,9 @@ static void graph_get_dais_count(struct asoc_simple_priv *priv, * => 4 DAIs = 2xCPU + 2xCodec * => 1 ccnf = 1xdummy-Codec */ - graph_for_each_link(priv, li, - graph_count_noml, - graph_count_dpcm); + return graph_for_each_link(priv, li, + graph_count_noml, + graph_count_dpcm); } int audio_graph_card_probe(struct snd_soc_card *card) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 5a686f82d1b4..e05539b5f997 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -524,8 +524,8 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, return 0; } -static void simple_get_dais_count(struct asoc_simple_priv *priv, - struct link_info *li) +static int simple_get_dais_count(struct asoc_simple_priv *priv, + struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); struct device_node *top = dev->of_node; @@ -582,12 +582,12 @@ static void simple_get_dais_count(struct asoc_simple_priv *priv, li->num[0].platforms = 1; li->link = 1; - return; + return 0; } - simple_for_each_link(priv, li, - simple_count_noml, - simple_count_dpcm); + return simple_for_each_link(priv, li, + simple_count_noml, + simple_count_dpcm); } static int simple_soc_probe(struct snd_soc_card *card) @@ -626,7 +626,10 @@ static int asoc_simple_probe(struct platform_device *pdev) card->probe = simple_soc_probe; memset(&li, 0, sizeof(li)); - simple_get_dais_count(priv, &li); + ret = simple_get_dais_count(priv, &li); + if (ret < 0) + return ret; + if (!li.link) return -EINVAL; From 343e55e71877415a23372388b3e0c59a9bba42f6 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Fri, 16 Apr 2021 09:11:47 +0200 Subject: [PATCH 1022/1091] ASoC: simple-card-utils: Increase maximum number of links to 128 On Tegra186 and later, the number of links can go up to 72, so bump the maximum number of links to the next power of two (128). Fixes: f2138aed231c ("ASoC: simple-card-utils: enable flexible CPU/Codec/Platform") Signed-off-by: Thierry Reding Link: https://lore.kernel.org/r/20210416071147.2149109-2-thierry.reding@gmail.com Reviewed-by: Jon Hunter Tested-by: Jon Hunter Signed-off-by: Mark Brown --- include/sound/simple_card_utils.h | 4 +++- sound/soc/generic/audio-graph-card.c | 4 ++-- sound/soc/generic/simple-card.c | 4 ++-- 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index fac3b832d982..e318a2d4ac44 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -115,10 +115,12 @@ struct asoc_simple_priv { ((codec) = simple_props_to_dai_codec(props, i)); \ (i)++) +#define SNDRV_MAX_LINKS 128 + struct link_info { int link; /* number of link */ int cpu; /* turn for CPU / Codec */ - struct prop_nums num[SNDRV_MINOR_DEVICES]; + struct prop_nums num[SNDRV_MAX_LINKS]; }; int asoc_simple_parse_daifmt(struct device *dev, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 080c1a22bfc2..c7369beee805 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -619,7 +619,7 @@ static int graph_count_noml(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); - if (li->link >= SNDRV_MINOR_DEVICES) { + if (li->link >= SNDRV_MAX_LINKS) { dev_err(dev, "too many links\n"); return -EINVAL; } @@ -642,7 +642,7 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); - if (li->link >= SNDRV_MINOR_DEVICES) { + if (li->link >= SNDRV_MAX_LINKS) { dev_err(dev, "too many links\n"); return -EINVAL; } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index e05539b5f997..8b9964d25757 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -482,7 +482,7 @@ static int simple_count_noml(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - if (li->link >= SNDRV_MINOR_DEVICES) { + if (li->link >= SNDRV_MAX_LINKS) { struct device *dev = simple_priv_to_dev(priv); dev_err(dev, "too many links\n"); @@ -503,7 +503,7 @@ static int simple_count_dpcm(struct asoc_simple_priv *priv, struct device_node *codec, struct link_info *li, bool is_top) { - if (li->link >= SNDRV_MINOR_DEVICES) { + if (li->link >= SNDRV_MAX_LINKS) { struct device *dev = simple_priv_to_dev(priv); dev_err(dev, "too many links\n"); From a48f928e13a01d60c9c2a7a7ffab3afd1f7337bf Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 29 Mar 2021 06:54:05 +0000 Subject: [PATCH 1023/1091] ASoC: rt715: modification for code simplicity Modification for code simplicity. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/340ee2df83ce47fcb1b59541b12ba7f4@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index f419d001a3fb..0f78ffbb03fd 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -57,14 +57,14 @@ static void rt715_get_gain(struct rt715_priv *rt715, unsigned int addr_h, { int ret; /* R Channel */ - *r_val = (val_h << 8); + *r_val = val_h << 8; ret = regmap_read(rt715->regmap, addr_l, r_val); if (ret < 0) pr_err("Failed to get R channel gain.\n"); /* L Channel */ val_h |= 0x20; - *l_val = (val_h << 8); + *l_val = val_h << 8; ret = regmap_read(rt715->regmap, addr_h, l_val); if (ret < 0) pr_err("Failed to get L channel gain.\n"); @@ -188,8 +188,8 @@ static int rt715_set_amp_gain_get(struct snd_kcontrol *kcontrol, if (mc->invert) { /* for mute status */ - read_ll = !((read_ll & 0x80) >> RT715_MUTE_SFT); - read_rl = !((read_rl & 0x80) >> RT715_MUTE_SFT); + read_ll = !(read_ll & 0x80); + read_rl = !(read_rl & 0x80); } else { /* for gain */ read_ll = read_ll & 0x7f; From dcca646c4977d885af3466b454df97b9cb0e0d26 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 29 Mar 2021 06:53:54 +0000 Subject: [PATCH 1024/1091] ASoC: rt715: add main capture switch and main capture volume Add main capture switch and main capture volume control. Main capture control has its own channel value respectivelly. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/dfd43a8db04e4d52a889d6f5c1262173@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715.c | 256 +++++++++++++++++++++++++++++++++++++++ sound/soc/codecs/rt715.h | 2 + 2 files changed, 258 insertions(+) diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index 0f78ffbb03fd..3849dd187de0 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -201,9 +201,246 @@ static int rt715_set_amp_gain_get(struct snd_kcontrol *kcontrol, return 0; } +static int rt715_set_main_switch_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, val_ll, val_lr; + unsigned int k_shift = RT715_DIR_IN_SFT, k_changed = 0; + unsigned int read_ll, read_rl, i, j, loop_cnt = 4; + + for (i = 0; i < 8; i++) { + if (ucontrol->value.integer.value[i] != rt715->kctl_8ch_switch_ori[i]) + k_changed = 1; + } + + for (j = 0; j < loop_cnt; j++) { + /* Can't use update bit function, so read the original value first */ + addr_h = capture_reg_H[j]; + addr_l = capture_reg_L[j]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); + + /* L Channel */ + /* for mute */ + rt715->kctl_8ch_switch_ori[j * 2] = + ucontrol->value.integer.value[j * 2]; + val_ll = (!ucontrol->value.integer.value[j * 2]) << 7; + /* keep gain */ + val_ll |= read_ll & 0x7f; + + /* R Channel */ + /* for mute */ + rt715->kctl_8ch_switch_ori[j * 2 + 1] = + ucontrol->value.integer.value[j * 2 + 1]; + val_lr = (!ucontrol->value.integer.value[j * 2 + 1]) << 7; + /* keep gain */ + val_lr |= read_rl & 0x7f; + + for (i = 0; i < 3; i++) { /* retry 3 times at most */ + + if (val_ll == val_lr) { + /* Set both L/R channels at the same time */ + val_h = (1 << k_shift) | (3 << 4); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_ll); + } else { + /* Lch*/ + val_h = (1 << k_shift) | (1 << 5); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + /* Rch */ + val_h = (1 << k_shift) | (1 << 4); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_lr); + } + val_h = 0x0; + rt715_get_gain(rt715, addr_h, addr_l, val_h, + &read_rl, &read_ll); + if (read_rl == val_lr && read_ll == val_ll) + break; + } + } + + /* D0:power on state, D3: power saving mode */ + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + return k_changed; +} + +static int rt715_set_main_switch_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, i, loop_cnt = 4; + unsigned int read_ll, read_rl; + + for (i = 0; i < loop_cnt; i++) { + addr_h = capture_reg_H[i]; + addr_l = capture_reg_L[i]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + ucontrol->value.integer.value[i * 2] = !(read_ll & 0x80); + ucontrol->value.integer.value[i * 2 + 1] = !(read_rl & 0x80); + } + + return 0; +} + +static int rt715_set_main_vol_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct snd_soc_dapm_context *dapm = + snd_soc_component_get_dapm(component); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, val_ll, val_lr; + unsigned int read_ll, read_rl, i, j, loop_cnt = 4, k_changed = 0; + unsigned int k_shift = RT715_DIR_IN_SFT, k_max = 0x3f; + + for (i = 0; i < 8; i++) { + if (ucontrol->value.integer.value[i] != rt715->kctl_8ch_vol_ori[i]) + k_changed = 1; + } + + for (j = 0; j < loop_cnt; j++) { + addr_h = capture_reg_H[j]; + addr_l = capture_reg_L[j]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); + + /* L Channel */ + /* for gain */ + rt715->kctl_8ch_vol_ori[j * 2] = ucontrol->value.integer.value[j * 2]; + val_ll = ((ucontrol->value.integer.value[j * 2]) & 0x7f); + if (val_ll > k_max) + val_ll = k_max; + /* keep mute status */ + val_ll |= read_ll & 0x80; + + /* R Channel */ + /* for gain */ + rt715->kctl_8ch_vol_ori[j * 2 + 1] = + ucontrol->value.integer.value[j * 2 + 1]; + val_lr = ((ucontrol->value.integer.value[j * 2 + 1]) & 0x7f); + if (val_lr > k_max) + val_lr = k_max; + /* keep mute status */ + val_lr |= read_rl & 0x80; + + for (i = 0; i < 3; i++) { /* retry 3 times at most */ + if (val_ll == val_lr) { + /* Set both L/R channels at the same time */ + val_h = (1 << k_shift) | (3 << 4); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_ll); + } else { + /* Lch*/ + val_h = (1 << k_shift) | (1 << 5); + regmap_write(rt715->regmap, addr_h, + (val_h << 8) | val_ll); + /* Rch */ + val_h = (1 << k_shift) | (1 << 4); + regmap_write(rt715->regmap, addr_l, + (val_h << 8) | val_lr); + } + val_h = 0x0; + rt715_get_gain(rt715, addr_h, addr_l, val_h, + &read_rl, &read_ll); + if (read_rl == val_lr && read_ll == val_ll) + break; + } + } + + /* D0:power on state, D3: power saving mode */ + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D3); + return k_changed; +} + +static int rt715_set_main_vol_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); + unsigned int capture_reg_H[] = {RT715_SET_GAIN_MIC_ADC_H, + RT715_SET_GAIN_LINE_ADC_H, RT715_SET_GAIN_MIX_ADC_H, + RT715_SET_GAIN_MIX_ADC2_H}; + unsigned int capture_reg_L[] = {RT715_SET_GAIN_MIC_ADC_L, + RT715_SET_GAIN_LINE_ADC_L, RT715_SET_GAIN_MIX_ADC_L, + RT715_SET_GAIN_MIX_ADC2_L}; + unsigned int addr_h, addr_l, val_h = 0x0, i, loop_cnt = 4; + unsigned int read_ll, read_rl; + + for (i = 0; i < loop_cnt; i++) { + addr_h = capture_reg_H[i]; + addr_l = capture_reg_L[i]; + rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + + ucontrol->value.integer.value[i * 2] = read_ll & 0x7f; + ucontrol->value.integer.value[i * 2 + 1] = read_rl & 0x7f; + } + + return 0; +} + static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); +static int rt715_switch_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BOOLEAN; + uinfo->count = 8; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 1; + return 0; +} + +static int rt715_vol_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_INTEGER; + uinfo->count = 8; + uinfo->value.integer.min = 0; + uinfo->value.integer.max = 0x3f; + return 0; +} + #define SOC_DOUBLE_R_EXT(xname, reg_left, reg_right, xshift, xmax, xinvert,\ xhandler_get, xhandler_put) \ { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ @@ -212,6 +449,21 @@ static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); .private_value = SOC_DOUBLE_R_VALUE(reg_left, reg_right, xshift, \ xmax, xinvert) } +#define RT715_MAIN_SWITCH_EXT(xname, xhandler_get, xhandler_put) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .info = rt715_switch_info, \ + .get = xhandler_get, .put = xhandler_put, \ +} + +#define RT715_MAIN_VOL_EXT_TLV(xname, xhandler_get, xhandler_put, tlv_array) \ +{ .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = (xname), \ + .access = SNDRV_CTL_ELEM_ACCESS_TLV_READ | \ + SNDRV_CTL_ELEM_ACCESS_READWRITE, \ + .tlv.p = (tlv_array), \ + .info = rt715_vol_info, \ + .get = xhandler_get, .put = xhandler_put, \ +} + static const struct snd_kcontrol_new rt715_snd_controls[] = { /* Capture switch */ SOC_DOUBLE_R_EXT("ADC 07 Capture Switch", RT715_SET_GAIN_MIC_ADC_H, @@ -226,6 +478,8 @@ static const struct snd_kcontrol_new rt715_snd_controls[] = { SOC_DOUBLE_R_EXT("ADC 27 Capture Switch", RT715_SET_GAIN_MIX_ADC2_H, RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 1, 1, rt715_set_amp_gain_get, rt715_set_amp_gain_put), + RT715_MAIN_SWITCH_EXT("Capture Switch", + rt715_set_main_switch_get, rt715_set_main_switch_put), /* Volume Control */ SOC_DOUBLE_R_EXT_TLV("ADC 07 Capture Volume", RT715_SET_GAIN_MIC_ADC_H, RT715_SET_GAIN_MIC_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0, @@ -243,6 +497,8 @@ static const struct snd_kcontrol_new rt715_snd_controls[] = { RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 0x3f, 0, rt715_set_amp_gain_get, rt715_set_amp_gain_put, in_vol_tlv), + RT715_MAIN_VOL_EXT_TLV("Capture Volume", + rt715_set_main_vol_get, rt715_set_main_vol_put, in_vol_tlv), /* MIC Boost Control */ SOC_DOUBLE_R_EXT_TLV("DMIC1 Boost", RT715_SET_GAIN_DMIC1_H, RT715_SET_GAIN_DMIC1_L, RT715_DIR_IN_SFT, 3, 0, diff --git a/sound/soc/codecs/rt715.h b/sound/soc/codecs/rt715.h index 009a8266f606..72c320bd35cb 100644 --- a/sound/soc/codecs/rt715.h +++ b/sound/soc/codecs/rt715.h @@ -22,6 +22,8 @@ struct rt715_priv { struct sdw_bus_params params; bool hw_init; bool first_hw_init; + unsigned int kctl_8ch_switch_ori[8]; + unsigned int kctl_8ch_vol_ori[8]; }; struct sdw_stream_data { From fa2f98378f941786a93f8e63696f59fb4ac7538b Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Mon, 29 Mar 2021 06:54:00 +0000 Subject: [PATCH 1025/1091] ASoC: rt715: remove kcontrols which no longer be used Using new kcontrols "Capture Switch" and "Capture Volume" instead, remove kcontrols which no longer be used. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/5c314f5512654aca9fff0195f77264de@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt715.c | 103 +++++++++++++-------------------------- sound/soc/codecs/rt715.h | 1 + 2 files changed, 36 insertions(+), 68 deletions(-) diff --git a/sound/soc/codecs/rt715.c b/sound/soc/codecs/rt715.c index 3849dd187de0..1352869cc086 100644 --- a/sound/soc/codecs/rt715.c +++ b/sound/soc/codecs/rt715.c @@ -81,12 +81,20 @@ static int rt715_set_amp_gain_put(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct rt715_priv *rt715 = snd_soc_component_get_drvdata(component); unsigned int addr_h, addr_l, val_h, val_ll, val_lr; - unsigned int read_ll, read_rl; - int i; + unsigned int read_ll, read_rl, i; + unsigned int k_vol_changed = 0; + + for (i = 0; i < 2; i++) { + if (ucontrol->value.integer.value[i] != rt715->kctl_2ch_vol_ori[i]) { + k_vol_changed = 1; + break; + } + } /* Can't use update bit function, so read the original value first */ addr_h = mc->reg; addr_l = mc->rreg; + if (mc->shift == RT715_DIR_OUT_SFT) /* output */ val_h = 0x80; else /* input */ @@ -94,41 +102,27 @@ static int rt715_set_amp_gain_put(struct snd_kcontrol *kcontrol, rt715_get_gain(rt715, addr_h, addr_l, val_h, &read_rl, &read_ll); + if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) + regmap_write(rt715->regmap, + RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); + /* L Channel */ - if (mc->invert) { - /* for mute */ - val_ll = (mc->max - ucontrol->value.integer.value[0]) << 7; - /* keep gain */ - read_ll = read_ll & 0x7f; - val_ll |= read_ll; - } else { - /* for gain */ - val_ll = ((ucontrol->value.integer.value[0]) & 0x7f); - if (val_ll > mc->max) - val_ll = mc->max; - /* keep mute status */ - read_ll = read_ll & 0x80; - val_ll |= read_ll; - } + rt715->kctl_2ch_vol_ori[0] = ucontrol->value.integer.value[0]; + /* for gain */ + val_ll = ((ucontrol->value.integer.value[0]) & 0x7f); + if (val_ll > mc->max) + val_ll = mc->max; + /* keep mute status */ + val_ll |= read_ll & 0x80; /* R Channel */ - if (mc->invert) { - regmap_write(rt715->regmap, - RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D0); - /* for mute */ - val_lr = (mc->max - ucontrol->value.integer.value[1]) << 7; - /* keep gain */ - read_rl = read_rl & 0x7f; - val_lr |= read_rl; - } else { - /* for gain */ - val_lr = ((ucontrol->value.integer.value[1]) & 0x7f); - if (val_lr > mc->max) - val_lr = mc->max; - /* keep mute status */ - read_rl = read_rl & 0x80; - val_lr |= read_rl; - } + rt715->kctl_2ch_vol_ori[1] = ucontrol->value.integer.value[1]; + /* for gain */ + val_lr = ((ucontrol->value.integer.value[1]) & 0x7f); + if (val_lr > mc->max) + val_lr = mc->max; + /* keep mute status */ + val_lr |= read_rl & 0x80; for (i = 0; i < 3; i++) { /* retry 3 times at most */ @@ -136,18 +130,18 @@ static int rt715_set_amp_gain_put(struct snd_kcontrol *kcontrol, /* Set both L/R channels at the same time */ val_h = (1 << mc->shift) | (3 << 4); regmap_write(rt715->regmap, addr_h, - (val_h << 8 | val_ll)); + (val_h << 8) | val_ll); regmap_write(rt715->regmap, addr_l, - (val_h << 8 | val_ll)); + (val_h << 8) | val_ll); } else { /* Lch*/ val_h = (1 << mc->shift) | (1 << 5); regmap_write(rt715->regmap, addr_h, - (val_h << 8 | val_ll)); + (val_h << 8) | val_ll); /* Rch */ val_h = (1 << mc->shift) | (1 << 4); regmap_write(rt715->regmap, addr_l, - (val_h << 8 | val_lr)); + (val_h << 8) | val_lr); } /* check result */ if (mc->shift == RT715_DIR_OUT_SFT) /* output */ @@ -156,15 +150,16 @@ static int rt715_set_amp_gain_put(struct snd_kcontrol *kcontrol, val_h = 0x0; rt715_get_gain(rt715, addr_h, addr_l, val_h, - &read_rl, &read_ll); + &read_rl, &read_ll); if (read_rl == val_lr && read_ll == val_ll) break; } + /* D0:power on state, D3: power saving mode */ if (dapm->bias_level <= SND_SOC_BIAS_STANDBY) regmap_write(rt715->regmap, RT715_SET_AUDIO_POWER_STATE, AC_PWRST_D3); - return 0; + return k_vol_changed; } static int rt715_set_amp_gain_get(struct snd_kcontrol *kcontrol, @@ -466,37 +461,9 @@ static int rt715_vol_info(struct snd_kcontrol *kcontrol, static const struct snd_kcontrol_new rt715_snd_controls[] = { /* Capture switch */ - SOC_DOUBLE_R_EXT("ADC 07 Capture Switch", RT715_SET_GAIN_MIC_ADC_H, - RT715_SET_GAIN_MIC_ADC_L, RT715_DIR_IN_SFT, 1, 1, - rt715_set_amp_gain_get, rt715_set_amp_gain_put), - SOC_DOUBLE_R_EXT("ADC 08 Capture Switch", RT715_SET_GAIN_LINE_ADC_H, - RT715_SET_GAIN_LINE_ADC_L, RT715_DIR_IN_SFT, 1, 1, - rt715_set_amp_gain_get, rt715_set_amp_gain_put), - SOC_DOUBLE_R_EXT("ADC 09 Capture Switch", RT715_SET_GAIN_MIX_ADC_H, - RT715_SET_GAIN_MIX_ADC_L, RT715_DIR_IN_SFT, 1, 1, - rt715_set_amp_gain_get, rt715_set_amp_gain_put), - SOC_DOUBLE_R_EXT("ADC 27 Capture Switch", RT715_SET_GAIN_MIX_ADC2_H, - RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 1, 1, - rt715_set_amp_gain_get, rt715_set_amp_gain_put), RT715_MAIN_SWITCH_EXT("Capture Switch", rt715_set_main_switch_get, rt715_set_main_switch_put), /* Volume Control */ - SOC_DOUBLE_R_EXT_TLV("ADC 07 Capture Volume", RT715_SET_GAIN_MIC_ADC_H, - RT715_SET_GAIN_MIC_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0, - rt715_set_amp_gain_get, rt715_set_amp_gain_put, - in_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("ADC 08 Capture Volume", RT715_SET_GAIN_LINE_ADC_H, - RT715_SET_GAIN_LINE_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0, - rt715_set_amp_gain_get, rt715_set_amp_gain_put, - in_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("ADC 09 Capture Volume", RT715_SET_GAIN_MIX_ADC_H, - RT715_SET_GAIN_MIX_ADC_L, RT715_DIR_IN_SFT, 0x3f, 0, - rt715_set_amp_gain_get, rt715_set_amp_gain_put, - in_vol_tlv), - SOC_DOUBLE_R_EXT_TLV("ADC 27 Capture Volume", RT715_SET_GAIN_MIX_ADC2_H, - RT715_SET_GAIN_MIX_ADC2_L, RT715_DIR_IN_SFT, 0x3f, 0, - rt715_set_amp_gain_get, rt715_set_amp_gain_put, - in_vol_tlv), RT715_MAIN_VOL_EXT_TLV("Capture Volume", rt715_set_main_vol_get, rt715_set_main_vol_put, in_vol_tlv), /* MIC Boost Control */ diff --git a/sound/soc/codecs/rt715.h b/sound/soc/codecs/rt715.h index 72c320bd35cb..25dba61f1760 100644 --- a/sound/soc/codecs/rt715.h +++ b/sound/soc/codecs/rt715.h @@ -22,6 +22,7 @@ struct rt715_priv { struct sdw_bus_params params; bool hw_init; bool first_hw_init; + unsigned int kctl_2ch_vol_ori[2]; unsigned int kctl_8ch_switch_ori[8]; unsigned int kctl_8ch_vol_ori[8]; }; From d63f2a88d5cfaad025f26e1107f3807d579654c5 Mon Sep 17 00:00:00 2001 From: Rob Herring Date: Fri, 16 Apr 2021 13:01:18 -0500 Subject: [PATCH 1026/1091] ASoC: mt6359: Drop ASoC mt6359 ASoC accdet jack document This reverts commit e61c589587c772c5f672b22683c3e0b38be20702. The binding document has lots of schema errors and there's been no effort to fix them, so let's remove it. Cc: Argus Lin Cc: Mark Brown Cc: Liam Girdwood Cc: Matthias Brugger Cc: alsa-devel@alsa-project.org Cc: linux-arm-kernel@lists.infradead.org Cc: linux-mediatek@lists.infradead.org Signed-off-by: Rob Herring Link: https://lore.kernel.org/r/20210416180118.3662904-1-robh@kernel.org Signed-off-by: Mark Brown --- .../bindings/sound/mt6359-accdet.yaml | 164 ------------------ 1 file changed, 164 deletions(-) delete mode 100644 Documentation/devicetree/bindings/sound/mt6359-accdet.yaml diff --git a/Documentation/devicetree/bindings/sound/mt6359-accdet.yaml b/Documentation/devicetree/bindings/sound/mt6359-accdet.yaml deleted file mode 100644 index 7fb3e8dfb4c5..000000000000 --- a/Documentation/devicetree/bindings/sound/mt6359-accdet.yaml +++ /dev/null @@ -1,164 +0,0 @@ -# SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause) -%YAML 1.2 ---- -$id: http://devicetree.org/schemas/sound/mt6359-accdet.yaml# -$schema: http://devicetree.org/meta-schemas/core.yaml# - -title: Mediatek Technologies Inc. MT6359 ASoC accdet jack driver bindings - -maintainers: - - Chipeng Chang - -description: | - This binding describes the Mediatek Technologies MT6359 ASoC - accdet jack driver. - -properties: - mediatek,accdet-name: - maxItems: 1 - description: named as "mt6359-accdet" jack. - - mediatek,mic-vol: - maxItems: 1 - description: | - accdet micbias1 voltage. - - enum: - - 0x00 # 1.7v - micbias1 volage is 1.7v. - - 0x01 # 1.8v - micbias1 volage is 1.8v. - - 0x02 # 1.9v - micbias1 volage is 1.9v. - - 0x03 # 2.0v - micbias1 volage is 2.0v. - - 0x04 # 2.1v - micbias1 volage is 2.1v. - - 0x05 # 2.5v - micbias1 volage is 2.5v. - - 0x06 # 2.6v - micbias1 volage is 2.6v. - - 0x07 # 2.7v - micbias1 volage is 2.7v. - - 0x08 # 2.8v - micbias1 volage is 2.8v. - - 0x09 # 2.85v - micbias1 volage is 2.85v. - - mediatek,mic-mode: - maxItems: 1 - description: | - value as 1, 2, 6 to indicate ACC/DCC mode. default is DCC mode 2. - - enum: - - 0x01 # ACC - ACC mode. - - 0x02 # DCC - low cost without in bias. - - 0x06 # DCC - low cost with in bias. - - mediatek,pwm-deb-setting: - maxItems: 15 - description: | - headset-mode-setting : Indicates customized pwm, debounce setting - accdet pwm_width, pwm_thresh, fall_delay, rise_delay - debounce0, debounce1, debounce3, debounce4 - eint pwm_width, eint pwm_thresh - eint deb(debounce0, debounce1, debounce2, debounce3), inv_debounce. - - mediatek,eint-use-ap: - maxItems: 1 - description: | - indicates to use ap gpio. - - enum: - - 0x00 # MT6359 eint detection mode. - - 0x01 # SoC GPIO detection mode. - - mediatek,eint-detect-mode: - maxItems: 1 - description: | - indicates to use ap gpio. - - enum: - - 0x00 # detection mode with higher detection power. - - 0x01 # detection mode with lower detection power. - - 0x02 # detection mode with sw moisture detection mode. - - 0x03 # detection mode with hw moisture detection mode1. - - 0x04 # detection mode with hw moisture detection mode2. - - mediatek,eint-num: - maxItems: 1 - description: | - incicates pmic eint usage. - - enum: - - 0x0 # PMIC_EINT0 - use pmic eint0 to trigger plug interrupt. - - 0x1 # PMIC_EINT1 - use pmic eint1 to trigger plug interrupt. - - 0x2 # PMIC_BI_EINT - use pmic eint0/1 to trigger plug interrupt. - - mediatek,eint-trig-mode: - maxItems: 1 - description: | - incicates pmic eint trigger mode. - - enum: - - 0x0 # PMIC_GPIO - use pmic gpio to detect plug status. - - 0x1 # PMIC_INVERTER - use pmic inverter to detect plug status. - - mediatek,eint-use-ext-res: - maxItems: 1 - description: | - select HP_EINT pull up resistance, default 0 use internal resistance. - - enum: - - 0x0 # use internal resistor. - - 0x1 # use external resistor. - - mediatek,eint-comp-vth: - maxItems: 1 - description: | - indicates comparator detection voltage. - - enum: - - 0x00 # 2.8v. - - 0x01 # 2.4v. - - 0x02 # 2.0v. - - 0x03 # 0.7v. - - mediatek,key-mode: - maxItems: 1 - description: | - incicates key mode type. - - enum: - - 0x0 # THREE_KEY - support 3-key key mode. - - 0x1 # FOUR_KEY - support 4-key key mode. - - 0x2 # TRI_KEY_CDD - support 3-key google CDD key mode. - - mediatek,three-key-thr: - maxItems: 4 - description: | - 3 key device detection threshold: 0--MD_MAX--UP_MAX--DW_MAX. - - mediatek,tri-key-cdd-thr: - maxItems: 4 - description: | - 3 key CDD device detection threshold: 0--MD_MAX--UP_MAX--DW_MAX. - - mediatek,four-key-thr: - maxItems: 4 - description: | - 4 key device detection threshold: 0--MD_MAX--VOICE_MAX--UP_MAX--DW_MAX. - -additionalProperties: false - -examples: - - | - accdet: accdet { - mediatek,accdet-name = "mt6359-accdet"; - mediatek,mic-vol = <8>; - mediatek,mic-mode = <2>; - mediatek,pwm-deb-setting = <0x500 0x500 1 0x1f0 - 0x800 0x800 0x20 0x44 - 0x4 0x1 - 0x5 0x3 0x3 0x5 0xe>; - mediatek,eint-use-ap = <0>; - mediatek,eint-detect-mode = <4>; - mediatek,eint-num = <0>; - mediatek,eint-trig-mode = <1>; - mediatek,eint-use-ext-res = <0>; - mediatek,eint-comp-vth = <2>; - mediatek,key-mode = <0>; - mediatek,three-key-thr = <0 80 220 400>; - status = "okay"; - }; -... From 9601148392520e2e134936e76788fc2a6371e7be Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 23 Mar 2021 08:32:59 +0100 Subject: [PATCH 1027/1091] bpf: Use correct permission flag for mixed signed bounds arithmetic We forbid adding unknown scalars with mixed signed bounds due to the spectre v1 masking mitigation. Hence this also needs bypass_spec_v1 flag instead of allow_ptr_leaks. Fixes: 2c78ee898d8f ("bpf: Implement CAP_BPF") Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- kernel/bpf/verifier.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 3a738724a380..2ede4b850230 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6085,7 +6085,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, dst, reg_type_str[ptr_reg->type]); return -EACCES; case PTR_TO_MAP_VALUE: - if (!env->allow_ptr_leaks && !known && (smin_val < 0) != (smax_val < 0)) { + if (!env->env->bypass_spec_v1 && !known && (smin_val < 0) != (smax_val < 0)) { verbose(env, "R%d has unknown scalar with mixed signed bounds, pointer arithmetic with it prohibited for !root\n", off_reg == dst_reg ? dst : src); return -EACCES; From 6f55b2f2a1178856c19bbce2f71449926e731914 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Mon, 22 Mar 2021 15:45:52 +0100 Subject: [PATCH 1028/1091] bpf: Move off_reg into sanitize_ptr_alu Small refactor to drag off_reg into sanitize_ptr_alu(), so we later on can use off_reg for generalizing some of the checks for all pointer types. Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- kernel/bpf/verifier.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 2ede4b850230..4ee014dadac7 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5929,11 +5929,12 @@ static int sanitize_val_alu(struct bpf_verifier_env *env, static int sanitize_ptr_alu(struct bpf_verifier_env *env, struct bpf_insn *insn, const struct bpf_reg_state *ptr_reg, - struct bpf_reg_state *dst_reg, - bool off_is_neg) + const struct bpf_reg_state *off_reg, + struct bpf_reg_state *dst_reg) { struct bpf_verifier_state *vstate = env->cur_state; struct bpf_insn_aux_data *aux = cur_aux(env); + bool off_is_neg = off_reg->smin_value < 0; bool ptr_is_dst_reg = ptr_reg == dst_reg; u8 opcode = BPF_OP(insn->code); u32 alu_state, alu_limit; @@ -6110,7 +6111,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, switch (opcode) { case BPF_ADD: - ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0); + ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg); if (ret < 0) { verbose(env, "R%d tried to add from different maps, paths, or prohibited types\n", dst); return ret; @@ -6165,7 +6166,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, } break; case BPF_SUB: - ret = sanitize_ptr_alu(env, insn, ptr_reg, dst_reg, smin_val < 0); + ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg); if (ret < 0) { verbose(env, "R%d tried to sub from different maps, paths, or prohibited types\n", dst); return ret; From 24c109bb1537c12c02aeed2d51a347b4d6a9b76e Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 23 Mar 2021 08:51:02 +0100 Subject: [PATCH 1029/1091] bpf: Ensure off_reg has no mixed signed bounds for all types The mixed signed bounds check really belongs into retrieve_ptr_limit() instead of outside of it in adjust_ptr_min_max_vals(). The reason is that this check is not tied to PTR_TO_MAP_VALUE only, but to all pointer types that we handle in retrieve_ptr_limit() and given errors from the latter propagate back to adjust_ptr_min_max_vals() and lead to rejection of the program, it's a better place to reside to avoid anything slipping through for future types. The reason why we must reject such off_reg is that we otherwise would not be able to derive a mask, see details in 9d7eceede769 ("bpf: restrict unknown scalars of mixed signed bounds for unprivileged"). Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- kernel/bpf/verifier.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 4ee014dadac7..a21d7f1a0ba8 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5857,12 +5857,18 @@ static struct bpf_insn_aux_data *cur_aux(struct bpf_verifier_env *env) } static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, - u32 *ptr_limit, u8 opcode, bool off_is_neg) + const struct bpf_reg_state *off_reg, + u32 *ptr_limit, u8 opcode) { + bool off_is_neg = off_reg->smin_value < 0; bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || (opcode == BPF_SUB && !off_is_neg); u32 off, max; + if (!tnum_is_const(off_reg->var_off) && + (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) + return -EACCES; + switch (ptr_reg->type) { case PTR_TO_STACK: /* Offset 0 is out-of-bounds, but acceptable start for the @@ -5956,7 +5962,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env, alu_state |= ptr_is_dst_reg ? BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST; - err = retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg); + err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode); if (err < 0) return err; @@ -6036,8 +6042,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value; u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value, umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value; - u32 dst = insn->dst_reg, src = insn->src_reg; u8 opcode = BPF_OP(insn->code); + u32 dst = insn->dst_reg; int ret; dst_reg = ®s[dst]; @@ -6085,13 +6091,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, verbose(env, "R%d pointer arithmetic on %s prohibited\n", dst, reg_type_str[ptr_reg->type]); return -EACCES; - case PTR_TO_MAP_VALUE: - if (!env->env->bypass_spec_v1 && !known && (smin_val < 0) != (smax_val < 0)) { - verbose(env, "R%d has unknown scalar with mixed signed bounds, pointer arithmetic with it prohibited for !root\n", - off_reg == dst_reg ? dst : src); - return -EACCES; - } - fallthrough; default: break; } From b658bbb844e28f1862867f37e8ca11a8e2aa94a3 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 23 Mar 2021 09:04:10 +0100 Subject: [PATCH 1030/1091] bpf: Rework ptr_limit into alu_limit and add common error path Small refactor with no semantic changes in order to consolidate the max ptr_limit boundary check. Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- kernel/bpf/verifier.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index a21d7f1a0ba8..b8e0171d9591 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5858,12 +5858,12 @@ static struct bpf_insn_aux_data *cur_aux(struct bpf_verifier_env *env) static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, const struct bpf_reg_state *off_reg, - u32 *ptr_limit, u8 opcode) + u32 *alu_limit, u8 opcode) { bool off_is_neg = off_reg->smin_value < 0; bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || (opcode == BPF_SUB && !off_is_neg); - u32 off, max; + u32 off, max = 0, ptr_limit = 0; if (!tnum_is_const(off_reg->var_off) && (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) @@ -5880,22 +5880,27 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, */ off = ptr_reg->off + ptr_reg->var_off.value; if (mask_to_left) - *ptr_limit = MAX_BPF_STACK + off; + ptr_limit = MAX_BPF_STACK + off; else - *ptr_limit = -off - 1; - return *ptr_limit >= max ? -ERANGE : 0; + ptr_limit = -off - 1; + break; case PTR_TO_MAP_VALUE: max = ptr_reg->map_ptr->value_size; if (mask_to_left) { - *ptr_limit = ptr_reg->umax_value + ptr_reg->off; + ptr_limit = ptr_reg->umax_value + ptr_reg->off; } else { off = ptr_reg->smin_value + ptr_reg->off; - *ptr_limit = ptr_reg->map_ptr->value_size - off - 1; + ptr_limit = ptr_reg->map_ptr->value_size - off - 1; } - return *ptr_limit >= max ? -ERANGE : 0; + break; default: return -EINVAL; } + + if (ptr_limit >= max) + return -ERANGE; + *alu_limit = ptr_limit; + return 0; } static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env, From a6aaece00a57fa6f22575364b3903dfbccf5345d Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 23 Mar 2021 09:30:01 +0100 Subject: [PATCH 1031/1091] bpf: Improve verifier error messages for users Consolidate all error handling and provide more user-friendly error messages from sanitize_ptr_alu() and sanitize_val_alu(). Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- kernel/bpf/verifier.c | 86 +++++++++++++++++++++++++++++++------------ 1 file changed, 63 insertions(+), 23 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index b8e0171d9591..f378d4ae405f 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5856,6 +5856,14 @@ static struct bpf_insn_aux_data *cur_aux(struct bpf_verifier_env *env) return &env->insn_aux_data[env->insn_idx]; } +enum { + REASON_BOUNDS = -1, + REASON_TYPE = -2, + REASON_PATHS = -3, + REASON_LIMIT = -4, + REASON_STACK = -5, +}; + static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, const struct bpf_reg_state *off_reg, u32 *alu_limit, u8 opcode) @@ -5867,7 +5875,7 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, if (!tnum_is_const(off_reg->var_off) && (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) - return -EACCES; + return REASON_BOUNDS; switch (ptr_reg->type) { case PTR_TO_STACK: @@ -5894,11 +5902,11 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, } break; default: - return -EINVAL; + return REASON_TYPE; } if (ptr_limit >= max) - return -ERANGE; + return REASON_LIMIT; *alu_limit = ptr_limit; return 0; } @@ -5918,7 +5926,7 @@ static int update_alu_sanitation_state(struct bpf_insn_aux_data *aux, if (aux->alu_state && (aux->alu_state != alu_state || aux->alu_limit != alu_limit)) - return -EACCES; + return REASON_PATHS; /* Corresponding fixup done in fixup_bpf_calls(). */ aux->alu_state = alu_state; @@ -5991,7 +5999,46 @@ do_sim: ret = push_stack(env, env->insn_idx + 1, env->insn_idx, true); if (!ptr_is_dst_reg && ret) *dst_reg = tmp; - return !ret ? -EFAULT : 0; + return !ret ? REASON_STACK : 0; +} + +static int sanitize_err(struct bpf_verifier_env *env, + const struct bpf_insn *insn, int reason, + const struct bpf_reg_state *off_reg, + const struct bpf_reg_state *dst_reg) +{ + static const char *err = "pointer arithmetic with it prohibited for !root"; + const char *op = BPF_OP(insn->code) == BPF_ADD ? "add" : "sub"; + u32 dst = insn->dst_reg, src = insn->src_reg; + + switch (reason) { + case REASON_BOUNDS: + verbose(env, "R%d has unknown scalar with mixed signed bounds, %s\n", + off_reg == dst_reg ? dst : src, err); + break; + case REASON_TYPE: + verbose(env, "R%d has pointer with unsupported alu operation, %s\n", + off_reg == dst_reg ? src : dst, err); + break; + case REASON_PATHS: + verbose(env, "R%d tried to %s from different maps, paths or scalars, %s\n", + dst, op, err); + break; + case REASON_LIMIT: + verbose(env, "R%d tried to %s beyond pointer bounds, %s\n", + dst, op, err); + break; + case REASON_STACK: + verbose(env, "R%d could not be pushed for speculative verification, %s\n", + dst, err); + break; + default: + verbose(env, "verifier internal error: unknown reason (%d)\n", + reason); + break; + } + + return -EACCES; } /* check that stack access falls within stack limits and that 'reg' doesn't @@ -6116,10 +6163,9 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, switch (opcode) { case BPF_ADD: ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg); - if (ret < 0) { - verbose(env, "R%d tried to add from different maps, paths, or prohibited types\n", dst); - return ret; - } + if (ret < 0) + return sanitize_err(env, insn, ret, off_reg, dst_reg); + /* We can take a fixed offset as long as it doesn't overflow * the s32 'off' field */ @@ -6171,10 +6217,9 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, break; case BPF_SUB: ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg); - if (ret < 0) { - verbose(env, "R%d tried to sub from different maps, paths, or prohibited types\n", dst); - return ret; - } + if (ret < 0) + return sanitize_err(env, insn, ret, off_reg, dst_reg); + if (dst_reg == off_reg) { /* scalar -= pointer. Creates an unknown scalar */ verbose(env, "R%d tried to subtract pointer from scalar\n", @@ -6863,9 +6908,8 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, s32 s32_min_val, s32_max_val; u32 u32_min_val, u32_max_val; u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32; - u32 dst = insn->dst_reg; - int ret; bool alu32 = (BPF_CLASS(insn->code) != BPF_ALU64); + int ret; smin_val = src_reg.smin_value; smax_val = src_reg.smax_value; @@ -6924,20 +6968,16 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, switch (opcode) { case BPF_ADD: ret = sanitize_val_alu(env, insn); - if (ret < 0) { - verbose(env, "R%d tried to add from different pointers or scalars\n", dst); - return ret; - } + if (ret < 0) + return sanitize_err(env, insn, ret, NULL, NULL); scalar32_min_max_add(dst_reg, &src_reg); scalar_min_max_add(dst_reg, &src_reg); dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off); break; case BPF_SUB: ret = sanitize_val_alu(env, insn); - if (ret < 0) { - verbose(env, "R%d tried to sub from different pointers or scalars\n", dst); - return ret; - } + if (ret < 0) + return sanitize_err(env, insn, ret, NULL, NULL); scalar32_min_max_sub(dst_reg, &src_reg); scalar_min_max_sub(dst_reg, &src_reg); dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg.var_off); From 073815b756c51ba9d8384d924c5d1c03ca3d1ae4 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Tue, 23 Mar 2021 15:05:48 +0100 Subject: [PATCH 1032/1091] bpf: Refactor and streamline bounds check into helper Move the bounds check in adjust_ptr_min_max_vals() into a small helper named sanitize_check_bounds() in order to simplify the former a bit. Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- kernel/bpf/verifier.c | 49 +++++++++++++++++++++++++++++-------------- 1 file changed, 33 insertions(+), 16 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index f378d4ae405f..db77e2c670b9 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -6075,6 +6075,37 @@ static int check_stack_access_for_ptr_arithmetic( return 0; } +static int sanitize_check_bounds(struct bpf_verifier_env *env, + const struct bpf_insn *insn, + const struct bpf_reg_state *dst_reg) +{ + u32 dst = insn->dst_reg; + + /* For unprivileged we require that resulting offset must be in bounds + * in order to be able to sanitize access later on. + */ + if (env->bypass_spec_v1) + return 0; + + switch (dst_reg->type) { + case PTR_TO_STACK: + if (check_stack_access_for_ptr_arithmetic(env, dst, dst_reg, + dst_reg->off + dst_reg->var_off.value)) + return -EACCES; + break; + case PTR_TO_MAP_VALUE: + if (check_map_access(env, dst, dst_reg->off, 1, false)) { + verbose(env, "R%d pointer arithmetic of map value goes out of range, " + "prohibited for !root\n", dst); + return -EACCES; + } + break; + default: + break; + } + + return 0; +} /* Handles arithmetic on a pointer and a scalar: computes new min/max and var_off. * Caller should also handle BPF_MOV case separately. @@ -6300,22 +6331,8 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, __reg_deduce_bounds(dst_reg); __reg_bound_offset(dst_reg); - /* For unprivileged we require that resulting offset must be in bounds - * in order to be able to sanitize access later on. - */ - if (!env->bypass_spec_v1) { - if (dst_reg->type == PTR_TO_MAP_VALUE && - check_map_access(env, dst, dst_reg->off, 1, false)) { - verbose(env, "R%d pointer arithmetic of map value goes out of range, " - "prohibited for !root\n", dst); - return -EACCES; - } else if (dst_reg->type == PTR_TO_STACK && - check_stack_access_for_ptr_arithmetic( - env, dst, dst_reg, dst_reg->off + - dst_reg->var_off.value)) { - return -EACCES; - } - } + if (sanitize_check_bounds(env, insn, dst_reg) < 0) + return -EACCES; return 0; } From f528819334881fd622fdadeddb3f7edaed8b7c9b Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 24 Mar 2021 11:25:39 +0100 Subject: [PATCH 1033/1091] bpf: Move sanitize_val_alu out of op switch Add a small sanitize_needed() helper function and move sanitize_val_alu() out of the main opcode switch. In upcoming work, we'll move sanitize_ptr_alu() as well out of its opcode switch so this helps to streamline both. Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- kernel/bpf/verifier.c | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index db77e2c670b9..e41b6326e3e6 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5945,6 +5945,11 @@ static int sanitize_val_alu(struct bpf_verifier_env *env, return update_alu_sanitation_state(aux, BPF_ALU_NON_POINTER, 0); } +static bool sanitize_needed(u8 opcode) +{ + return opcode == BPF_ADD || opcode == BPF_SUB; +} + static int sanitize_ptr_alu(struct bpf_verifier_env *env, struct bpf_insn *insn, const struct bpf_reg_state *ptr_reg, @@ -6968,6 +6973,12 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, return 0; } + if (sanitize_needed(opcode)) { + ret = sanitize_val_alu(env, insn); + if (ret < 0) + return sanitize_err(env, insn, ret, NULL, NULL); + } + /* Calculate sign/unsigned bounds and tnum for alu32 and alu64 bit ops. * There are two classes of instructions: The first class we track both * alu32 and alu64 sign/unsigned bounds independently this provides the @@ -6984,17 +6995,11 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env, */ switch (opcode) { case BPF_ADD: - ret = sanitize_val_alu(env, insn); - if (ret < 0) - return sanitize_err(env, insn, ret, NULL, NULL); scalar32_min_max_add(dst_reg, &src_reg); scalar_min_max_add(dst_reg, &src_reg); dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off); break; case BPF_SUB: - ret = sanitize_val_alu(env, insn); - if (ret < 0) - return sanitize_err(env, insn, ret, NULL, NULL); scalar32_min_max_sub(dst_reg, &src_reg); scalar_min_max_sub(dst_reg, &src_reg); dst_reg->var_off = tnum_sub(dst_reg->var_off, src_reg.var_off); From 7fedb63a8307dda0ec3b8969a3b233a1dd7ea8e0 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 24 Mar 2021 10:38:26 +0100 Subject: [PATCH 1034/1091] bpf: Tighten speculative pointer arithmetic mask This work tightens the offset mask we use for unprivileged pointer arithmetic in order to mitigate a corner case reported by Piotr and Benedict where in the speculative domain it is possible to advance, for example, the map value pointer by up to value_size-1 out-of-bounds in order to leak kernel memory via side-channel to user space. Before this change, the computed ptr_limit for retrieve_ptr_limit() helper represents largest valid distance when moving pointer to the right or left which is then fed as aux->alu_limit to generate masking instructions against the offset register. After the change, the derived aux->alu_limit represents the largest potential value of the offset register which we mask against which is just a narrower subset of the former limit. For minimal complexity, we call sanitize_ptr_alu() from 2 observation points in adjust_ptr_min_max_vals(), that is, before and after the simulated alu operation. In the first step, we retieve the alu_state and alu_limit before the operation as well as we branch-off a verifier path and push it to the verification stack as we did before which checks the dst_reg under truncation, in other words, when the speculative domain would attempt to move the pointer out-of-bounds. In the second step, we retrieve the new alu_limit and calculate the absolute distance between both. Moreover, we commit the alu_state and final alu_limit via update_alu_sanitation_state() to the env's instruction aux data, and bail out from there if there is a mismatch due to coming from different verification paths with different states. Reported-by: Piotr Krysiuk Reported-by: Benedict Schlueter Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov Tested-by: Benedict Schlueter --- kernel/bpf/verifier.c | 73 ++++++++++++++++++++++++++----------------- 1 file changed, 44 insertions(+), 29 deletions(-) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index e41b6326e3e6..0399ac092b36 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -5871,7 +5871,7 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, bool off_is_neg = off_reg->smin_value < 0; bool mask_to_left = (opcode == BPF_ADD && off_is_neg) || (opcode == BPF_SUB && !off_is_neg); - u32 off, max = 0, ptr_limit = 0; + u32 max = 0, ptr_limit = 0; if (!tnum_is_const(off_reg->var_off) && (off_reg->smin_value < 0) != (off_reg->smax_value < 0)) @@ -5880,26 +5880,18 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg, switch (ptr_reg->type) { case PTR_TO_STACK: /* Offset 0 is out-of-bounds, but acceptable start for the - * left direction, see BPF_REG_FP. + * left direction, see BPF_REG_FP. Also, unknown scalar + * offset where we would need to deal with min/max bounds is + * currently prohibited for unprivileged. */ max = MAX_BPF_STACK + mask_to_left; - /* Indirect variable offset stack access is prohibited in - * unprivileged mode so it's not handled here. - */ - off = ptr_reg->off + ptr_reg->var_off.value; - if (mask_to_left) - ptr_limit = MAX_BPF_STACK + off; - else - ptr_limit = -off - 1; + ptr_limit = -(ptr_reg->var_off.value + ptr_reg->off); break; case PTR_TO_MAP_VALUE: max = ptr_reg->map_ptr->value_size; - if (mask_to_left) { - ptr_limit = ptr_reg->umax_value + ptr_reg->off; - } else { - off = ptr_reg->smin_value + ptr_reg->off; - ptr_limit = ptr_reg->map_ptr->value_size - off - 1; - } + ptr_limit = (mask_to_left ? + ptr_reg->smin_value : + ptr_reg->umax_value) + ptr_reg->off; break; default: return REASON_TYPE; @@ -5954,10 +5946,12 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env, struct bpf_insn *insn, const struct bpf_reg_state *ptr_reg, const struct bpf_reg_state *off_reg, - struct bpf_reg_state *dst_reg) + struct bpf_reg_state *dst_reg, + struct bpf_insn_aux_data *tmp_aux, + const bool commit_window) { + struct bpf_insn_aux_data *aux = commit_window ? cur_aux(env) : tmp_aux; struct bpf_verifier_state *vstate = env->cur_state; - struct bpf_insn_aux_data *aux = cur_aux(env); bool off_is_neg = off_reg->smin_value < 0; bool ptr_is_dst_reg = ptr_reg == dst_reg; u8 opcode = BPF_OP(insn->code); @@ -5976,18 +5970,33 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env, if (vstate->speculative) goto do_sim; - alu_state = off_is_neg ? BPF_ALU_NEG_VALUE : 0; - alu_state |= ptr_is_dst_reg ? - BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST; - err = retrieve_ptr_limit(ptr_reg, off_reg, &alu_limit, opcode); if (err < 0) return err; + if (commit_window) { + /* In commit phase we narrow the masking window based on + * the observed pointer move after the simulated operation. + */ + alu_state = tmp_aux->alu_state; + alu_limit = abs(tmp_aux->alu_limit - alu_limit); + } else { + alu_state = off_is_neg ? BPF_ALU_NEG_VALUE : 0; + alu_state |= ptr_is_dst_reg ? + BPF_ALU_SANITIZE_SRC : BPF_ALU_SANITIZE_DST; + } + err = update_alu_sanitation_state(aux, alu_state, alu_limit); if (err < 0) return err; do_sim: + /* If we're in commit phase, we're done here given we already + * pushed the truncated dst_reg into the speculative verification + * stack. + */ + if (commit_window) + return 0; + /* Simulate and find potential out-of-bounds access under * speculative execution from truncation as a result of * masking when off was not within expected range. If off @@ -6130,6 +6139,7 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, smin_ptr = ptr_reg->smin_value, smax_ptr = ptr_reg->smax_value; u64 umin_val = off_reg->umin_value, umax_val = off_reg->umax_value, umin_ptr = ptr_reg->umin_value, umax_ptr = ptr_reg->umax_value; + struct bpf_insn_aux_data tmp_aux = {}; u8 opcode = BPF_OP(insn->code); u32 dst = insn->dst_reg; int ret; @@ -6196,12 +6206,15 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, /* pointer types do not carry 32-bit bounds at the moment. */ __mark_reg32_unbounded(dst_reg); - switch (opcode) { - case BPF_ADD: - ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg); + if (sanitize_needed(opcode)) { + ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg, + &tmp_aux, false); if (ret < 0) return sanitize_err(env, insn, ret, off_reg, dst_reg); + } + switch (opcode) { + case BPF_ADD: /* We can take a fixed offset as long as it doesn't overflow * the s32 'off' field */ @@ -6252,10 +6265,6 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, } break; case BPF_SUB: - ret = sanitize_ptr_alu(env, insn, ptr_reg, off_reg, dst_reg); - if (ret < 0) - return sanitize_err(env, insn, ret, off_reg, dst_reg); - if (dst_reg == off_reg) { /* scalar -= pointer. Creates an unknown scalar */ verbose(env, "R%d tried to subtract pointer from scalar\n", @@ -6338,6 +6347,12 @@ static int adjust_ptr_min_max_vals(struct bpf_verifier_env *env, if (sanitize_check_bounds(env, insn, dst_reg) < 0) return -EACCES; + if (sanitize_needed(opcode)) { + ret = sanitize_ptr_alu(env, insn, dst_reg, off_reg, dst_reg, + &tmp_aux, true); + if (ret < 0) + return sanitize_err(env, insn, ret, off_reg, dst_reg); + } return 0; } From d7a5091351756d0ae8e63134313c455624e36a13 Mon Sep 17 00:00:00 2001 From: Daniel Borkmann Date: Wed, 24 Mar 2021 14:52:31 +0100 Subject: [PATCH 1035/1091] bpf: Update selftests to reflect new error states Update various selftest error messages: * The 'Rx tried to sub from different maps, paths, or prohibited types' is reworked into more specific/differentiated error messages for better guidance. * The change into 'value -4294967168 makes map_value pointer be out of bounds' is due to moving the mixed bounds check into the speculation handling and thus occuring slightly later than above mentioned sanity check. * The change into 'math between map_value pointer and register with unbounded min value' is similarly due to register sanity check coming before the mixed bounds check. * The case of 'map access: known scalar += value_ptr from different maps' now loads fine given masks are the same from the different paths (despite max map value size being different). Signed-off-by: Daniel Borkmann Reviewed-by: John Fastabend Acked-by: Alexei Starovoitov --- tools/testing/selftests/bpf/verifier/bounds.c | 5 ----- .../selftests/bpf/verifier/bounds_deduction.c | 21 ++++++++++--------- .../bpf/verifier/bounds_mix_sign_unsign.c | 13 ------------ .../testing/selftests/bpf/verifier/map_ptr.c | 4 ++-- tools/testing/selftests/bpf/verifier/unpriv.c | 2 +- .../selftests/bpf/verifier/value_ptr_arith.c | 6 ++---- 6 files changed, 16 insertions(+), 35 deletions(-) diff --git a/tools/testing/selftests/bpf/verifier/bounds.c b/tools/testing/selftests/bpf/verifier/bounds.c index 57ed67b86074..8a1caf46ffbc 100644 --- a/tools/testing/selftests/bpf/verifier/bounds.c +++ b/tools/testing/selftests/bpf/verifier/bounds.c @@ -261,8 +261,6 @@ }, .fixup_map_hash_8b = { 3 }, /* not actually fully unbounded, but the bound is very high */ - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds, pointer arithmetic with it prohibited for !root", - .result_unpriv = REJECT, .errstr = "value -4294967168 makes map_value pointer be out of bounds", .result = REJECT, }, @@ -298,9 +296,6 @@ BPF_EXIT_INSN(), }, .fixup_map_hash_8b = { 3 }, - /* not actually fully unbounded, but the bound is very high */ - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds, pointer arithmetic with it prohibited for !root", - .result_unpriv = REJECT, .errstr = "value -4294967168 makes map_value pointer be out of bounds", .result = REJECT, }, diff --git a/tools/testing/selftests/bpf/verifier/bounds_deduction.c b/tools/testing/selftests/bpf/verifier/bounds_deduction.c index c162498a64fc..91869aea6d64 100644 --- a/tools/testing/selftests/bpf/verifier/bounds_deduction.c +++ b/tools/testing/selftests/bpf/verifier/bounds_deduction.c @@ -6,7 +6,7 @@ BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R0 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .errstr = "R0 tried to subtract pointer from scalar", .result = REJECT, }, @@ -21,7 +21,7 @@ BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R1 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .result_unpriv = REJECT, .result = ACCEPT, .retval = 1, @@ -34,22 +34,23 @@ BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R0 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .errstr = "R0 tried to subtract pointer from scalar", .result = REJECT, }, { "check deducing bounds from const, 4", .insns = { + BPF_MOV64_REG(BPF_REG_6, BPF_REG_1), BPF_MOV64_IMM(BPF_REG_0, 0), BPF_JMP_IMM(BPF_JSLE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(), BPF_JMP_IMM(BPF_JSGE, BPF_REG_0, 0, 1), BPF_EXIT_INSN(), - BPF_ALU64_REG(BPF_SUB, BPF_REG_1, BPF_REG_0), + BPF_ALU64_REG(BPF_SUB, BPF_REG_6, BPF_REG_0), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R1 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R6 has pointer with unsupported alu operation", .result_unpriv = REJECT, .result = ACCEPT, }, @@ -61,7 +62,7 @@ BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R0 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .errstr = "R0 tried to subtract pointer from scalar", .result = REJECT, }, @@ -74,7 +75,7 @@ BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R0 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .errstr = "R0 tried to subtract pointer from scalar", .result = REJECT, }, @@ -88,7 +89,7 @@ offsetof(struct __sk_buff, mark)), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R1 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .errstr = "dereference of modified ctx ptr", .result = REJECT, .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, @@ -103,7 +104,7 @@ offsetof(struct __sk_buff, mark)), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R1 tried to add from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .errstr = "dereference of modified ctx ptr", .result = REJECT, .flags = F_NEEDS_EFFICIENT_UNALIGNED_ACCESS, @@ -116,7 +117,7 @@ BPF_ALU64_REG(BPF_SUB, BPF_REG_0, BPF_REG_1), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R0 tried to sub from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .errstr = "R0 tried to subtract pointer from scalar", .result = REJECT, }, diff --git a/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c b/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c index 9baca7a75c42..c2aa6f26738b 100644 --- a/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c +++ b/tools/testing/selftests/bpf/verifier/bounds_mix_sign_unsign.c @@ -19,7 +19,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -43,7 +42,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -69,7 +67,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R8 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -94,7 +91,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R8 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -141,7 +137,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -210,7 +205,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -260,7 +254,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -287,7 +280,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -313,7 +305,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -342,7 +333,6 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R7 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -372,7 +362,6 @@ }, .fixup_map_hash_8b = { 4 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, }, { @@ -400,7 +389,5 @@ }, .fixup_map_hash_8b = { 3 }, .errstr = "unbounded min value", - .errstr_unpriv = "R1 has unknown scalar with mixed signed bounds", .result = REJECT, - .result_unpriv = REJECT, }, diff --git a/tools/testing/selftests/bpf/verifier/map_ptr.c b/tools/testing/selftests/bpf/verifier/map_ptr.c index 6f610cfddae5..1f82021429bf 100644 --- a/tools/testing/selftests/bpf/verifier/map_ptr.c +++ b/tools/testing/selftests/bpf/verifier/map_ptr.c @@ -76,7 +76,7 @@ }, .fixup_map_hash_16b = { 4 }, .result_unpriv = REJECT, - .errstr_unpriv = "R1 tried to add from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 has pointer with unsupported alu operation", .result = ACCEPT, }, { @@ -94,6 +94,6 @@ }, .fixup_map_hash_16b = { 4 }, .result_unpriv = REJECT, - .errstr_unpriv = "R1 tried to add from different maps, paths, or prohibited types", + .errstr_unpriv = "R0 has pointer with unsupported alu operation", .result = ACCEPT, }, diff --git a/tools/testing/selftests/bpf/verifier/unpriv.c b/tools/testing/selftests/bpf/verifier/unpriv.c index 3e32400c4b44..bd436df5cc32 100644 --- a/tools/testing/selftests/bpf/verifier/unpriv.c +++ b/tools/testing/selftests/bpf/verifier/unpriv.c @@ -505,7 +505,7 @@ BPF_STX_MEM(BPF_DW, BPF_REG_1, BPF_REG_0, -8), BPF_EXIT_INSN(), }, - .errstr_unpriv = "R1 tried to add from different maps, paths, or prohibited types", + .errstr_unpriv = "R1 stack pointer arithmetic goes out of range", .result_unpriv = REJECT, .result = ACCEPT, }, diff --git a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c b/tools/testing/selftests/bpf/verifier/value_ptr_arith.c index feb91266db39..e5913fd3b903 100644 --- a/tools/testing/selftests/bpf/verifier/value_ptr_arith.c +++ b/tools/testing/selftests/bpf/verifier/value_ptr_arith.c @@ -21,8 +21,6 @@ .fixup_map_hash_16b = { 5 }, .fixup_map_array_48b = { 8 }, .result = ACCEPT, - .result_unpriv = REJECT, - .errstr_unpriv = "R1 tried to add from different maps", .retval = 1, }, { @@ -122,7 +120,7 @@ .fixup_map_array_48b = { 1 }, .result = ACCEPT, .result_unpriv = REJECT, - .errstr_unpriv = "R2 tried to add from different pointers or scalars", + .errstr_unpriv = "R2 tried to add from different maps, paths or scalars", .retval = 0, }, { @@ -169,7 +167,7 @@ .fixup_map_array_48b = { 1 }, .result = ACCEPT, .result_unpriv = REJECT, - .errstr_unpriv = "R2 tried to add from different maps, paths, or prohibited types", + .errstr_unpriv = "R2 tried to add from different maps, paths or scalars", .retval = 0, }, { From 6b389c16378a03fe71f3b1365b593ba41d2dd8ec Mon Sep 17 00:00:00 2001 From: Lijun Pan Date: Thu, 15 Apr 2021 23:18:13 -0500 Subject: [PATCH 1036/1091] MAINTAINERS: update my email Update my email and change myself to Reviewer. Signed-off-by: Lijun Pan Signed-off-by: David S. Miller --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 163264c282eb..a31f76c41aec 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -8517,9 +8517,9 @@ F: drivers/pci/hotplug/rpaphp* IBM Power SRIOV Virtual NIC Device Driver M: Dany Madden -M: Lijun Pan M: Sukadev Bhattiprolu R: Thomas Falcon +R: Lijun Pan L: netdev@vger.kernel.org S: Supported F: drivers/net/ethernet/ibm/ibmvnic.* From 845be1cd34464620861b457b808e5fb2115d06b0 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Apr 2021 15:45:54 -0700 Subject: [PATCH 1037/1091] mm: eliminate "expecting prototype" kernel-doc warnings Fix stray kernel-doc warnings in mm/ due to mis-typed or missing function names. Quietens these kernel-doc warnings: mm/mmu_gather.c:264: warning: expecting prototype for tlb_gather_mmu(). Prototype was for __tlb_gather_mmu() instead mm/oom_kill.c:180: warning: expecting prototype for Check whether unreclaimable slab amount is greater than(). Prototype was for should_dump_unreclaim_slab() instead mm/shuffle.c:155: warning: expecting prototype for shuffle_free_memory(). Prototype was for __shuffle_free_memory() instead Link: https://lkml.kernel.org/r/20210411210642.11362-1-rdunlap@infradead.org Signed-off-by: Randy Dunlap Reviewed-by: Matthew Wilcox (Oracle) Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mmu_gather.c | 29 +++++++++++++++++++---------- mm/oom_kill.c | 2 +- mm/shuffle.c | 4 ++-- 3 files changed, 22 insertions(+), 13 deletions(-) diff --git a/mm/mmu_gather.c b/mm/mmu_gather.c index 0dc7149b0c61..1b9837419bf9 100644 --- a/mm/mmu_gather.c +++ b/mm/mmu_gather.c @@ -249,16 +249,6 @@ void tlb_flush_mmu(struct mmu_gather *tlb) tlb_flush_mmu_free(tlb); } -/** - * tlb_gather_mmu - initialize an mmu_gather structure for page-table tear-down - * @tlb: the mmu_gather structure to initialize - * @mm: the mm_struct of the target address space - * @fullmm: @mm is without users and we're going to destroy the full address - * space (exit/execve) - * - * Called to initialize an (on-stack) mmu_gather structure for page-table - * tear-down from @mm. - */ static void __tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, bool fullmm) { @@ -283,11 +273,30 @@ static void __tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm, inc_tlb_flush_pending(tlb->mm); } +/** + * tlb_gather_mmu - initialize an mmu_gather structure for page-table tear-down + * @tlb: the mmu_gather structure to initialize + * @mm: the mm_struct of the target address space + * + * Called to initialize an (on-stack) mmu_gather structure for page-table + * tear-down from @mm. + */ void tlb_gather_mmu(struct mmu_gather *tlb, struct mm_struct *mm) { __tlb_gather_mmu(tlb, mm, false); } +/** + * tlb_gather_mmu_fullmm - initialize an mmu_gather structure for page-table tear-down + * @tlb: the mmu_gather structure to initialize + * @mm: the mm_struct of the target address space + * + * In this case, @mm is without users and we're going to destroy the + * full address space (exit/execve). + * + * Called to initialize an (on-stack) mmu_gather structure for page-table + * tear-down from @mm. + */ void tlb_gather_mmu_fullmm(struct mmu_gather *tlb, struct mm_struct *mm) { __tlb_gather_mmu(tlb, mm, true); diff --git a/mm/oom_kill.c b/mm/oom_kill.c index 9efaf430cfd3..fa1cf18bac97 100644 --- a/mm/oom_kill.c +++ b/mm/oom_kill.c @@ -170,7 +170,7 @@ static bool oom_unkillable_task(struct task_struct *p) return false; } -/** +/* * Check whether unreclaimable slab amount is greater than * all user memory(LRU pages). * dump_unreclaimable_slab() could help in the case that diff --git a/mm/shuffle.c b/mm/shuffle.c index 9c2e145a747a..c13c33b247e8 100644 --- a/mm/shuffle.c +++ b/mm/shuffle.c @@ -147,8 +147,8 @@ void __meminit __shuffle_zone(struct zone *z) spin_unlock_irqrestore(&z->lock, flags); } -/** - * shuffle_free_memory - reduce the predictability of the page allocator +/* + * __shuffle_free_memory - reduce the predictability of the page allocator * @pgdat: node page data */ void __meminit __shuffle_free_memory(pg_data_t *pgdat) From 5c595ac4c776c44b5c59de22ab43b3fe256d9fbb Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Fri, 16 Apr 2021 15:45:57 -0700 Subject: [PATCH 1038/1091] kasan: fix hwasan build for gcc gcc-11 adds support for -fsanitize=kernel-hwaddress, so it becomes possible to enable CONFIG_KASAN_SW_TAGS. Unfortunately this fails to build at the moment, because the corresponding command line arguments use llvm specific syntax. Change it to use the cc-param macro instead, which works on both clang and gcc. [elver@google.com: fixup for "kasan: fix hwasan build for gcc"] Link: https://lkml.kernel.org/r/YHQZVfVVLE/LDK2v@elver.google.com Link: https://lkml.kernel.org/r/20210323124112.1229772-1-arnd@kernel.org Signed-off-by: Arnd Bergmann Signed-off-by: Marco Elver Reviewed-by: Marco Elver Acked-by: Andrey Konovalov Cc: Masahiro Yamada Cc: Michal Marek Cc: Andrey Ryabinin Cc: Nathan Chancellor Cc: Nick Desaulniers Cc: Alexander Potapenko Cc: Dmitry Vyukov Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- scripts/Makefile.kasan | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index 1e000cc2e7b4..127012f45166 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -2,6 +2,8 @@ CFLAGS_KASAN_NOSANITIZE := -fno-builtin KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET) +cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1))) + ifdef CONFIG_KASAN_GENERIC ifdef CONFIG_KASAN_INLINE @@ -12,8 +14,6 @@ endif CFLAGS_KASAN_MINIMAL := -fsanitize=kernel-address -cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1))) - # -fasan-shadow-offset fails without -fsanitize CFLAGS_KASAN_SHADOW := $(call cc-option, -fsanitize=kernel-address \ -fasan-shadow-offset=$(KASAN_SHADOW_OFFSET), \ @@ -36,14 +36,14 @@ endif # CONFIG_KASAN_GENERIC ifdef CONFIG_KASAN_SW_TAGS ifdef CONFIG_KASAN_INLINE - instrumentation_flags := -mllvm -hwasan-mapping-offset=$(KASAN_SHADOW_OFFSET) + instrumentation_flags := $(call cc-param,hwasan-mapping-offset=$(KASAN_SHADOW_OFFSET)) else - instrumentation_flags := -mllvm -hwasan-instrument-with-calls=1 + instrumentation_flags := $(call cc-param,hwasan-instrument-with-calls=1) endif CFLAGS_KASAN := -fsanitize=kernel-hwaddress \ - -mllvm -hwasan-instrument-stack=$(CONFIG_KASAN_STACK) \ - -mllvm -hwasan-use-short-granules=0 \ + $(call cc-param,hwasan-instrument-stack=$(CONFIG_KASAN_STACK)) \ + $(call cc-param,hwasan-use-short-granules=0) \ $(instrumentation_flags) endif # CONFIG_KASAN_SW_TAGS From 02c587733c8161355a43e6e110c2e29bd0acff72 Mon Sep 17 00:00:00 2001 From: Walter Wu Date: Fri, 16 Apr 2021 15:46:00 -0700 Subject: [PATCH 1039/1091] kasan: remove redundant config option CONFIG_KASAN_STACK and CONFIG_KASAN_STACK_ENABLE both enable KASAN stack instrumentation, but we should only need one config, so that we remove CONFIG_KASAN_STACK_ENABLE and make CONFIG_KASAN_STACK workable. see [1]. When enable KASAN stack instrumentation, then for gcc we could do no prompt and default value y, and for clang prompt and default value n. This patch fixes the following compilation warning: include/linux/kasan.h:333:30: warning: 'CONFIG_KASAN_STACK' is not defined, evaluates to 0 [-Wundef] [akpm@linux-foundation.org: fix merge snafu] Link: https://bugzilla.kernel.org/show_bug.cgi?id=210221 [1] Link: https://lkml.kernel.org/r/20210226012531.29231-1-walter-zh.wu@mediatek.com Fixes: d9b571c885a8 ("kasan: fix KASAN_STACK dependency for HW_TAGS") Signed-off-by: Walter Wu Suggested-by: Dmitry Vyukov Reviewed-by: Nathan Chancellor Acked-by: Arnd Bergmann Reviewed-by: Andrey Konovalov Cc: Andrey Ryabinin Cc: Dmitry Vyukov Cc: Alexander Potapenko Cc: Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/arm64/kernel/sleep.S | 2 +- arch/x86/kernel/acpi/wakeup_64.S | 2 +- include/linux/kasan.h | 2 +- lib/Kconfig.kasan | 9 ++------- mm/kasan/common.c | 2 +- mm/kasan/kasan.h | 2 +- mm/kasan/report_generic.c | 2 +- scripts/Makefile.kasan | 10 ++++++++-- security/Kconfig.hardening | 4 ++-- 9 files changed, 18 insertions(+), 17 deletions(-) diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index 5bfd9b87f85d..4ea9392f86e0 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -134,7 +134,7 @@ SYM_FUNC_START(_cpu_resume) */ bl cpu_do_resume -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK) mov x0, sp bl kasan_unpoison_task_stack_below #endif diff --git a/arch/x86/kernel/acpi/wakeup_64.S b/arch/x86/kernel/acpi/wakeup_64.S index 56b6865afb2a..d5d8a352eafa 100644 --- a/arch/x86/kernel/acpi/wakeup_64.S +++ b/arch/x86/kernel/acpi/wakeup_64.S @@ -115,7 +115,7 @@ SYM_FUNC_START(do_suspend_lowlevel) movq pt_regs_r14(%rax), %r14 movq pt_regs_r15(%rax), %r15 -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK) /* * The suspend path may have poisoned some areas deeper in the stack, * which we now need to unpoison. diff --git a/include/linux/kasan.h b/include/linux/kasan.h index b91732bd05d7..14f72ec96492 100644 --- a/include/linux/kasan.h +++ b/include/linux/kasan.h @@ -330,7 +330,7 @@ static inline bool kasan_check_byte(const void *address) #endif /* CONFIG_KASAN */ -#if defined(CONFIG_KASAN) && CONFIG_KASAN_STACK +#if defined(CONFIG_KASAN) && defined(CONFIG_KASAN_STACK) void kasan_unpoison_task_stack(struct task_struct *task); #else static inline void kasan_unpoison_task_stack(struct task_struct *task) {} diff --git a/lib/Kconfig.kasan b/lib/Kconfig.kasan index fba9909e31b7..cffc2ebbf185 100644 --- a/lib/Kconfig.kasan +++ b/lib/Kconfig.kasan @@ -138,9 +138,10 @@ config KASAN_INLINE endchoice -config KASAN_STACK_ENABLE +config KASAN_STACK bool "Enable stack instrumentation (unsafe)" if CC_IS_CLANG && !COMPILE_TEST depends on KASAN_GENERIC || KASAN_SW_TAGS + default y if CC_IS_GCC help The LLVM stack address sanitizer has a know problem that causes excessive stack usage in a lot of functions, see @@ -154,12 +155,6 @@ config KASAN_STACK_ENABLE CONFIG_COMPILE_TEST. On gcc it is assumed to always be safe to use and enabled by default. -config KASAN_STACK - int - depends on KASAN_GENERIC || KASAN_SW_TAGS - default 1 if KASAN_STACK_ENABLE || CC_IS_GCC - default 0 - config KASAN_SW_TAGS_IDENTIFY bool "Enable memory corruption identification" depends on KASAN_SW_TAGS diff --git a/mm/kasan/common.c b/mm/kasan/common.c index b5e08d4cefec..7b53291dafa1 100644 --- a/mm/kasan/common.c +++ b/mm/kasan/common.c @@ -63,7 +63,7 @@ void __kasan_unpoison_range(const void *address, size_t size) kasan_unpoison(address, size); } -#if CONFIG_KASAN_STACK +#ifdef CONFIG_KASAN_STACK /* Unpoison the entire stack for a task. */ void kasan_unpoison_task_stack(struct task_struct *task) { diff --git a/mm/kasan/kasan.h b/mm/kasan/kasan.h index 8c55634d6edd..3436c6bf7c0c 100644 --- a/mm/kasan/kasan.h +++ b/mm/kasan/kasan.h @@ -231,7 +231,7 @@ void *kasan_find_first_bad_addr(void *addr, size_t size); const char *kasan_get_bug_type(struct kasan_access_info *info); void kasan_metadata_fetch_row(char *buffer, void *row); -#if defined(CONFIG_KASAN_GENERIC) && CONFIG_KASAN_STACK +#if defined(CONFIG_KASAN_GENERIC) && defined(CONFIG_KASAN_STACK) void kasan_print_address_stack_frame(const void *addr); #else static inline void kasan_print_address_stack_frame(const void *addr) { } diff --git a/mm/kasan/report_generic.c b/mm/kasan/report_generic.c index 41f374585144..de732bc341c5 100644 --- a/mm/kasan/report_generic.c +++ b/mm/kasan/report_generic.c @@ -128,7 +128,7 @@ void kasan_metadata_fetch_row(char *buffer, void *row) memcpy(buffer, kasan_mem_to_shadow(row), META_BYTES_PER_ROW); } -#if CONFIG_KASAN_STACK +#ifdef CONFIG_KASAN_STACK static bool __must_check tokenize_frame_descr(const char **frame_descr, char *token, size_t max_tok_len, unsigned long *value) diff --git a/scripts/Makefile.kasan b/scripts/Makefile.kasan index 127012f45166..3d791908ed36 100644 --- a/scripts/Makefile.kasan +++ b/scripts/Makefile.kasan @@ -4,6 +4,12 @@ KASAN_SHADOW_OFFSET ?= $(CONFIG_KASAN_SHADOW_OFFSET) cc-param = $(call cc-option, -mllvm -$(1), $(call cc-option, --param $(1))) +ifdef CONFIG_KASAN_STACK + stack_enable := 1 +else + stack_enable := 0 +endif + ifdef CONFIG_KASAN_GENERIC ifdef CONFIG_KASAN_INLINE @@ -27,7 +33,7 @@ else CFLAGS_KASAN := $(CFLAGS_KASAN_SHADOW) \ $(call cc-param,asan-globals=1) \ $(call cc-param,asan-instrumentation-with-call-threshold=$(call_threshold)) \ - $(call cc-param,asan-stack=$(CONFIG_KASAN_STACK)) \ + $(call cc-param,asan-stack=$(stack_enable)) \ $(call cc-param,asan-instrument-allocas=1) endif @@ -42,7 +48,7 @@ else endif CFLAGS_KASAN := -fsanitize=kernel-hwaddress \ - $(call cc-param,hwasan-instrument-stack=$(CONFIG_KASAN_STACK)) \ + $(call cc-param,hwasan-instrument-stack=$(stack_enable)) \ $(call cc-param,hwasan-use-short-granules=0) \ $(instrumentation_flags) diff --git a/security/Kconfig.hardening b/security/Kconfig.hardening index 269967c4fc1b..a56c36470cb1 100644 --- a/security/Kconfig.hardening +++ b/security/Kconfig.hardening @@ -64,7 +64,7 @@ choice config GCC_PLUGIN_STRUCTLEAK_BYREF bool "zero-init structs passed by reference (strong)" depends on GCC_PLUGINS - depends on !(KASAN && KASAN_STACK=1) + depends on !(KASAN && KASAN_STACK) select GCC_PLUGIN_STRUCTLEAK help Zero-initialize any structures on the stack that may @@ -82,7 +82,7 @@ choice config GCC_PLUGIN_STRUCTLEAK_BYREF_ALL bool "zero-init anything passed by reference (very strong)" depends on GCC_PLUGINS - depends on !(KASAN && KASAN_STACK=1) + depends on !(KASAN && KASAN_STACK) select GCC_PLUGIN_STRUCTLEAK help Zero-initialize any stack variables that may be passed From d199161653d612b8fb96ac51bfd5b2d2782ecef3 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Apr 2021 15:46:03 -0700 Subject: [PATCH 1040/1091] csky: change a Kconfig symbol name to fix e1000 build error e1000's #define of CONFIG_RAM_BASE conflicts with a Kconfig symbol in arch/csky/Kconfig. The symbol in e1000 has been around longer, so change arch/csky/ to use DRAM_BASE instead of RAM_BASE to remove the conflict. (although e1000 is also a 2-line change) Link: https://lkml.kernel.org/r/20210411055335.7111-1-rdunlap@infradead.org Signed-off-by: Randy Dunlap Reported-by: kernel test robot Acked-by: Guo Ren Cc: Jesse Brandeburg Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/csky/Kconfig | 2 +- arch/csky/include/asm/page.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/csky/Kconfig b/arch/csky/Kconfig index 34e91224adc3..8de5b987edb9 100644 --- a/arch/csky/Kconfig +++ b/arch/csky/Kconfig @@ -314,7 +314,7 @@ config FORCE_MAX_ZONEORDER int "Maximum zone order" default "11" -config RAM_BASE +config DRAM_BASE hex "DRAM start addr (the same with memory-section in dts)" default 0x0 diff --git a/arch/csky/include/asm/page.h b/arch/csky/include/asm/page.h index 3b91fc3cf36f..ed7451478b1b 100644 --- a/arch/csky/include/asm/page.h +++ b/arch/csky/include/asm/page.h @@ -28,7 +28,7 @@ #define SSEG_SIZE 0x20000000 #define LOWMEM_LIMIT (SSEG_SIZE * 2) -#define PHYS_OFFSET_OFFSET (CONFIG_RAM_BASE & (SSEG_SIZE - 1)) +#define PHYS_OFFSET_OFFSET (CONFIG_DRAM_BASE & (SSEG_SIZE - 1)) #ifndef __ASSEMBLY__ From 19d000d93303e05bd7b1326e3de9df05a41b25b5 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Apr 2021 15:46:06 -0700 Subject: [PATCH 1041/1091] ia64: remove duplicate entries in generic_defconfig Fix ia64 generic_defconfig duplicate entries, as warned by: arch/ia64/configs/generic_defconfig: warning: override: reassigning to symbol ATA: => 58 arch/ia64/configs/generic_defconfig: warning: override: reassigning to symbol ATA_PIIX: => 59 These 2 symbols still have the same value as in the removed lines. Link: https://lkml.kernel.org/r/20210411020255.18052-1-rdunlap@infradead.org Fixes: c331649e6371 ("ia64: Use libata instead of the legacy ide driver in defconfigs") Signed-off-by: Randy Dunlap Reported-by: Geert Uytterhoeven Reviewed-by: Christoph Hellwig Cc: Tony Luck Cc: Fenghua Yu Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/configs/generic_defconfig | 2 -- 1 file changed, 2 deletions(-) diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig index ca0d596c800d..8916a2850c48 100644 --- a/arch/ia64/configs/generic_defconfig +++ b/arch/ia64/configs/generic_defconfig @@ -55,8 +55,6 @@ CONFIG_CHR_DEV_SG=m CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_QLOGIC_1280=y -CONFIG_ATA=y -CONFIG_ATA_PIIX=y CONFIG_SATA_VITESSE=y CONFIG_MD=y CONFIG_BLK_DEV_MD=m From e2af9da4f867a1a54f1252bf3abc1a5c63951778 Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Apr 2021 15:46:09 -0700 Subject: [PATCH 1042/1091] ia64: fix discontig.c section mismatches Fix IA64 discontig.c Section mismatch warnings. When CONFIG_SPARSEMEM=y and CONFIG_MEMORY_HOTPLUG=y, the functions computer_pernodesize() and scatter_node_data() should not be marked as __meminit because they are needed after init, on any memory hotplug event. Also, early_nr_cpus_node() is called by compute_pernodesize(), so early_nr_cpus_node() cannot be __meminit either. WARNING: modpost: vmlinux.o(.text.unlikely+0x1612): Section mismatch in reference from the function arch_alloc_nodedata() to the function .meminit.text:compute_pernodesize() The function arch_alloc_nodedata() references the function __meminit compute_pernodesize(). This is often because arch_alloc_nodedata lacks a __meminit annotation or the annotation of compute_pernodesize is wrong. WARNING: modpost: vmlinux.o(.text.unlikely+0x1692): Section mismatch in reference from the function arch_refresh_nodedata() to the function .meminit.text:scatter_node_data() The function arch_refresh_nodedata() references the function __meminit scatter_node_data(). This is often because arch_refresh_nodedata lacks a __meminit annotation or the annotation of scatter_node_data is wrong. WARNING: modpost: vmlinux.o(.text.unlikely+0x1502): Section mismatch in reference from the function compute_pernodesize() to the function .meminit.text:early_nr_cpus_node() The function compute_pernodesize() references the function __meminit early_nr_cpus_node(). This is often because compute_pernodesize lacks a __meminit annotation or the annotation of early_nr_cpus_node is wrong. Link: https://lkml.kernel.org/r/20210411001201.3069-1-rdunlap@infradead.org Signed-off-by: Randy Dunlap Cc: Mike Rapoport Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/ia64/mm/discontig.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/ia64/mm/discontig.c b/arch/ia64/mm/discontig.c index 03b3a02375ff..c310b4c99fb3 100644 --- a/arch/ia64/mm/discontig.c +++ b/arch/ia64/mm/discontig.c @@ -95,7 +95,7 @@ static int __init build_node_maps(unsigned long start, unsigned long len, * acpi_boot_init() (which builds the node_to_cpu_mask array) hasn't been * called yet. Note that node 0 will also count all non-existent cpus. */ -static int __meminit early_nr_cpus_node(int node) +static int early_nr_cpus_node(int node) { int cpu, n = 0; @@ -110,7 +110,7 @@ static int __meminit early_nr_cpus_node(int node) * compute_pernodesize - compute size of pernode data * @node: the node id. */ -static unsigned long __meminit compute_pernodesize(int node) +static unsigned long compute_pernodesize(int node) { unsigned long pernodesize = 0, cpus; @@ -367,7 +367,7 @@ static void __init reserve_pernode_space(void) } } -static void __meminit scatter_node_data(void) +static void scatter_node_data(void) { pg_data_t **dst; int node; From 17786fea414393813b56e33a1a01b2dfa03c0915 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Fri, 16 Apr 2021 15:46:12 -0700 Subject: [PATCH 1043/1091] ia64: tools: remove inclusion of ia64-specific version of errno.h header There is no longer an ia64-specific version of the errno.h header below arch/ia64/include/uapi/asm/, so trying to build tools/bpf fails with: CC /usr/src/linux/tools/bpf/bpftool/btf_dumper.o In file included from /usr/src/linux/tools/include/linux/err.h:8, from btf_dumper.c:11: /usr/src/linux/tools/include/uapi/asm/errno.h:13:10: fatal error: ../../../arch/ia64/include/uapi/asm/errno.h: No such file or directory 13 | #include "../../../arch/ia64/include/uapi/asm/errno.h" | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ compilation terminated. Thus, just remove the inclusion of the ia64-specific errno.h so that the build will use the generic errno.h header on this target which was used there anyway as the ia64-specific errno.h was just a wrapper for the generic header. Fixes: c25f867ddd00 ("ia64: remove unneeded uapi asm-generic wrappers") Signed-off-by: John Paul Adrian Glaubitz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/include/uapi/asm/errno.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/include/uapi/asm/errno.h b/tools/include/uapi/asm/errno.h index 637189ec1ab9..d30439b4b8ab 100644 --- a/tools/include/uapi/asm/errno.h +++ b/tools/include/uapi/asm/errno.h @@ -9,8 +9,6 @@ #include "../../../arch/alpha/include/uapi/asm/errno.h" #elif defined(__mips__) #include "../../../arch/mips/include/uapi/asm/errno.h" -#elif defined(__ia64__) -#include "../../../arch/ia64/include/uapi/asm/errno.h" #elif defined(__xtensa__) #include "../../../arch/xtensa/include/uapi/asm/errno.h" #else From f4bf09dc3aaa4b07cd15630f2023f68cb2668809 Mon Sep 17 00:00:00 2001 From: John Paul Adrian Glaubitz Date: Fri, 16 Apr 2021 15:46:15 -0700 Subject: [PATCH 1044/1091] ia64: tools: remove duplicate definition of ia64_mf() on ia64 The ia64_mf() macro defined in tools/arch/ia64/include/asm/barrier.h is already defined in on ia64 which causes libbpf failing to build: CC /usr/src/linux/tools/bpf/bpftool//libbpf/staticobjs/libbpf.o In file included from /usr/src/linux/tools/include/asm/barrier.h:24, from /usr/src/linux/tools/include/linux/ring_buffer.h:4, from libbpf.c:37: /usr/src/linux/tools/include/asm/../../arch/ia64/include/asm/barrier.h:43: error: "ia64_mf" redefined [-Werror] 43 | #define ia64_mf() asm volatile ("mf" ::: "memory") | In file included from /usr/include/ia64-linux-gnu/asm/intrinsics.h:20, from /usr/include/ia64-linux-gnu/asm/swab.h:11, from /usr/include/linux/swab.h:8, from /usr/include/linux/byteorder/little_endian.h:13, from /usr/include/ia64-linux-gnu/asm/byteorder.h:5, from /usr/src/linux/tools/include/uapi/linux/perf_event.h:20, from libbpf.c:36: /usr/include/ia64-linux-gnu/asm/gcc_intrin.h:382: note: this is the location of the previous definition 382 | #define ia64_mf() __asm__ volatile ("mf" ::: "memory") | cc1: all warnings being treated as errors Thus, remove the definition from tools/arch/ia64/include/asm/barrier.h. Signed-off-by: John Paul Adrian Glaubitz Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- tools/arch/ia64/include/asm/barrier.h | 3 --- 1 file changed, 3 deletions(-) diff --git a/tools/arch/ia64/include/asm/barrier.h b/tools/arch/ia64/include/asm/barrier.h index 4d471d9511a5..6fffe5682713 100644 --- a/tools/arch/ia64/include/asm/barrier.h +++ b/tools/arch/ia64/include/asm/barrier.h @@ -39,9 +39,6 @@ * sequential memory pages only. */ -/* XXX From arch/ia64/include/uapi/asm/gcc_intrin.h */ -#define ia64_mf() asm volatile ("mf" ::: "memory") - #define mb() ia64_mf() #define rmb() mb() #define wmb() mb() From 94036f4c884377bdf2da1ba7666c9599d6df0191 Mon Sep 17 00:00:00 2001 From: Zack Rusin Date: Fri, 16 Apr 2021 15:46:18 -0700 Subject: [PATCH 1045/1091] mm/mapping_dirty_helpers: guard hugepage pud's usage Mapping dirty helpers have, so far, been only used on X86, but a port of vmwgfx to ARM64 exposed a problem which results in a compilation error on ARM64 systems: mm/mapping_dirty_helpers.c: In function `wp_clean_pud_entry': mm/mapping_dirty_helpers.c:172:32: error: implicit declaration of function `pud_dirty'; did you mean `pmd_dirty'? [-Werror=implicit-function-declaration] This is due to the fact that mapping_dirty_helpers code assumes that pud_dirty is always defined, which is not the case for architectures that don't define CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD. ARM64 arch is a little inconsistent when it comes to PUD hugepage helpers, e.g. it defines pud_young but not pud_dirty but regardless of that the core kernel code shouldn't assume that any of the PUD hugepage helpers are available unless CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD is defined. This prevents compilation errors whenever one of the drivers is ported to new architectures. Link: https://lkml.kernel.org/r/20210409165151.694574-1-zackr@vmware.com Signed-off-by: Zack Rusin Reviewed-by: Thomas Hellstrm (Intel) Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/mapping_dirty_helpers.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mm/mapping_dirty_helpers.c b/mm/mapping_dirty_helpers.c index b59054ef2e10..b890854ec761 100644 --- a/mm/mapping_dirty_helpers.c +++ b/mm/mapping_dirty_helpers.c @@ -165,10 +165,12 @@ static int wp_clean_pud_entry(pud_t *pud, unsigned long addr, unsigned long end, return 0; } +#ifdef CONFIG_HAVE_ARCH_TRANSPARENT_HUGEPAGE_PUD /* Huge pud */ walk->action = ACTION_CONTINUE; if (pud_trans_huge(pudval) || pud_devmap(pudval)) WARN_ON(pud_write(pudval) || pud_dirty(pudval)); +#endif return 0; } From 458376913d86bed2fb781b4952eb6861675ef3be Mon Sep 17 00:00:00 2001 From: Christophe Leroy Date: Fri, 16 Apr 2021 15:46:20 -0700 Subject: [PATCH 1046/1091] mm: ptdump: fix build failure READ_ONCE() cannot be used for reading PTEs. Use ptep_get() instead, to avoid the following errors: CC mm/ptdump.o In file included from : mm/ptdump.c: In function 'ptdump_pte_entry': include/linux/compiler_types.h:320:38: error: call to '__compiletime_assert_207' declared with attribute error: Unsupported access size for {READ,WRITE}_ONCE(). 320 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^ include/linux/compiler_types.h:301:4: note: in definition of macro '__compiletime_assert' 301 | prefix ## suffix(); \ | ^~~~~~ include/linux/compiler_types.h:320:2: note: in expansion of macro '_compiletime_assert' 320 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__) | ^~~~~~~~~~~~~~~~~~~ include/asm-generic/rwonce.h:36:2: note: in expansion of macro 'compiletime_assert' 36 | compiletime_assert(__native_word(t) || sizeof(t) == sizeof(long long), \ | ^~~~~~~~~~~~~~~~~~ include/asm-generic/rwonce.h:49:2: note: in expansion of macro 'compiletime_assert_rwonce_type' 49 | compiletime_assert_rwonce_type(x); \ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ mm/ptdump.c:114:14: note: in expansion of macro 'READ_ONCE' 114 | pte_t val = READ_ONCE(*pte); | ^~~~~~~~~ make[2]: *** [mm/ptdump.o] Error 1 See commit 481e980a7c19 ("mm: Allow arches to provide ptep_get()") and commit c0e1c8c22beb ("powerpc/8xx: Provide ptep_get() with 16k pages") for details. Link: https://lkml.kernel.org/r/912b349e2bcaa88939904815ca0af945740c6bd4.1618478922.git.christophe.leroy@csgroup.eu Fixes: 30d621f6723b ("mm: add generic ptdump") Signed-off-by: Christophe Leroy Cc: Steven Price Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- mm/ptdump.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mm/ptdump.c b/mm/ptdump.c index 4354c1422d57..da751448d0e4 100644 --- a/mm/ptdump.c +++ b/mm/ptdump.c @@ -111,7 +111,7 @@ static int ptdump_pte_entry(pte_t *pte, unsigned long addr, unsigned long next, struct mm_walk *walk) { struct ptdump_state *st = walk->private; - pte_t val = READ_ONCE(*pte); + pte_t val = ptep_get(pte); if (st->effective_prot) st->effective_prot(st, 4, pte_val(val)); From 04c53de57cb6435738961dace8b1b71d3ecd3c39 Mon Sep 17 00:00:00 2001 From: Johannes Berg Date: Fri, 16 Apr 2021 15:46:23 -0700 Subject: [PATCH 1047/1091] gcov: clang: fix clang-11+ build With clang-11+, the code is broken due to my kvmalloc() conversion (which predated the clang-11 support code) leaving one vmalloc() in place. Fix that. Link: https://lkml.kernel.org/r/20210412214210.6e1ecca9cdc5.I24459763acf0591d5e6b31c7e3a59890d802f79c@changeid Signed-off-by: Johannes Berg Reviewed-by: Nick Desaulniers Tested-by: Nick Desaulniers Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- kernel/gcov/clang.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel/gcov/clang.c b/kernel/gcov/clang.c index c466c7fbdece..b81f2823630d 100644 --- a/kernel/gcov/clang.c +++ b/kernel/gcov/clang.c @@ -369,7 +369,7 @@ static struct gcov_fn_info *gcov_fn_info_dup(struct gcov_fn_info *fn) INIT_LIST_HEAD(&fn_dup->head); cv_size = fn->num_counters * sizeof(fn->counters[0]); - fn_dup->counters = vmalloc(cv_size); + fn_dup->counters = kvmalloc(cv_size, GFP_KERNEL); if (!fn_dup->counters) { kfree(fn_dup); return NULL; From c95c2d328cd051484bea161e66dfa715c02a7d7e Mon Sep 17 00:00:00 2001 From: Randy Dunlap Date: Fri, 16 Apr 2021 15:46:26 -0700 Subject: [PATCH 1048/1091] lib: remove "expecting prototype" kernel-doc warnings Fix various kernel-doc warnings in lib/ due to missing or erroneous function names. Add kernel-doc for some function parameters that was missing. Use kernel-doc "Return:" notation in earlycpio.c. Quietens the following warnings: lib/earlycpio.c:61: warning: expecting prototype for cpio_data find_cpio_data(). Prototype was for find_cpio_data() instead lib/lru_cache.c:640: warning: expecting prototype for lc_dump(). Prototype was for lc_seq_dump_details() instead lru_cache.c:90: warning: Function parameter or member 'cache' not described in 'lc_create' lib/parman.c:368: warning: expecting prototype for parman_item_del(). Prototype was for parman_item_remove() instead parman.c:309: warning: Excess function parameter 'prority' description in 'parman_prio_init' lib/radix-tree.c:703: warning: expecting prototype for __radix_tree_insert(). Prototype was for radix_tree_insert() instead radix-tree.c:180: warning: Excess function parameter 'addr' description in 'radix_tree_find_next_bit' radix-tree.c:180: warning: Excess function parameter 'size' description in 'radix_tree_find_next_bit' radix-tree.c:931: warning: Function parameter or member 'iter' not described in 'radix_tree_iter_replace' Link: https://lkml.kernel.org/r/20210411221756.15461-1-rdunlap@infradead.org Signed-off-by: Randy Dunlap Cc: Philipp Reisner Cc: Lars Ellenberg Cc: Jiri Pirko Cc: Matthew Wilcox Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- lib/earlycpio.c | 4 ++-- lib/lru_cache.c | 3 ++- lib/parman.c | 4 ++-- lib/radix-tree.c | 11 ++++++----- 4 files changed, 12 insertions(+), 10 deletions(-) diff --git a/lib/earlycpio.c b/lib/earlycpio.c index e83628882001..7921193f0424 100644 --- a/lib/earlycpio.c +++ b/lib/earlycpio.c @@ -40,7 +40,7 @@ enum cpio_fields { }; /** - * cpio_data find_cpio_data - Search for files in an uncompressed cpio + * find_cpio_data - Search for files in an uncompressed cpio * @path: The directory to search for, including a slash at the end * @data: Pointer to the cpio archive or a header inside * @len: Remaining length of the cpio based on data pointer @@ -49,7 +49,7 @@ enum cpio_fields { * matching file itself. It can be used to iterate through the cpio * to find all files inside of a directory path. * - * @return: struct cpio_data containing the address, length and + * Return: &struct cpio_data containing the address, length and * filename (with the directory path cut off) of the found file. * If you search for a filename and not for files in a directory, * pass the absolute path of the filename in the cpio and make sure diff --git a/lib/lru_cache.c b/lib/lru_cache.c index c69ee53d8dde..52313acbfa62 100644 --- a/lib/lru_cache.c +++ b/lib/lru_cache.c @@ -76,6 +76,7 @@ int lc_try_lock(struct lru_cache *lc) /** * lc_create - prepares to track objects in an active set * @name: descriptive name only used in lc_seq_printf_stats and lc_seq_dump_details + * @cache: cache root pointer * @max_pending_changes: maximum changes to accumulate until a transaction is required * @e_count: number of elements allowed to be active simultaneously * @e_size: size of the tracked objects @@ -627,7 +628,7 @@ void lc_set(struct lru_cache *lc, unsigned int enr, int index) } /** - * lc_dump - Dump a complete LRU cache to seq in textual form. + * lc_seq_dump_details - Dump a complete LRU cache to seq in textual form. * @lc: the lru cache to operate on * @seq: the &struct seq_file pointer to seq_printf into * @utext: user supplied additional "heading" or other info diff --git a/lib/parman.c b/lib/parman.c index a11f2f667639..3f8f8d422e62 100644 --- a/lib/parman.c +++ b/lib/parman.c @@ -297,7 +297,7 @@ EXPORT_SYMBOL(parman_destroy); * parman_prio_init - initializes a parman priority chunk * @parman: parman instance * @prio: parman prio structure to be initialized - * @prority: desired priority of the chunk + * @priority: desired priority of the chunk * * Note: all locking must be provided by the caller. * @@ -356,7 +356,7 @@ int parman_item_add(struct parman *parman, struct parman_prio *prio, EXPORT_SYMBOL(parman_item_add); /** - * parman_item_del - deletes parman item + * parman_item_remove - deletes parman item * @parman: parman instance * @prio: parman prio instance to delete the item from * @item: parman item instance diff --git a/lib/radix-tree.c b/lib/radix-tree.c index 3a4da11b804d..b3afafe46fff 100644 --- a/lib/radix-tree.c +++ b/lib/radix-tree.c @@ -166,9 +166,9 @@ static inline void all_tag_set(struct radix_tree_node *node, unsigned int tag) /** * radix_tree_find_next_bit - find the next set bit in a memory region * - * @addr: The address to base the search on - * @size: The bitmap size in bits - * @offset: The bitnumber to start searching at + * @node: where to begin the search + * @tag: the tag index + * @offset: the bitnumber to start searching at * * Unrollable variant of find_next_bit() for constant size arrays. * Tail bits starting from size to roundup(size, BITS_PER_LONG) must be zero. @@ -461,7 +461,7 @@ out: /** * radix_tree_shrink - shrink radix tree to minimum height - * @root radix tree root + * @root: radix tree root */ static inline bool radix_tree_shrink(struct radix_tree_root *root) { @@ -691,7 +691,7 @@ static inline int insert_entries(struct radix_tree_node *node, } /** - * __radix_tree_insert - insert into a radix tree + * radix_tree_insert - insert into a radix tree * @root: radix tree root * @index: index key * @item: item to insert @@ -919,6 +919,7 @@ EXPORT_SYMBOL(radix_tree_replace_slot); /** * radix_tree_iter_replace - replace item in a slot * @root: radix tree root + * @iter: iterator state * @slot: pointer to slot * @item: new item to store in the slot. * From f2764bd4f6a8dffaec3e220728385d9756b3c2cb Mon Sep 17 00:00:00 2001 From: Florian Westphal Date: Fri, 16 Apr 2021 21:29:13 +0200 Subject: [PATCH 1049/1091] netlink: don't call ->netlink_bind with table lock held When I added support to allow generic netlink multicast groups to be restricted to subscribers with CAP_NET_ADMIN I was unaware that a genl_bind implementation already existed in the past. It was reverted due to ABBA deadlock: 1. ->netlink_bind gets called with the table lock held. 2. genetlink bind callback is invoked, it grabs the genl lock. But when a new genl subsystem is (un)registered, these two locks are taken in reverse order. One solution would be to revert again and add a comment in genl referring 1e82a62fec613, "genetlink: remove genl_bind"). This would need a second change in mptcp to not expose the raw token value anymore, e.g. by hashing the token with a secret key so userspace can still associate subflow events with the correct mptcp connection. However, Paolo Abeni reminded me to double-check why the netlink table is locked in the first place. I can't find one. netlink_bind() is already called without this lock when userspace joins a group via NETLINK_ADD_MEMBERSHIP setsockopt. Same holds for the netlink_unbind operation. Digging through the history, commit f773608026ee1 ("netlink: access nlk groups safely in netlink bind and getname") expanded the lock scope. commit 3a20773beeeeade ("net: netlink: cap max groups which will be considered in netlink_bind()") ... removed the nlk->ngroups access that the lock scope extension was all about. Reduce the lock scope again and always call ->netlink_bind without the table lock. The Fixes tag should be vs. the patch mentioned in the link below, but that one got squash-merged into the patch that came earlier in the series. Fixes: 4d54cc32112d8d ("mptcp: avoid lock_fast usage in accept path") Link: https://lore.kernel.org/mptcp/20210213000001.379332-8-mathew.j.martineau@linux.intel.com/T/#u Cc: Cong Wang Cc: Xin Long Cc: Johannes Berg Cc: Sean Tranchetti Cc: Paolo Abeni Cc: Pablo Neira Ayuso Signed-off-by: Florian Westphal Signed-off-by: David S. Miller --- net/netlink/af_netlink.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c index dd488938447f..3a62f97acf39 100644 --- a/net/netlink/af_netlink.c +++ b/net/netlink/af_netlink.c @@ -1019,7 +1019,6 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, return -EINVAL; } - netlink_lock_table(); if (nlk->netlink_bind && groups) { int group; @@ -1031,13 +1030,14 @@ static int netlink_bind(struct socket *sock, struct sockaddr *addr, if (!err) continue; netlink_undo_bind(group, groups, sk); - goto unlock; + return err; } } /* No need for barriers here as we return to user-space without * using any of the bound attributes. */ + netlink_lock_table(); if (!bound) { err = nladdr->nl_pid ? netlink_insert(sk, nladdr->nl_pid) : From fae8817ae804a682c6823ad1672438f39fc46c28 Mon Sep 17 00:00:00 2001 From: Dan Williams Date: Fri, 16 Apr 2021 17:43:30 -0700 Subject: [PATCH 1050/1091] cxl/mem: Fix memory device capacity probing The CXL Identify Memory Device output payload emits capacity in 256MB units. The driver is treating the capacity field as bytes. This was missed because QEMU reports bytes when it should report bytes / 256MB. Fixes: 8adaf747c9f0 ("cxl/mem: Find device capabilities") Reviewed-by: Vishal Verma Cc: Ben Widawsky Link: https://lore.kernel.org/r/161862021044.3259705.7008520073059739760.stgit@dwillia2-desk3.amr.corp.intel.com Signed-off-by: Dan Williams --- drivers/cxl/mem.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/drivers/cxl/mem.c b/drivers/cxl/mem.c index 1b5078311f7d..2acc6173da36 100644 --- a/drivers/cxl/mem.c +++ b/drivers/cxl/mem.c @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -1419,6 +1420,7 @@ out: */ static int cxl_mem_identify(struct cxl_mem *cxlm) { + /* See CXL 2.0 Table 175 Identify Memory Device Output Payload */ struct cxl_mbox_identify { char fw_revision[0x10]; __le64 total_capacity; @@ -1447,10 +1449,11 @@ static int cxl_mem_identify(struct cxl_mem *cxlm) * For now, only the capacity is exported in sysfs */ cxlm->ram_range.start = 0; - cxlm->ram_range.end = le64_to_cpu(id.volatile_capacity) - 1; + cxlm->ram_range.end = le64_to_cpu(id.volatile_capacity) * SZ_256M - 1; cxlm->pmem_range.start = 0; - cxlm->pmem_range.end = le64_to_cpu(id.persistent_capacity) - 1; + cxlm->pmem_range.end = + le64_to_cpu(id.persistent_capacity) * SZ_256M - 1; memcpy(cxlm->firmware_version, id.fw_revision, sizeof(id.fw_revision)); From 0c93ac69407d63a85be0129aa55ffaec27ffebd3 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sat, 17 Apr 2021 09:27:04 -0700 Subject: [PATCH 1051/1091] readdir: make sure to verify directory entry for legacy interfaces too This does the directory entry name verification for the legacy "fillonedir" (and compat) interface that goes all the way back to the dark ages before we had a proper dirent, and the readdir() system call returned just a single entry at a time. Nobody should use this interface unless you still have binaries from 1991, but let's do it right. This came up during discussions about unsafe_copy_to_user() and proper checking of all the inputs to it, as the networking layer is looking to use it in a few new places. So let's make sure the _old_ users do it all right and proper, before we add new ones. See also commit 8a23eb804ca4 ("Make filldir[64]() verify the directory entry filename is valid") which did the proper modern interfaces that people actually use. It had a note: Note that I didn't bother adding the checks to any legacy interfaces that nobody uses. which this now corrects. Note that we really don't care about POSIX and the presense of '/' in a directory entry, but verify_dirent_name() also ends up doing the proper name length verification which is what the input checking discussion was about. [ Another option would be to remove the support for this particular very old interface: any binaries that use it are likely a.out binaries, and they will no longer run anyway since we removed a.out binftm support in commit eac616557050 ("x86: Deprecate a.out support"). But I'm not sure which came first: getdents() or ELF support, so let's pretend somebody might still have a working binary that uses the legacy readdir() case.. ] Link: https://lore.kernel.org/lkml/CAHk-=wjbvzCAhAtvG0d81W5o0-KT5PPTHhfJ5ieDFq+bGtgOYg@mail.gmail.com/ Acked-by: Al Viro Signed-off-by: Linus Torvalds --- fs/readdir.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/fs/readdir.c b/fs/readdir.c index 19434b3c982c..09e8ed7d4161 100644 --- a/fs/readdir.c +++ b/fs/readdir.c @@ -150,6 +150,9 @@ static int fillonedir(struct dir_context *ctx, const char *name, int namlen, if (buf->result) return -EINVAL; + buf->result = verify_dirent_name(name, namlen); + if (buf->result < 0) + return buf->result; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->result = -EOVERFLOW; @@ -405,6 +408,9 @@ static int compat_fillonedir(struct dir_context *ctx, const char *name, if (buf->result) return -EINVAL; + buf->result = verify_dirent_name(name, namlen); + if (buf->result < 0) + return buf->result; d_ino = ino; if (sizeof(d_ino) < sizeof(ino) && d_ino != ino) { buf->result = -EOVERFLOW; From d2f7eca60b29006285d57c7035539e33300e89e5 Mon Sep 17 00:00:00 2001 From: Fredrik Strupe Date: Mon, 5 Apr 2021 21:52:05 +0100 Subject: [PATCH 1052/1091] ARM: 9071/1: uprobes: Don't hook on thumb instructions Since uprobes is not supported for thumb, check that the thumb bit is not set when matching the uprobes instruction hooks. The Arm UDF instructions used for uprobes triggering (UPROBE_SWBP_ARM_INSN and UPROBE_SS_ARM_INSN) coincidentally share the same encoding as a pair of unallocated 32-bit thumb instructions (not UDF) when the condition code is 0b1111 (0xf). This in effect makes it possible to trigger the uprobes functionality from thumb, and at that using two unallocated instructions which are not permanently undefined. Signed-off-by: Fredrik Strupe Cc: stable@vger.kernel.org Fixes: c7edc9e326d5 ("ARM: add uprobes support") Signed-off-by: Russell King --- arch/arm/probes/uprobes/core.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/arch/arm/probes/uprobes/core.c b/arch/arm/probes/uprobes/core.c index c4b49b322e8a..f5f790c6e5f8 100644 --- a/arch/arm/probes/uprobes/core.c +++ b/arch/arm/probes/uprobes/core.c @@ -204,7 +204,7 @@ unsigned long uprobe_get_swbp_addr(struct pt_regs *regs) static struct undef_hook uprobes_arm_break_hook = { .instr_mask = 0x0fffffff, .instr_val = (UPROBE_SWBP_ARM_INSN & 0x0fffffff), - .cpsr_mask = MODE_MASK, + .cpsr_mask = (PSR_T_BIT | MODE_MASK), .cpsr_val = USR_MODE, .fn = uprobe_trap_handler, }; @@ -212,7 +212,7 @@ static struct undef_hook uprobes_arm_break_hook = { static struct undef_hook uprobes_arm_ss_hook = { .instr_mask = 0x0fffffff, .instr_val = (UPROBE_SS_ARM_INSN & 0x0fffffff), - .cpsr_mask = MODE_MASK, + .cpsr_mask = (PSR_T_BIT | MODE_MASK), .cpsr_val = USR_MODE, .fn = uprobe_trap_handler, }; From bf05bf16c76bb44ab5156223e1e58e26dfe30a88 Mon Sep 17 00:00:00 2001 From: Linus Torvalds Date: Sun, 18 Apr 2021 14:45:32 -0700 Subject: [PATCH 1053/1091] Linux 5.12-rc8 --- Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Makefile b/Makefile index 4730cf156f6b..bc19584fee59 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ VERSION = 5 PATCHLEVEL = 12 SUBLEVEL = 0 -EXTRAVERSION = -rc7 +EXTRAVERSION = -rc8 NAME = Frozen Wasteland # *DOCUMENTATION* From 59ce3233a538fc21c5c59ff38cafd784cbcd6de0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 16 Apr 2021 14:11:40 -0500 Subject: [PATCH 1054/1091] ASoC: soc-acpi: remove useless initialization cppcheck warning: value that is never used. [unreadVariable] acpi_status status = AE_OK; ^ sound/soc/soc-acpi.c:37:21: style: Variable 'status' is assigned a Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210416191144.27006-2-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-acpi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-acpi.c b/sound/soc/soc-acpi.c index 444ce0602f76..395229bf5c51 100644 --- a/sound/soc/soc-acpi.c +++ b/sound/soc/soc-acpi.c @@ -34,7 +34,7 @@ static acpi_status snd_soc_acpi_find_package(acpi_handle handle, u32 level, void *context, void **ret) { struct acpi_device *adev; - acpi_status status = AE_OK; + acpi_status status; struct snd_soc_acpi_package_context *pkg_ctx = context; pkg_ctx->data_valid = false; From d3b47a888f0bc66a8590941cfa57ba015b288040 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 16 Apr 2021 14:11:41 -0500 Subject: [PATCH 1055/1091] ASoC: soc-core: fix signed/unsigned issue cppcheck warning: sound/soc/soc-core.c:2237:13: warning: %x in format string (no. 1) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int] } else if (sscanf(name, "%x-%x", &id1, &id2) == 2) { ^ sound/soc/soc-core.c:2237:13: warning: %x in format string (no. 2) requires 'unsigned int *' but the argument type is 'signed int *'. [invalidScanfArgType_int] } else if (sscanf(name, "%x-%x", &id1, &id2) == 2) { ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210416191144.27006-3-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 80374c82c501..fb6b3a6194ce 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2219,7 +2219,7 @@ static char *fmt_single_name(struct device *dev, int *id) { const char *devname = dev_name(dev); char *found, *name; - int id1, id2; + unsigned int id1, id2; if (devname == NULL) return NULL; From e2290daefef3afa08135a0a65d4f0ce7fe23d5c0 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 16 Apr 2021 14:11:42 -0500 Subject: [PATCH 1056/1091] ASoC: soc-core: fix always-false condition cppcheck warning: sound/soc/soc-core.c:2784:6: style: Condition '!num_routes' is always false [knownConditionTrueFalse] if (!num_routes) { ^ sound/soc/soc-core.c:2777:17: note: Assuming that condition 'num_routes<0' is not redundant if (num_routes < 0 || num_routes & 1) { ^ sound/soc/soc-core.c:2783:2: note: Compound assignment '/=', assigned value is 0 num_routes /= 2; ^ sound/soc/soc-core.c:2784:6: note: Condition '!num_routes' is always false if (!num_routes) { ^ The documentation for of_property_count_string reads " * Returns the number of strings on * success, -EINVAL if the property does not exist, -ENODATA if property * does not have a value, and -EILSEQ if the string is not null-terminated * within the length of the property data. " Since the case for num_routes == 0 is not possible, let's remove this test. Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210416191144.27006-4-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/soc-core.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index fb6b3a6194ce..1c0904acb935 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2785,11 +2785,6 @@ int snd_soc_of_parse_audio_routing(struct snd_soc_card *card, return -EINVAL; } num_routes /= 2; - if (!num_routes) { - dev_err(card->dev, "ASoC: Property '%s's length is zero\n", - propname); - return -EINVAL; - } routes = devm_kcalloc(card->dev, num_routes, sizeof(*routes), GFP_KERNEL); From 36924a12c32021a098fec621fb5ea707a72cd5b5 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 16 Apr 2021 14:11:43 -0500 Subject: [PATCH 1057/1091] ASoC: codecs: lpass-rx-macro: remove useless return cppcheck warning: sound/soc/codecs/lpass-rx-macro.c:1626:9: warning: Identical condition and return expression 'ret', return value is always 0 [identicalConditionAfterEarlyExit] return ret; ^ sound/soc/codecs/lpass-rx-macro.c:1623:6: note: If condition 'ret' is true, the function will return/exit if (ret) ^ sound/soc/codecs/lpass-rx-macro.c:1626:9: note: Returning identical expression 'ret' return ret; ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210416191144.27006-5-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-rx-macro.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/codecs/lpass-rx-macro.c b/sound/soc/codecs/lpass-rx-macro.c index 14c166506fb1..4f1b569d7c47 100644 --- a/sound/soc/codecs/lpass-rx-macro.c +++ b/sound/soc/codecs/lpass-rx-macro.c @@ -1620,8 +1620,6 @@ static int rx_macro_set_interpolator_rate(struct snd_soc_dai *dai, return ret; ret = rx_macro_set_mix_interpolator_rate(dai, rate_val, sample_rate); - if (ret) - return ret; return ret; } From 9726db36ed83670be93d053e05e150308e3ce743 Mon Sep 17 00:00:00 2001 From: Pierre-Louis Bossart Date: Fri, 16 Apr 2021 14:11:44 -0500 Subject: [PATCH 1058/1091] ASoC: codecs: rt5682: clarify expression cppcheck warning: sound/soc/codecs/rt5682.c:2404:42: style: Boolean result is used in bitwise operation. Clarify expression with parentheses. [clarifyCondition] (pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST)); ^ Signed-off-by: Pierre-Louis Bossart Reviewed-by: Daniel Baluta Reviewed-by: Guennadi Liakhovetski Link: https://lore.kernel.org/r/20210416191144.27006-6-pierre-louis.bossart@linux.intel.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 0e2a10ed11da..a5aacfe01a0d 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2401,7 +2401,7 @@ static int rt5682_set_component_pll(struct snd_soc_component *component, (pll_code.n_code << RT5682_PLL_N_SFT) | pll_code.k_code); snd_soc_component_write(component, RT5682_PLL_CTRL_2, ((pll_code.m_bp ? 0 : pll_code.m_code) << RT5682_PLL_M_SFT) | - (pll_code.m_bp << RT5682_PLL_M_BP_SFT | RT5682_PLL_RST)); + ((pll_code.m_bp << RT5682_PLL_M_BP_SFT) | RT5682_PLL_RST)); } rt5682->pll_in[pll_id] = freq_in; From e86a53fb64ed0a4749eeac2eccc7a6412fd3c920 Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Mon, 19 Apr 2021 17:54:32 +0800 Subject: [PATCH 1059/1091] ASoC: ak4458: check reset control status check the return value of ak4458_rstn_control. Signed-off-by: Viorel Suman Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1618826072-29344-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak4458.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 85a1d00894a9..3088128816bb 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -334,7 +334,7 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream, struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); int pcm_width = max(params_physical_width(params), ak4458->slot_width); u8 format, dsdsel0, dsdsel1; - int nfs1, dsd_bclk; + int nfs1, dsd_bclk, ret; nfs1 = params_rate(params); ak4458->fs = nfs1; @@ -419,8 +419,13 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream, snd_soc_component_update_bits(component, AK4458_00_CONTROL1, AK4458_DIF_MASK, format); - ak4458_rstn_control(component, 0); - ak4458_rstn_control(component, 1); + ret = ak4458_rstn_control(component, 0); + if (ret) + return ret; + + ret = ak4458_rstn_control(component, 1); + if (ret) + return ret; return 0; } @@ -429,6 +434,7 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) { struct snd_soc_component *component = dai->component; struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); + int ret; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { case SND_SOC_DAIFMT_CBS_CFS: /* Slave Mode */ @@ -461,8 +467,13 @@ static int ak4458_set_dai_fmt(struct snd_soc_dai *dai, unsigned int fmt) ak4458->fmt == SND_SOC_DAIFMT_PDM ? AK4458_DP_MASK : 0); - ak4458_rstn_control(component, 0); - ak4458_rstn_control(component, 1); + ret = ak4458_rstn_control(component, 0); + if (ret) + return ret; + + ret = ak4458_rstn_control(component, 1); + if (ret) + return ret; return 0; } From dfa7b01dbdc9723ced606425b47005bb583a8778 Mon Sep 17 00:00:00 2001 From: David Ward Date: Sun, 18 Apr 2021 09:46:54 -0400 Subject: [PATCH 1060/1091] ASoC: rt286: Fix upper byte in DMIC2 configuration This HDA verb sets the upper byte of the Configuration Default register, so only an 8-bit value should be used. For the rt298, the same fix was applied in commit f8f2dc4a7127 ("ASoC: rt298: fix wrong setting of gpio2_en"). Signed-off-by: David Ward Link: https://lore.kernel.org/r/20210418134658.4333-2-david.ward@gatech.edu Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/codecs/rt286.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 8abe232ca4a4..f9b29782b62a 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1204,7 +1204,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, mdelay(10); if (!rt286->pdata.gpio2_en) - regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x4000); + regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0x40); else regmap_write(rt286->regmap, RT286_SET_DMIC2_DEFAULT, 0); From cd8499d5c03ba260e3191e90236d0e5f6b147563 Mon Sep 17 00:00:00 2001 From: David Ward Date: Sun, 18 Apr 2021 09:46:57 -0400 Subject: [PATCH 1061/1091] ASoC: rt286: Make RT286_SET_GPIO_* readable and writable The GPIO configuration cannot be applied if the registers are inaccessible. This prevented the headset mic from working on the Dell XPS 13 9343. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=114171 Signed-off-by: David Ward Link: https://lore.kernel.org/r/20210418134658.4333-5-david.ward@gatech.edu Reviewed-by: Pierre-Louis Bossart Signed-off-by: Mark Brown --- sound/soc/codecs/rt286.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index f9b29782b62a..e16e7237156f 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -171,6 +171,9 @@ static bool rt286_readable_register(struct device *dev, unsigned int reg) case RT286_PROC_COEF: case RT286_SET_AMP_GAIN_ADC_IN1: case RT286_SET_AMP_GAIN_ADC_IN2: + case RT286_SET_GPIO_MASK: + case RT286_SET_GPIO_DIRECTION: + case RT286_SET_GPIO_DATA: case RT286_SET_POWER(RT286_DAC_OUT1): case RT286_SET_POWER(RT286_DAC_OUT2): case RT286_SET_POWER(RT286_ADC_IN1): From 11a9b987611f17e6a95e9bb34c1f5f9aa0b6ae25 Mon Sep 17 00:00:00 2001 From: Niklas Carlsson Date: Mon, 19 Apr 2021 16:49:01 +0200 Subject: [PATCH 1062/1091] ASoC: sigmadsp: Disable cache mechanism for readbacks The ALSA control readback functionality only works for non-volatile controls, i.e. control values that does not change on their own without driver interaction. This doesn't work for readbacks since the DSP firmware updates the control value. Disable the cache mechanism in the driver if the control name matches the prefix used for readbacks to ensure that the control value is valid. Signed-off-by: Niklas Carlsson Link: https://lore.kernel.org/r/20210419144901.9441-1-Niklas.Carlsson@axis.com Signed-off-by: Mark Brown --- sound/soc/codecs/sigmadsp.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/sigmadsp.c b/sound/soc/codecs/sigmadsp.c index 76c77dc8ecf7..b992216aee55 100644 --- a/sound/soc/codecs/sigmadsp.c +++ b/sound/soc/codecs/sigmadsp.c @@ -24,6 +24,8 @@ #define SIGMA_FW_CHUNK_TYPE_CONTROL 1 #define SIGMA_FW_CHUNK_TYPE_SAMPLERATES 2 +#define READBACK_CTRL_NAME "ReadBack" + struct sigmadsp_control { struct list_head head; uint32_t samplerates; @@ -31,6 +33,7 @@ struct sigmadsp_control { unsigned int num_bytes; const char *name; struct snd_kcontrol *kcontrol; + bool is_readback; bool cached; uint8_t cache[]; }; @@ -141,7 +144,8 @@ static int sigmadsp_ctrl_put(struct snd_kcontrol *kcontrol, if (ret == 0) { memcpy(ctrl->cache, data, ctrl->num_bytes); - ctrl->cached = true; + if (!ctrl->is_readback) + ctrl->cached = true; } mutex_unlock(&sigmadsp->lock); @@ -164,7 +168,8 @@ static int sigmadsp_ctrl_get(struct snd_kcontrol *kcontrol, } if (ret == 0) { - ctrl->cached = true; + if (!ctrl->is_readback) + ctrl->cached = true; memcpy(ucontrol->value.bytes.data, ctrl->cache, ctrl->num_bytes); } @@ -231,6 +236,15 @@ static int sigma_fw_load_control(struct sigmadsp *sigmadsp, name[name_len] = '\0'; ctrl->name = name; + /* + * Readbacks doesn't work with non-volatile controls, since the + * firmware updates the control value without driver interaction. Mark + * the readbacks to ensure that the values are not cached. + */ + if (ctrl->name && strncmp(ctrl->name, READBACK_CTRL_NAME, + (sizeof(READBACK_CTRL_NAME) - 1)) == 0) + ctrl->is_readback = true; + ctrl->addr = le16_to_cpu(ctrl_chunk->addr); ctrl->num_bytes = num_bytes; ctrl->samplerates = le32_to_cpu(chunk->samplerates); From b15c3ea7e0d2c53b33adc8ca0896de378d6df853 Mon Sep 17 00:00:00 2001 From: David Ward Date: Sun, 18 Apr 2021 09:46:55 -0400 Subject: [PATCH 1063/1091] ASoC: rt286: Configure combo jack for headphones During jack detection, the combo jack is configured for a CTIA headset, and then for an OMTP headset, while sensing the mic connection. If a mic is not found in either case, the combo jack should be re-configured for headphones only. This is consistent with the HDA driver behavior. Signed-off-by: David Ward Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210418134658.4333-3-david.ward@gatech.edu Signed-off-by: Mark Brown --- sound/soc/codecs/rt286.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index e16e7237156f..45e4a48ef5bf 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -255,11 +255,16 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) msleep(300); regmap_read(rt286->regmap, RT286_CBJ_CTRL2, &val); - if (0x0070 == (val & 0x0070)) + if (0x0070 == (val & 0x0070)) { *mic = true; - else + } else { *mic = false; + regmap_update_bits(rt286->regmap, + RT286_CBJ_CTRL1, + 0xfcc0, 0xc400); + } } + regmap_update_bits(rt286->regmap, RT286_DC_GAIN, 0x200, 0x0); From f3bd4dde9f048fa711e98626c8c3bc4d1eae3436 Mon Sep 17 00:00:00 2001 From: David Ward Date: Sun, 18 Apr 2021 09:46:56 -0400 Subject: [PATCH 1064/1091] ASoC: rt298: Configure combo jack for headphones During jack detection, the combo jack is configured for a CTIA headset, and then for an OMTP headset, while sensing the mic connection. If a mic is not found in either case, the combo jack should be re-configured for headphones only. This is consistent with the HDA driver behavior. Signed-off-by: David Ward Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210418134658.4333-4-david.ward@gatech.edu Signed-off-by: Mark Brown --- sound/soc/codecs/rt298.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt298.c b/sound/soc/codecs/rt298.c index 32cc9b6287d2..c592c40a7ab3 100644 --- a/sound/soc/codecs/rt298.c +++ b/sound/soc/codecs/rt298.c @@ -267,11 +267,16 @@ static int rt298_jack_detect(struct rt298_priv *rt298, bool *hp, bool *mic) msleep(300); regmap_read(rt298->regmap, RT298_CBJ_CTRL2, &val); - if (0x0070 == (val & 0x0070)) + if (0x0070 == (val & 0x0070)) { *mic = true; - else + } else { *mic = false; + regmap_update_bits(rt298->regmap, + RT298_CBJ_CTRL1, + 0xfcc0, 0xc400); + } } + regmap_update_bits(rt298->regmap, RT298_DC_GAIN, 0x200, 0x0); From aa2f9c12821e6a4ba1df4fb34a3dbc6a2a1ee7fe Mon Sep 17 00:00:00 2001 From: David Ward Date: Sun, 18 Apr 2021 09:46:58 -0400 Subject: [PATCH 1065/1091] ASoC: rt286: Generalize support for ALC3263 codec The ALC3263 codec on the XPS 13 9343 is also found on the Latitude 13 7350 and Venue 11 Pro 7140. They require the same handling for the combo jack to work with a headset: GPIO pin 6 must be set. The HDA driver always sets this pin on the ALC3263, which it distinguishes by the codec vendor/device ID 0x10ec0288 and PCI subsystem vendor ID 0x1028 (Dell). The ASoC driver does not use PCI, so adapt this check to use DMI to determine if Dell is the system vendor. BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=150601 BugLink: https://bugzilla.kernel.org/show_bug.cgi?id=205961 Signed-off-by: David Ward Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210418134658.4333-6-david.ward@gatech.edu Signed-off-by: Mark Brown --- sound/soc/codecs/rt286.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 45e4a48ef5bf..802f4851c3df 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -1125,12 +1125,11 @@ static const struct dmi_system_id force_combo_jack_table[] = { { } }; -static const struct dmi_system_id dmi_dell_dino[] = { +static const struct dmi_system_id dmi_dell[] = { { - .ident = "Dell Dino", + .ident = "Dell", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "Dell Inc."), - DMI_MATCH(DMI_PRODUCT_NAME, "XPS 13 9343") } }, { } @@ -1141,7 +1140,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, { struct rt286_platform_data *pdata = dev_get_platdata(&i2c->dev); struct rt286_priv *rt286; - int i, ret, val; + int i, ret, vendor_id; rt286 = devm_kzalloc(&i2c->dev, sizeof(*rt286), GFP_KERNEL); @@ -1157,14 +1156,15 @@ static int rt286_i2c_probe(struct i2c_client *i2c, } ret = regmap_read(rt286->regmap, - RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val); + RT286_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &vendor_id); if (ret != 0) { dev_err(&i2c->dev, "I2C error %d\n", ret); return ret; } - if (val != RT286_VENDOR_ID && val != RT288_VENDOR_ID) { + if (vendor_id != RT286_VENDOR_ID && vendor_id != RT288_VENDOR_ID) { dev_err(&i2c->dev, - "Device with ID register %#x is not rt286\n", val); + "Device with ID register %#x is not rt286\n", + vendor_id); return -ENODEV; } @@ -1188,8 +1188,8 @@ static int rt286_i2c_probe(struct i2c_client *i2c, if (pdata) rt286->pdata = *pdata; - if (dmi_check_system(force_combo_jack_table) || - dmi_check_system(dmi_dell_dino)) + if ((vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) || + dmi_check_system(force_combo_jack_table)) rt286->pdata.cbj_en = true; regmap_write(rt286->regmap, RT286_SET_AUDIO_POWER, AC_PWRST_D3); @@ -1228,7 +1228,7 @@ static int rt286_i2c_probe(struct i2c_client *i2c, regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL3, 0xf777, 0x4737); regmap_update_bits(rt286->regmap, RT286_DEPOP_CTRL4, 0x00ff, 0x003f); - if (dmi_check_system(dmi_dell_dino)) { + if (vendor_id == RT288_VENDOR_ID && dmi_check_system(dmi_dell)) { regmap_update_bits(rt286->regmap, RT286_SET_GPIO_MASK, 0x40, 0x40); regmap_update_bits(rt286->regmap, From 7f51384f17b3e1039fbb2d3535cc777585dc3175 Mon Sep 17 00:00:00 2001 From: Jack Yu Date: Tue, 20 Apr 2021 09:30:48 +0000 Subject: [PATCH 1066/1091] ASoC: rt1015p: add support on format S32_LE Add support on format S32_LE for rt1015p. Signed-off-by: Jack Yu Link: https://lore.kernel.org/r/377f0ee05d514c66b567eb6385ac7753@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt1015p.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/rt1015p.c b/sound/soc/codecs/rt1015p.c index 39f4c4ed2ab8..40f2063aefbe 100644 --- a/sound/soc/codecs/rt1015p.c +++ b/sound/soc/codecs/rt1015p.c @@ -96,7 +96,8 @@ static struct snd_soc_dai_driver rt1015p_dai_driver = { .name = "HiFi", .playback = { .stream_name = "HiFi Playback", - .formats = SNDRV_PCM_FMTBIT_S24, + .formats = SNDRV_PCM_FMTBIT_S24 | + SNDRV_PCM_FMTBIT_S32, .rates = SNDRV_PCM_RATE_48000, .channels_min = 1, .channels_max = 2, From ec1af6c64db94e4f24e53011a77b2bf2220ae000 Mon Sep 17 00:00:00 2001 From: Thierry Reding Date: Mon, 19 Apr 2021 18:41:17 +0200 Subject: [PATCH 1067/1091] ASoC: simple-card-utils: Allocate link info structure on heap struct link_info can grow fairly large and may cause the stack frame size to be exceeded when allocated on the stack. Some architectures such as 32-bit ARM, RISC-V or PowerPC have small stack frames where this causes a compiler warning, so allocate these structures on the heap instead of the stack. Fixes: 343e55e71877 ("ASoC: simple-card-utils: Increase maximum number of links to 128") Reported-by: Kuninori Morimoto Reported-by: Stephen Rothwell Reported-by: kernel test robot Signed-off-by: Thierry Reding Acked-by: Kuninori Morimoto Link: https://lore.kernel.org/r/20210419164117.1422242-1-thierry.reding@gmail.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 18 +++++++++++------- sound/soc/generic/simple-card.c | 23 +++++++++++++---------- 2 files changed, 24 insertions(+), 17 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index c7369beee805..e45a560aa9b0 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -548,21 +548,24 @@ static int graph_get_dais_count(struct asoc_simple_priv *priv, int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) { struct snd_soc_card *card = simple_priv_to_card(priv); - struct link_info li; + struct link_info *li; int ret; + li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); + if (!li) + return -ENOMEM; + card->owner = THIS_MODULE; card->dev = dev; - memset(&li, 0, sizeof(li)); - ret = graph_get_dais_count(priv, &li); + ret = graph_get_dais_count(priv, li); if (ret < 0) return ret; - if (!li.link) + if (!li->link) return -EINVAL; - ret = asoc_simple_init_priv(priv, &li); + ret = asoc_simple_init_priv(priv, li); if (ret < 0) return ret; @@ -581,8 +584,8 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) if (ret < 0) return ret; - memset(&li, 0, sizeof(li)); - ret = graph_for_each_link(priv, &li, + memset(li, 0, sizeof(*li)); + ret = graph_for_each_link(priv, li, graph_dai_link_of, graph_dai_link_of_dpcm); if (ret < 0) @@ -600,6 +603,7 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev) if (ret < 0) goto err; + devm_kfree(dev, li); return 0; err: diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 8b9964d25757..ca27cb9ff9e1 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -442,10 +442,9 @@ static int simple_for_each_link(struct asoc_simple_priv *priv, return ret; } -static int simple_parse_of(struct asoc_simple_priv *priv) +static int simple_parse_of(struct asoc_simple_priv *priv, struct link_info *li) { struct snd_soc_card *card = simple_priv_to_card(priv); - struct link_info li; int ret; ret = asoc_simple_parse_widgets(card, PREFIX); @@ -461,8 +460,8 @@ static int simple_parse_of(struct asoc_simple_priv *priv) return ret; /* Single/Muti DAI link(s) & New style of DT node */ - memset(&li, 0, sizeof(li)); - ret = simple_for_each_link(priv, &li, + memset(li, 0, sizeof(*li)); + ret = simple_for_each_link(priv, li, simple_dai_link_of, simple_dai_link_of_dpcm); if (ret < 0) @@ -612,7 +611,7 @@ static int asoc_simple_probe(struct platform_device *pdev) struct device *dev = &pdev->dev; struct device_node *np = dev->of_node; struct snd_soc_card *card; - struct link_info li; + struct link_info *li; int ret; /* Allocate the private data and the DAI link array */ @@ -625,21 +624,24 @@ static int asoc_simple_probe(struct platform_device *pdev) card->dev = dev; card->probe = simple_soc_probe; - memset(&li, 0, sizeof(li)); - ret = simple_get_dais_count(priv, &li); + li = devm_kzalloc(dev, sizeof(*li), GFP_KERNEL); + if (!li) + return -ENOMEM; + + ret = simple_get_dais_count(priv, li); if (ret < 0) return ret; - if (!li.link) + if (!li->link) return -EINVAL; - ret = asoc_simple_init_priv(priv, &li); + ret = asoc_simple_init_priv(priv, li); if (ret < 0) return ret; if (np && of_device_is_available(np)) { - ret = simple_parse_of(priv); + ret = simple_parse_of(priv, li); if (ret < 0) { if (ret != -EPROBE_DEFER) dev_err(dev, "parse error %d\n", ret); @@ -698,6 +700,7 @@ static int asoc_simple_probe(struct platform_device *pdev) if (ret < 0) goto err; + devm_kfree(dev, li); return 0; err: asoc_simple_clean_reference(card); From 1a456b1c6be13514a8fc5c1a99e6763f491d17e9 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Apr 2021 11:02:19 +0900 Subject: [PATCH 1068/1091] ASoC: audio-graph: move audio_graph_card_probe() to simple-card-utils.c audio-graph-card2 can reuse audio_graph_card_probe(). This patch moves it to simple-card-utils.c. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87zgxv3uc4.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/graph_card.h | 2 -- include/sound/simple_card_utils.h | 3 +++ sound/soc/generic/audio-graph-card.c | 19 +------------------ sound/soc/generic/simple-card-utils.c | 17 +++++++++++++++++ sound/soc/tegra/tegra_audio_graph_card.c | 2 +- 5 files changed, 22 insertions(+), 21 deletions(-) diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h index 013784467bec..9c2feb792742 100644 --- a/include/sound/graph_card.h +++ b/include/sound/graph_card.h @@ -9,8 +9,6 @@ #include -int audio_graph_card_probe(struct snd_soc_card *card); - int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); int audio_graph_remove(struct platform_device *pdev); diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index e318a2d4ac44..656c7e30b6e4 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -178,6 +178,9 @@ int asoc_simple_init_jack(struct snd_soc_card *card, int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct link_info *li); +int asoc_graph_card_probe(struct snd_soc_card *card); + + #ifdef DEBUG static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, char *name, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index e45a560aa9b0..6cac167a4e2b 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -721,23 +721,6 @@ static int graph_get_dais_count(struct asoc_simple_priv *priv, graph_count_dpcm); } -int audio_graph_card_probe(struct snd_soc_card *card) -{ - struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card); - int ret; - - ret = asoc_simple_init_hp(card, &priv->hp_jack, NULL); - if (ret < 0) - return ret; - - ret = asoc_simple_init_mic(card, &priv->mic_jack, NULL); - if (ret < 0) - return ret; - - return 0; -} -EXPORT_SYMBOL_GPL(audio_graph_card_probe); - static int graph_probe(struct platform_device *pdev) { struct asoc_simple_priv *priv; @@ -752,7 +735,7 @@ static int graph_probe(struct platform_device *pdev) card = simple_priv_to_card(priv); card->dapm_widgets = graph_dapm_widgets; card->num_dapm_widgets = ARRAY_SIZE(graph_dapm_widgets); - card->probe = audio_graph_card_probe; + card->probe = asoc_graph_card_probe; if (of_device_get_match_data(dev)) priv->dpcm_selectable = 1; diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index e1b7b30a4c8c..ed2cad6d9ac1 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -740,6 +740,23 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, } EXPORT_SYMBOL_GPL(asoc_simple_init_priv); +int asoc_graph_card_probe(struct snd_soc_card *card) +{ + struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card); + int ret; + + ret = asoc_simple_init_hp(card, &priv->hp_jack, NULL); + if (ret < 0) + return ret; + + ret = asoc_simple_init_mic(card, &priv->mic_jack, NULL); + if (ret < 0) + return ret; + + return 0; +} +EXPORT_SYMBOL_GPL(asoc_graph_card_probe); + /* Module information */ MODULE_AUTHOR("Kuninori Morimoto "); MODULE_DESCRIPTION("ALSA SoC Simple Card Utils"); diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c index 47b319504c8c..35d008b5d373 100644 --- a/sound/soc/tegra/tegra_audio_graph_card.c +++ b/sound/soc/tegra/tegra_audio_graph_card.c @@ -184,7 +184,7 @@ static int tegra_audio_graph_card_probe(struct snd_soc_card *card) return PTR_ERR(priv->clk_plla_out0); } - return audio_graph_card_probe(card); + return asoc_graph_card_probe(card); } static int tegra_audio_graph_probe(struct platform_device *pdev) From f6fcc820e0c96664e2f21c0d6bb60630243ef36a Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Apr 2021 11:02:25 +0900 Subject: [PATCH 1069/1091] ASoC: audio-graph: move audio_graph_remove() to simple-card-utils.c audio-graph-card2 can reuse audio_graph_remove() / asoc_simple_remove(). This patch moves it to simple-card-utils.c. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87y2df3uby.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- include/sound/graph_card.h | 2 -- include/sound/simple_card_utils.h | 2 +- sound/soc/generic/audio-graph-card.c | 10 +--------- sound/soc/generic/simple-card-utils.c | 8 ++++++++ sound/soc/generic/simple-card.c | 7 ------- sound/soc/tegra/tegra_audio_graph_card.c | 2 +- 6 files changed, 11 insertions(+), 20 deletions(-) diff --git a/include/sound/graph_card.h b/include/sound/graph_card.h index 9c2feb792742..6f10bfb0d5ee 100644 --- a/include/sound/graph_card.h +++ b/include/sound/graph_card.h @@ -11,6 +11,4 @@ int audio_graph_parse_of(struct asoc_simple_priv *priv, struct device *dev); -int audio_graph_remove(struct platform_device *pdev); - #endif /* __GRAPH_CARD_H */ diff --git a/include/sound/simple_card_utils.h b/include/sound/simple_card_utils.h index 656c7e30b6e4..51b3b485a92e 100644 --- a/include/sound/simple_card_utils.h +++ b/include/sound/simple_card_utils.h @@ -177,10 +177,10 @@ int asoc_simple_init_jack(struct snd_soc_card *card, int is_hp, char *prefix, char *pin); int asoc_simple_init_priv(struct asoc_simple_priv *priv, struct link_info *li); +int asoc_simple_remove(struct platform_device *pdev); int asoc_graph_card_probe(struct snd_soc_card *card); - #ifdef DEBUG static inline void asoc_simple_debug_dai(struct asoc_simple_priv *priv, char *name, diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 6cac167a4e2b..976c1ea31a98 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -743,14 +743,6 @@ static int graph_probe(struct platform_device *pdev) return audio_graph_parse_of(priv, dev); } -int audio_graph_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - return asoc_simple_clean_reference(card); -} -EXPORT_SYMBOL_GPL(audio_graph_remove); - static const struct of_device_id graph_of_match[] = { { .compatible = "audio-graph-card", }, { .compatible = "audio-graph-scu-card", @@ -766,7 +758,7 @@ static struct platform_driver graph_card = { .of_match_table = graph_of_match, }, .probe = graph_probe, - .remove = audio_graph_remove, + .remove = asoc_simple_remove, }; module_platform_driver(graph_card); diff --git a/sound/soc/generic/simple-card-utils.c b/sound/soc/generic/simple-card-utils.c index ed2cad6d9ac1..fa1247f0dda1 100644 --- a/sound/soc/generic/simple-card-utils.c +++ b/sound/soc/generic/simple-card-utils.c @@ -740,6 +740,14 @@ int asoc_simple_init_priv(struct asoc_simple_priv *priv, } EXPORT_SYMBOL_GPL(asoc_simple_init_priv); +int asoc_simple_remove(struct platform_device *pdev) +{ + struct snd_soc_card *card = platform_get_drvdata(pdev); + + return asoc_simple_clean_reference(card); +} +EXPORT_SYMBOL_GPL(asoc_simple_remove); + int asoc_graph_card_probe(struct snd_soc_card *card) { struct asoc_simple_priv *priv = snd_soc_card_get_drvdata(card); diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index ca27cb9ff9e1..a1373be4558f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -708,13 +708,6 @@ err: return ret; } -static int asoc_simple_remove(struct platform_device *pdev) -{ - struct snd_soc_card *card = platform_get_drvdata(pdev); - - return asoc_simple_clean_reference(card); -} - static const struct of_device_id simple_of_match[] = { { .compatible = "simple-audio-card", }, { .compatible = "simple-scu-audio-card", diff --git a/sound/soc/tegra/tegra_audio_graph_card.c b/sound/soc/tegra/tegra_audio_graph_card.c index 35d008b5d373..1f2c5018bf5a 100644 --- a/sound/soc/tegra/tegra_audio_graph_card.c +++ b/sound/soc/tegra/tegra_audio_graph_card.c @@ -244,7 +244,7 @@ static struct platform_driver tegra_audio_graph_card = { .of_match_table = graph_of_tegra_match, }, .probe = tegra_audio_graph_probe, - .remove = audio_graph_remove, + .remove = asoc_simple_remove, }; module_platform_driver(tegra_audio_graph_card); From 6769ea1e4315999624ce4637c9c338b9d88a85e6 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Apr 2021 11:02:29 +0900 Subject: [PATCH 1070/1091] ASoC: audio-graph: check ports if exists "endpoint" and "port" are always exists, but there is no guarantee for "ports". This patch checks "ports" if exists, otherwise, it might set un-expected settings. This patch also do align to 100 char in 1 line. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87wnsz3ubu.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 976c1ea31a98..f3c278a4be21 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -182,7 +182,8 @@ static void graph_parse_convert(struct device *dev, asoc_simple_parse_convert(top, NULL, adata); asoc_simple_parse_convert(node, PREFIX, adata); - asoc_simple_parse_convert(ports, NULL, adata); + if (of_node_name_eq(ports, "ports")) + asoc_simple_parse_convert(ports, NULL, adata); asoc_simple_parse_convert(port, NULL, adata); asoc_simple_parse_convert(ep, NULL, adata); @@ -200,7 +201,8 @@ static void graph_parse_mclk_fs(struct device_node *top, struct device_node *node = of_graph_get_port_parent(ep); of_property_read_u32(top, "mclk-fs", &props->mclk_fs); - of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); + if (of_node_name_eq(ports, "ports")) + of_property_read_u32(ports, "mclk-fs", &props->mclk_fs); of_property_read_u32(port, "mclk-fs", &props->mclk_fs); of_property_read_u32(ep, "mclk-fs", &props->mclk_fs); @@ -311,8 +313,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, "prefix"); snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node, PREFIX "prefix"); - snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, - "prefix"); + if (of_node_name_eq(ports, "ports")) + snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, "prefix"); } From 14d78d74d7bc47c6ff3a66fb9d405084de7b6b02 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Apr 2021 11:02:34 +0900 Subject: [PATCH 1071/1091] ASoC: audio-graph: remove "audio-graph-card, " preix support No upstream code is using "audio-graph-card," preix, and Yaml base Document doesn't indicate it. Let's remove it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87v98j3ubp.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 5 ----- 1 file changed, 5 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index f3c278a4be21..d5ab5c919311 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -22,8 +22,6 @@ #define DPCM_SELECTABLE 1 -#define PREFIX "audio-graph-card," - static int graph_outdrv_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) @@ -181,7 +179,6 @@ static void graph_parse_convert(struct device *dev, struct device_node *node = of_graph_get_port_parent(ep); asoc_simple_parse_convert(top, NULL, adata); - asoc_simple_parse_convert(node, PREFIX, adata); if (of_node_name_eq(ports, "ports")) asoc_simple_parse_convert(ports, NULL, adata); asoc_simple_parse_convert(port, NULL, adata); @@ -311,8 +308,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, /* check "prefix" from top node */ snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, "prefix"); - snd_soc_of_parse_node_prefix(node, cconf, codecs->of_node, - PREFIX "prefix"); if (of_node_name_eq(ports, "ports")) snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, From 67800ae93982eb4496f446cfd06f98ba7382ce36 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Apr 2021 11:02:38 +0900 Subject: [PATCH 1072/1091] ASoC: audio-graph: remove unused "node" from graph_parse_mclk_fs() graph_parse_mclk_fs() has "node", but is not used. This patch removes unused "node" Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87tuo33ubl.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index d5ab5c919311..6b38640773b3 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -195,7 +195,6 @@ static void graph_parse_mclk_fs(struct device_node *top, { struct device_node *port = of_get_parent(ep); struct device_node *ports = of_get_parent(port); - struct device_node *node = of_graph_get_port_parent(ep); of_property_read_u32(top, "mclk-fs", &props->mclk_fs); if (of_node_name_eq(ports, "ports")) @@ -205,7 +204,6 @@ static void graph_parse_mclk_fs(struct device_node *top, of_node_put(port); of_node_put(ports); - of_node_put(node); } static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, From 63f2f9cceb09f8e5f668e36c1cf764eea468ebed Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Mon, 19 Apr 2021 11:02:43 +0900 Subject: [PATCH 1073/1091] ASoC: audio-graph: remove Platform support Platform was one of mandatory component on ASoC before, and audio-graph-card was assuming that CPU and Platform were same driver. But it is no longer mandatory on ASoC. Current ASoC will just ignore if Platform and CPU were same or doplicated component. Of course ASoC is supporting Platform, but current audio-graph-card doesn't support detecting it from DT. This means current audio-graph-card operation for Platform so far is 100% useless. This patch removes it. We can respawn it when we need it. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87sg3n3ubg.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 6 ------ 1 file changed, 6 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 6b38640773b3..44714a12fcd8 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -223,7 +223,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct asoc_simple_dai *dai; struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); - struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); int ret; port = of_get_parent(ep); @@ -275,7 +274,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, /* card->num_links includes Codec */ asoc_simple_canonicalize_cpu(cpus, is_single_links); - asoc_simple_canonicalize_platform(platforms, cpus); } else { struct snd_soc_codec_conf *cconf; @@ -354,7 +352,6 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, struct asoc_simple_dai *codec_dai = simple_props_to_dai_codec(dai_props, 0); struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); - struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); int ret, single_cpu = 0; dev_dbg(dev, "link_of (%pOF)\n", cpu_ep); @@ -405,7 +402,6 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, dai_link->init = asoc_simple_dai_init; asoc_simple_canonicalize_cpu(cpus, single_cpu); - asoc_simple_canonicalize_platform(platforms, cpus); return 0; } @@ -625,7 +621,6 @@ static int graph_count_noml(struct asoc_simple_priv *priv, li->num[li->link].cpus = 1; li->num[li->link].codecs = 1; - li->num[li->link].platforms = 1; li->link += 1; /* 1xCPU-Codec */ @@ -648,7 +643,6 @@ static int graph_count_dpcm(struct asoc_simple_priv *priv, if (li->cpu) { li->num[li->link].cpus = 1; - li->num[li->link].platforms = 1; li->link++; /* 1xCPU-dummy */ } else { From 7342db3cddcd1d8ff54f4dff8c942e04232f1d6d Mon Sep 17 00:00:00 2001 From: Viorel Suman Date: Tue, 20 Apr 2021 18:44:13 +0800 Subject: [PATCH 1074/1091] ASoC: ak4458: enable daisy chain Enable Daisy Chain if in TDM mode and the number of played channels is bigger than the maximum supported number of channels. Signed-off-by: Viorel Suman Signed-off-by: Shengjiu Wang Link: https://lore.kernel.org/r/1618915453-29445-1-git-send-email-shengjiu.wang@nxp.com Signed-off-by: Mark Brown --- sound/soc/codecs/ak4458.c | 47 ++++++++++++++++++++++++++------------- sound/soc/codecs/ak4458.h | 1 + 2 files changed, 32 insertions(+), 16 deletions(-) diff --git a/sound/soc/codecs/ak4458.c b/sound/soc/codecs/ak4458.c index 3088128816bb..29eb78702bf3 100644 --- a/sound/soc/codecs/ak4458.c +++ b/sound/soc/codecs/ak4458.c @@ -306,6 +306,20 @@ static const struct snd_soc_dapm_route ak4497_intercon[] = { }; +static int ak4458_get_tdm_mode(struct ak4458_priv *ak4458) +{ + switch (ak4458->slots * ak4458->slot_width) { + case 128: + return 1; + case 256: + return 2; + case 512: + return 3; + default: + return 0; + } +} + static int ak4458_rstn_control(struct snd_soc_component *component, int bit) { int ret; @@ -333,13 +347,16 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream, struct snd_soc_component *component = dai->component; struct ak4458_priv *ak4458 = snd_soc_component_get_drvdata(component); int pcm_width = max(params_physical_width(params), ak4458->slot_width); - u8 format, dsdsel0, dsdsel1; - int nfs1, dsd_bclk, ret; + u8 format, dsdsel0, dsdsel1, dchn; + int nfs1, dsd_bclk, ret, channels, channels_max; nfs1 = params_rate(params); ak4458->fs = nfs1; /* calculate bit clock */ + channels = params_channels(params); + channels_max = dai->driver->playback.channels_max; + switch (params_format(params)) { case SNDRV_PCM_FORMAT_DSD_U8: case SNDRV_PCM_FORMAT_DSD_U16_LE: @@ -419,6 +436,17 @@ static int ak4458_hw_params(struct snd_pcm_substream *substream, snd_soc_component_update_bits(component, AK4458_00_CONTROL1, AK4458_DIF_MASK, format); + /* + * Enable/disable Daisy Chain if in TDM mode and the number of played + * channels is bigger than the maximum supported number of channels + */ + dchn = ak4458_get_tdm_mode(ak4458) && + (ak4458->fmt == SND_SOC_DAIFMT_DSP_B) && + (channels > channels_max) ? AK4458_DCHAIN_MASK : 0; + + snd_soc_component_update_bits(component, AK4458_0B_CONTROL7, + AK4458_DCHAIN_MASK, dchn); + ret = ak4458_rstn_control(component, 0); if (ret) return ret; @@ -519,20 +547,7 @@ static int ak4458_set_tdm_slot(struct snd_soc_dai *dai, unsigned int tx_mask, ak4458->slots = slots; ak4458->slot_width = slot_width; - switch (slots * slot_width) { - case 128: - mode = AK4458_MODE_TDM128; - break; - case 256: - mode = AK4458_MODE_TDM256; - break; - case 512: - mode = AK4458_MODE_TDM512; - break; - default: - mode = AK4458_MODE_NORMAL; - break; - } + mode = ak4458_get_tdm_mode(ak4458) << AK4458_MODE_SHIFT; snd_soc_component_update_bits(component, AK4458_0A_CONTROL6, AK4458_MODE_MASK, diff --git a/sound/soc/codecs/ak4458.h b/sound/soc/codecs/ak4458.h index 9548c5d78621..9ad869575f8d 100644 --- a/sound/soc/codecs/ak4458.h +++ b/sound/soc/codecs/ak4458.h @@ -82,6 +82,7 @@ * */ #define AK4458_ATS_SHIFT 6 #define AK4458_ATS_MASK GENMASK(7, 6) +#define AK4458_DCHAIN_MASK (0x1 << 1) #define AK4458_DSDSEL_MASK (0x1 << 0) #define AK4458_DP_MASK (0x1 << 7) From 1300c7037f0f08692008053e4b12a2fb6fbd185a Mon Sep 17 00:00:00 2001 From: Vijendar Mukunda Date: Wed, 21 Apr 2021 13:53:11 +0530 Subject: [PATCH 1075/1091] ASoC: amd: drop S24_LE format support AMD I2S Controller doesn't support S24_LE format. Remove S24_LE format support from ACP DMA driver and CPU DAI Driver. Signed-off-by: Vijendar Mukunda Link: https://lore.kernel.org/r/1618993402-10354-1-git-send-email-Vijendar.Mukunda@amd.com Signed-off-by: Mark Brown --- sound/soc/amd/raven/acp3x-i2s.c | 6 ++---- sound/soc/amd/raven/acp3x-pcm-dma.c | 6 ++---- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/sound/soc/amd/raven/acp3x-i2s.c b/sound/soc/amd/raven/acp3x-i2s.c index 5bc028692fcf..2cd93887410c 100644 --- a/sound/soc/amd/raven/acp3x-i2s.c +++ b/sound/soc/amd/raven/acp3x-i2s.c @@ -264,8 +264,7 @@ static struct snd_soc_dai_driver acp3x_i2s_dai = { .playback = { .rates = SNDRV_PCM_RATE_8000_96000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, .channels_max = 8, .rate_min = 8000, @@ -274,8 +273,7 @@ static struct snd_soc_dai_driver acp3x_i2s_dai = { .capture = { .rates = SNDRV_PCM_RATE_8000_48000, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, .channels_max = 2, .rate_min = 8000, diff --git a/sound/soc/amd/raven/acp3x-pcm-dma.c b/sound/soc/amd/raven/acp3x-pcm-dma.c index 417cda24030c..f22bb2bdf527 100644 --- a/sound/soc/amd/raven/acp3x-pcm-dma.c +++ b/sound/soc/amd/raven/acp3x-pcm-dma.c @@ -24,8 +24,7 @@ static const struct snd_pcm_hardware acp3x_pcm_hardware_playback = { SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, .channels_max = 8, .rates = SNDRV_PCM_RATE_8000_96000, @@ -45,8 +44,7 @@ static const struct snd_pcm_hardware acp3x_pcm_hardware_capture = { SNDRV_PCM_INFO_MMAP | SNDRV_PCM_INFO_MMAP_VALID | SNDRV_PCM_INFO_PAUSE | SNDRV_PCM_INFO_RESUME, .formats = SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S8 | - SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S24_LE | - SNDRV_PCM_FMTBIT_S32_LE, + SNDRV_PCM_FMTBIT_U8 | SNDRV_PCM_FMTBIT_S32_LE, .channels_min = 2, .channels_max = 2, .rates = SNDRV_PCM_RATE_8000_48000, From 62bad12bceebd7d336ced4e44f408b702c151ba0 Mon Sep 17 00:00:00 2001 From: Sia Jee Heng Date: Wed, 21 Apr 2021 08:55:46 +0800 Subject: [PATCH 1076/1091] ASoC: Intel: KMB: Fix random noise at the HDMI output Random noise could be heard when playing audio to the HDMI output. This is due to the IEC conversion is invoked in the external loop. As a result, this additional loop takes up a lot of the processing cycle. hdmi_reformat_iec958() process the conversion using an internal loop, it is safe to move it out from the external loop to avoid unnecessary processing cycle been spent. Furthermore, ALSA IEC958 plugin works in 32bit format only. Signed-off-by: Sia Jee Heng Reviewed-by: Pierre-Louis Bossart Link: https://lore.kernel.org/r/20210421005546.7534-1-jee.heng.sia@intel.com Signed-off-by: Mark Brown --- sound/soc/intel/keembay/kmb_platform.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/sound/soc/intel/keembay/kmb_platform.c b/sound/soc/intel/keembay/kmb_platform.c index 0fd1e8f62c89..96741c7c0fba 100644 --- a/sound/soc/intel/keembay/kmb_platform.c +++ b/sound/soc/intel/keembay/kmb_platform.c @@ -105,14 +105,15 @@ static unsigned int kmb_pcm_tx_fn(struct kmb_i2s_info *kmb_i2s, void *buf = runtime->dma_area; int i; + if (kmb_i2s->iec958_fmt) + hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr); + /* KMB i2s uses two separate L/R FIFO */ for (i = 0; i < kmb_i2s->fifo_th; i++) { if (kmb_i2s->config.data_width == 16) { writel(((u16(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); writel(((u16(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); } else { - if (kmb_i2s->iec958_fmt) - hdmi_reformat_iec958(runtime, kmb_i2s, tx_ptr); writel(((u32(*)[2])buf)[tx_ptr][0], i2s_base + LRBR_LTHR(0)); writel(((u32(*)[2])buf)[tx_ptr][1], i2s_base + RRBR_RTHR(0)); } From 8859f809c7d5813c28ab90f5335f182e634d77af Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 21 Apr 2021 14:45:21 +0900 Subject: [PATCH 1077/1091] ASoC: audio-graph: add graph_parse_node() Parse mclk_fs/dai/tdm/clk are common for both CPU/Codec node. This patch creates graph_parse_node() for it and share the code. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87fszki426.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 108 ++++++++++++--------------- 1 file changed, 49 insertions(+), 59 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 44714a12fcd8..bfaeb208db46 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -206,6 +206,47 @@ static void graph_parse_mclk_fs(struct device_node *top, of_node_put(ports); } +static int graph_parse_node(struct asoc_simple_priv *priv, + struct device_node *ep, + struct link_info *li, + int is_cpu) +{ + struct device *dev = simple_priv_to_dev(priv); + struct device_node *top = dev->of_node; + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); + struct snd_soc_dai_link_component *dlc; + struct asoc_simple_dai *dai; + int ret, single = 0; + + if (is_cpu) { + dlc = asoc_link_to_cpu(dai_link, 0); + dai = simple_props_to_dai_cpu(dai_props, 0); + } else { + dlc = asoc_link_to_codec(dai_link, 0); + dai = simple_props_to_dai_codec(dai_props, 0); + } + + graph_parse_mclk_fs(top, ep, dai_props); + + ret = asoc_simple_parse_dai(ep, dlc, &single); + if (ret < 0) + return ret; + + ret = asoc_simple_parse_tdm(ep, dai); + if (ret < 0) + return ret; + + ret = asoc_simple_parse_clk(dev, ep, dai, dlc); + if (ret < 0) + return ret; + + if (is_cpu) + asoc_simple_canonicalize_cpu(dlc, single); + + return 0; +} + static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *cpu_ep, struct device_node *codec_ep, @@ -219,39 +260,26 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *ep = li->cpu ? cpu_ep : codec_ep; struct device_node *port; struct device_node *ports; - struct device_node *node; - struct asoc_simple_dai *dai; struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); int ret; port = of_get_parent(ep); ports = of_get_parent(port); - node = of_graph_get_port_parent(ep); - - li->link++; dev_dbg(dev, "link_of DPCM (%pOF)\n", ep); if (li->cpu) { - int is_single_links = 0; - /* Codec is dummy */ /* FE settings */ dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - dai = simple_props_to_dai_cpu(dai_props, 0); - - ret = asoc_simple_parse_dai(ep, cpus, &is_single_links); + ret = graph_parse_node(priv, cpu_ep, li, 1); if (ret) goto out_put_node; - ret = asoc_simple_parse_clk(dev, ep, dai, cpus); - if (ret < 0) - goto out_put_node; - ret = asoc_simple_set_dailink_name(dev, dai_link, "fe.%pOFP.%s", cpus->of_node, @@ -271,9 +299,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, */ if (card->component_chaining && !soc_component_is_pcm(cpus)) dai_link->no_pcm = 1; - - /* card->num_links includes Codec */ - asoc_simple_canonicalize_cpu(cpus, is_single_links); } else { struct snd_soc_codec_conf *cconf; @@ -283,14 +308,9 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; - dai = simple_props_to_dai_codec(dai_props, 0); cconf = simple_props_to_codec_conf(dai_props, 0); - ret = asoc_simple_parse_dai(ep, codecs, NULL); - if (ret < 0) - goto out_put_node; - - ret = asoc_simple_parse_clk(dev, ep, dai, codecs); + ret = graph_parse_node(priv, codec_ep, li, 0); if (ret < 0) goto out_put_node; @@ -311,11 +331,6 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, } graph_parse_convert(dev, ep, &dai_props->adata); - graph_parse_mclk_fs(top, ep, dai_props); - - ret = asoc_simple_parse_tdm(ep, dai); - if (ret) - goto out_put_node; ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, NULL, &dai_link->dai_fmt); @@ -333,9 +348,10 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->init = asoc_simple_dai_init; out_put_node: + li->link++; + of_node_put(ports); of_node_put(port); - of_node_put(node); return ret; } @@ -346,48 +362,22 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); - struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); - struct device_node *top = dev->of_node; - struct asoc_simple_dai *cpu_dai = simple_props_to_dai_cpu(dai_props, 0); - struct asoc_simple_dai *codec_dai = simple_props_to_dai_codec(dai_props, 0); struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); - int ret, single_cpu = 0; + int ret; dev_dbg(dev, "link_of (%pOF)\n", cpu_ep); - li->link++; - - /* Factor to mclk, used in hw_params() */ - graph_parse_mclk_fs(top, cpu_ep, dai_props); - graph_parse_mclk_fs(top, codec_ep, dai_props); - ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, NULL, &dai_link->dai_fmt); if (ret < 0) return ret; - ret = asoc_simple_parse_dai(cpu_ep, cpus, &single_cpu); + ret = graph_parse_node(priv, cpu_ep, li, 1); if (ret < 0) return ret; - ret = asoc_simple_parse_dai(codec_ep, codecs, NULL); - if (ret < 0) - return ret; - - ret = asoc_simple_parse_tdm(cpu_ep, cpu_dai); - if (ret < 0) - return ret; - - ret = asoc_simple_parse_tdm(codec_ep, codec_dai); - if (ret < 0) - return ret; - - ret = asoc_simple_parse_clk(dev, cpu_ep, cpu_dai, cpus); - if (ret < 0) - return ret; - - ret = asoc_simple_parse_clk(dev, codec_ep, codec_dai, codecs); + ret = graph_parse_node(priv, codec_ep, li, 0); if (ret < 0) return ret; @@ -401,7 +391,7 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, dai_link->ops = &graph_ops; dai_link->init = asoc_simple_dai_init; - asoc_simple_canonicalize_cpu(cpus, single_cpu); + li->link++; return 0; } From e51237b8d3052251421770468903fa6e4446d158 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 21 Apr 2021 14:45:43 +0900 Subject: [PATCH 1078/1091] ASoC: audio-graph: add graph_link_init() This patch adds graph_link_init() and share dai_link setting code. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87eef4i41k.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 70 +++++++++++++--------------- 1 file changed, 33 insertions(+), 37 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index bfaeb208db46..2c8a2fcb7922 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -247,6 +247,29 @@ static int graph_parse_node(struct asoc_simple_priv *priv, return 0; } +static int graph_link_init(struct asoc_simple_priv *priv, + struct device_node *cpu_ep, + struct device_node *codec_ep, + struct link_info *li, + char *name) +{ + struct device *dev = simple_priv_to_dev(priv); + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + int ret; + + ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, + NULL, &dai_link->dai_fmt); + if (ret < 0) + return ret; + + dai_link->init = asoc_simple_dai_init; + dai_link->ops = &graph_ops; + if (priv->ops) + dai_link->ops = priv->ops; + + return asoc_simple_set_dailink_name(dev, dai_link, name); +} + static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *cpu_ep, struct device_node *codec_ep, @@ -262,6 +285,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *ports; struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + char dai_name[64]; int ret; port = of_get_parent(ep); @@ -280,13 +304,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret) goto out_put_node; - ret = asoc_simple_set_dailink_name(dev, dai_link, - "fe.%pOFP.%s", - cpus->of_node, - cpus->dai_name); - if (ret < 0) - goto out_put_node; - + snprintf(dai_name, sizeof(dai_name), + "fe.%pOFP.%s", cpus->of_node, cpus->dai_name); /* * In BE<->BE connections it is not required to create * PCM devices at CPU end of the dai link and thus 'no_pcm' @@ -314,12 +333,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node; - ret = asoc_simple_set_dailink_name(dev, dai_link, - "be.%pOFP.%s", - codecs->of_node, - codecs->dai_name); - if (ret < 0) - goto out_put_node; + snprintf(dai_name, sizeof(dai_name), + "be.%pOFP.%s", codecs->of_node, codecs->dai_name); /* check "prefix" from top node */ snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, @@ -332,20 +347,9 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, graph_parse_convert(dev, ep, &dai_props->adata); - ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, - NULL, &dai_link->dai_fmt); - if (ret < 0) - goto out_put_node; - snd_soc_dai_link_set_capabilities(dai_link); - dai_link->ops = &graph_ops; - - /* Use custom snd_soc_ops callbacks if available */ - if (priv->ops) - dai_link->ops = priv->ops; - - dai_link->init = asoc_simple_dai_init; + ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); out_put_node: li->link++; @@ -364,15 +368,11 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + char dai_name[64]; int ret; dev_dbg(dev, "link_of (%pOF)\n", cpu_ep); - ret = asoc_simple_parse_daifmt(dev, cpu_ep, codec_ep, - NULL, &dai_link->dai_fmt); - if (ret < 0) - return ret; - ret = graph_parse_node(priv, cpu_ep, li, 1); if (ret < 0) return ret; @@ -381,16 +381,12 @@ static int graph_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) return ret; - ret = asoc_simple_set_dailink_name(dev, dai_link, - "%s-%s", - cpus->dai_name, - codecs->dai_name); + snprintf(dai_name, sizeof(dai_name), + "%s-%s", cpus->dai_name, codecs->dai_name); + ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); if (ret < 0) return ret; - dai_link->ops = &graph_ops; - dai_link->init = asoc_simple_dai_init; - li->link++; return 0; From 59c35c44a9cf89a83a92a8d26749e59497d0317d Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 21 Apr 2021 14:45:48 +0900 Subject: [PATCH 1079/1091] ASoC: simple-card: add simple_parse_node() Parse dai/tdm/clk are common for both CPU/Codec node. This patch creates simple_parse_node() for it and share the code. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87czuoi41f.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 119 ++++++++++++++++---------------- 1 file changed, 58 insertions(+), 61 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index a1373be4558f..91af4eca9c86 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -93,12 +93,11 @@ static void simple_parse_convert(struct device *dev, } static void simple_parse_mclk_fs(struct device_node *top, - struct device_node *cpu, - struct device_node *codec, + struct device_node *np, struct simple_dai_props *props, char *prefix) { - struct device_node *node = of_get_parent(cpu); + struct device_node *node = of_get_parent(np); char prop[128]; snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX); @@ -106,12 +105,57 @@ static void simple_parse_mclk_fs(struct device_node *top, snprintf(prop, sizeof(prop), "%smclk-fs", prefix); of_property_read_u32(node, prop, &props->mclk_fs); - of_property_read_u32(cpu, prop, &props->mclk_fs); - of_property_read_u32(codec, prop, &props->mclk_fs); + of_property_read_u32(np, prop, &props->mclk_fs); of_node_put(node); } +static int simple_parse_node(struct asoc_simple_priv *priv, + struct device_node *np, + struct link_info *li, + char *prefix, + int is_cpu) +{ + struct device *dev = simple_priv_to_dev(priv); + struct device_node *top = dev->of_node; + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); + struct snd_soc_dai_link_component *dlc; + struct asoc_simple_dai *dai; + int ret, single = 0; + + if (is_cpu) { + dlc = asoc_link_to_cpu(dai_link, 0); + dai = simple_props_to_dai_cpu(dai_props, 0); + } else { + dlc = asoc_link_to_codec(dai_link, 0); + dai = simple_props_to_dai_codec(dai_props, 0); + } + + simple_parse_mclk_fs(top, np, dai_props, prefix); + + ret = asoc_simple_parse_dai(np, dlc, &single); + if (ret) + return ret; + + ret = asoc_simple_parse_clk(dev, np, dai, dlc); + if (ret) + return ret; + + ret = asoc_simple_parse_tdm(np, dai); + if (ret) + return ret; + + if (is_cpu) { + struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); + + asoc_simple_canonicalize_cpu(dlc, single); + asoc_simple_canonicalize_platform(platforms, dlc); + } + + return 0; +} + static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *np, struct device_node *codec, @@ -121,10 +165,8 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); - struct asoc_simple_dai *dai; struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); - struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); struct device_node *top = dev->of_node; struct device_node *node = of_get_parent(np); char *prefix = ""; @@ -132,28 +174,18 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dev_dbg(dev, "link_of DPCM (%pOF)\n", np); - li->link++; - /* For single DAI link & old style of DT node */ if (is_top) prefix = PREFIX; if (li->cpu) { - int is_single_links = 0; - /* Codec is dummy */ /* FE settings */ dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - dai = simple_props_to_dai_cpu(dai_props, 0); - - ret = asoc_simple_parse_dai(np, cpus, &is_single_links); - if (ret) - goto out_put_node; - - ret = asoc_simple_parse_clk(dev, np, dai, cpus); + ret = simple_parse_node(priv, np, li, prefix, 1); if (ret < 0) goto out_put_node; @@ -162,9 +194,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, cpus->dai_name); if (ret < 0) goto out_put_node; - - asoc_simple_canonicalize_cpu(cpus, is_single_links); - asoc_simple_canonicalize_platform(platforms, cpus); } else { struct snd_soc_codec_conf *cconf; @@ -174,14 +203,9 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; - dai = simple_props_to_dai_codec(dai_props, 0); cconf = simple_props_to_codec_conf(dai_props, 0); - ret = asoc_simple_parse_dai(np, codecs, NULL); - if (ret < 0) - goto out_put_node; - - ret = asoc_simple_parse_clk(dev, np, dai, codecs); + ret = simple_parse_node(priv, np, li, prefix, 0); if (ret < 0) goto out_put_node; @@ -201,11 +225,6 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, } simple_parse_convert(dev, np, &dai_props->adata); - simple_parse_mclk_fs(top, np, codec, dai_props, prefix); - - ret = asoc_simple_parse_tdm(np, dai); - if (ret) - goto out_put_node; ret = asoc_simple_parse_daifmt(dev, node, codec, prefix, &dai_link->dai_fmt); @@ -218,6 +237,8 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->init = asoc_simple_dai_init; out_put_node: + li->link++; + of_node_put(node); return ret; } @@ -230,23 +251,18 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); - struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); - struct asoc_simple_dai *cpu_dai = simple_props_to_dai_cpu(dai_props, 0); - struct asoc_simple_dai *codec_dai = simple_props_to_dai_codec(dai_props, 0); struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); - struct device_node *top = dev->of_node; struct device_node *cpu = NULL; struct device_node *node = NULL; struct device_node *plat = NULL; char prop[128]; char *prefix = ""; - int ret, single_cpu = 0; + int ret; cpu = np; node = of_get_parent(np); - li->link++; dev_dbg(dev, "link_of (%pOF)\n", node); @@ -262,13 +278,11 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; - simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix); - - ret = asoc_simple_parse_dai(cpu, cpus, &single_cpu); + ret = simple_parse_node(priv, cpu, li, prefix, 1); if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_dai(codec, codecs, NULL); + ret = simple_parse_node(priv, codec, li, prefix, 0); if (ret < 0) goto dai_link_of_err; @@ -276,22 +290,6 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_parse_tdm(cpu, cpu_dai); - if (ret < 0) - goto dai_link_of_err; - - ret = asoc_simple_parse_tdm(codec, codec_dai); - if (ret < 0) - goto dai_link_of_err; - - ret = asoc_simple_parse_clk(dev, cpu, cpu_dai, cpus); - if (ret < 0) - goto dai_link_of_err; - - ret = asoc_simple_parse_clk(dev, codec, codec_dai, codecs); - if (ret < 0) - goto dai_link_of_err; - ret = asoc_simple_set_dailink_name(dev, dai_link, "%s-%s", cpus->dai_name, @@ -302,13 +300,12 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, dai_link->ops = &simple_ops; dai_link->init = asoc_simple_dai_init; - asoc_simple_canonicalize_cpu(cpus, single_cpu); - asoc_simple_canonicalize_platform(platforms, cpus); - dai_link_of_err: of_node_put(plat); of_node_put(node); + li->link++; + return ret; } From 434392271afcff350fe11730f12b831fffaf33eb Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 21 Apr 2021 14:45:52 +0900 Subject: [PATCH 1080/1091] ASoC: simple-card: add simple_link_init() This patch adds simple_link_init() and share dai_link setting code. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87bla8i41b.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/simple-card.c | 59 +++++++++++++++++---------------- 1 file changed, 30 insertions(+), 29 deletions(-) diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 91af4eca9c86..6a04632944b8 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -156,6 +156,28 @@ static int simple_parse_node(struct asoc_simple_priv *priv, return 0; } +static int simple_link_init(struct asoc_simple_priv *priv, + struct device_node *node, + struct device_node *codec, + struct link_info *li, + char *prefix, + char *name) +{ + struct device *dev = simple_priv_to_dev(priv); + struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + int ret; + + ret = asoc_simple_parse_daifmt(dev, node, codec, + prefix, &dai_link->dai_fmt); + if (ret < 0) + return 0; + + dai_link->init = asoc_simple_dai_init; + dai_link->ops = &simple_ops; + + return asoc_simple_set_dailink_name(dev, dai_link, name); +} + static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *np, struct device_node *codec, @@ -170,6 +192,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *top = dev->of_node; struct device_node *node = of_get_parent(np); char *prefix = ""; + char dai_name[64]; int ret; dev_dbg(dev, "link_of DPCM (%pOF)\n", np); @@ -189,11 +212,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node; - ret = asoc_simple_set_dailink_name(dev, dai_link, - "fe.%s", - cpus->dai_name); - if (ret < 0) - goto out_put_node; + snprintf(dai_name, sizeof(dai_name), "fe.%s", cpus->dai_name); } else { struct snd_soc_codec_conf *cconf; @@ -209,11 +228,7 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node; - ret = asoc_simple_set_dailink_name(dev, dai_link, - "be.%s", - codecs->dai_name); - if (ret < 0) - goto out_put_node; + snprintf(dai_name, sizeof(dai_name), "be.%s", codecs->dai_name); /* check "prefix" from top node */ snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, @@ -226,15 +241,9 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, simple_parse_convert(dev, np, &dai_props->adata); - ret = asoc_simple_parse_daifmt(dev, node, codec, - prefix, &dai_link->dai_fmt); - if (ret < 0) - goto out_put_node; - snd_soc_dai_link_set_capabilities(dai_link); - dai_link->ops = &simple_ops; - dai_link->init = asoc_simple_dai_init; + ret = simple_link_init(priv, node, codec, li, prefix, dai_name); out_put_node: li->link++; @@ -257,6 +266,7 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, struct device_node *cpu = NULL; struct device_node *node = NULL; struct device_node *plat = NULL; + char dai_name[64]; char prop[128]; char *prefix = ""; int ret; @@ -273,11 +283,6 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, snprintf(prop, sizeof(prop), "%splat", prefix); plat = of_get_child_by_name(node, prop); - ret = asoc_simple_parse_daifmt(dev, node, codec, - prefix, &dai_link->dai_fmt); - if (ret < 0) - goto dai_link_of_err; - ret = simple_parse_node(priv, cpu, li, prefix, 1); if (ret < 0) goto dai_link_of_err; @@ -290,16 +295,12 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; - ret = asoc_simple_set_dailink_name(dev, dai_link, - "%s-%s", - cpus->dai_name, - codecs->dai_name); + snprintf(dai_name, sizeof(dai_name), + "%s-%s", cpus->dai_name, codecs->dai_name); + ret = simple_link_init(priv, node, codec, li, prefix, dai_name); if (ret < 0) goto dai_link_of_err; - dai_link->ops = &simple_ops; - dai_link->init = asoc_simple_dai_init; - dai_link_of_err: of_node_put(plat); of_node_put(node); From 73371bacf0475a20ab6f3e7b6310e378ec5b3023 Mon Sep 17 00:00:00 2001 From: Kuninori Morimoto Date: Wed, 21 Apr 2021 14:45:56 +0900 Subject: [PATCH 1081/1091] ASoC: audio-graph: tidyup graph_dai_link_of_dpcm() Use local variable at local area only. Signed-off-by: Kuninori Morimoto Link: https://lore.kernel.org/r/87a6psi417.wl-kuninori.morimoto.gx@renesas.com Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 30 +++++++++++++--------------- 1 file changed, 14 insertions(+), 16 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 2c8a2fcb7922..0159a4576e9c 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -276,24 +276,19 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); - struct snd_soc_card *card = simple_priv_to_card(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct device_node *top = dev->of_node; struct device_node *ep = li->cpu ? cpu_ep : codec_ep; - struct device_node *port; - struct device_node *ports; - struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); - struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); char dai_name[64]; int ret; - port = of_get_parent(ep); - ports = of_get_parent(port); - dev_dbg(dev, "link_of DPCM (%pOF)\n", ep); if (li->cpu) { + struct snd_soc_card *card = simple_priv_to_card(priv); + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + /* Codec is dummy */ /* FE settings */ @@ -302,7 +297,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = graph_parse_node(priv, cpu_ep, li, 1); if (ret) - goto out_put_node; + return ret; snprintf(dai_name, sizeof(dai_name), "fe.%pOFP.%s", cpus->of_node, cpus->dai_name); @@ -319,7 +314,10 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (card->component_chaining && !soc_component_is_pcm(cpus)) dai_link->no_pcm = 1; } else { - struct snd_soc_codec_conf *cconf; + struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, 0); + struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + struct device_node *port; + struct device_node *ports; /* CPU is dummy */ @@ -327,22 +325,25 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; - cconf = simple_props_to_codec_conf(dai_props, 0); - ret = graph_parse_node(priv, codec_ep, li, 0); if (ret < 0) - goto out_put_node; + return ret; snprintf(dai_name, sizeof(dai_name), "be.%pOFP.%s", codecs->of_node, codecs->dai_name); /* check "prefix" from top node */ + port = of_get_parent(ep); + ports = of_get_parent(port); snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, "prefix"); if (of_node_name_eq(ports, "ports")) snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, "prefix"); + + of_node_put(ports); + of_node_put(port); } graph_parse_convert(dev, ep, &dai_props->adata); @@ -351,11 +352,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); -out_put_node: li->link++; - of_node_put(ports); - of_node_put(port); return ret; } From a89f3a93cd20f77ac1f84089297258d4b409e280 Mon Sep 17 00:00:00 2001 From: Niklas Carlsson Date: Thu, 22 Apr 2021 15:02:26 +0200 Subject: [PATCH 1082/1091] ASoC: adau17x1: Avoid overwriting CHPF Configuring number of channels per LRCLK frame by using e.g. snd_soc_dai_set_tdm_slot before configuring DAI format was being overwritten by the latter due to a regmap_write which would write over the whole register. Signed-off-by: Niklas Carlsson Link: https://lore.kernel.org/r/20210422130226.15201-1-Niklas.Carlsson@axis.com Signed-off-by: Mark Brown --- sound/soc/codecs/adau17x1.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/adau17x1.c b/sound/soc/codecs/adau17x1.c index 546ee8178038..8aae7ab74091 100644 --- a/sound/soc/codecs/adau17x1.c +++ b/sound/soc/codecs/adau17x1.c @@ -553,6 +553,7 @@ static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai, { struct adau *adau = snd_soc_component_get_drvdata(dai->component); unsigned int ctrl0, ctrl1; + unsigned int ctrl0_mask; int lrclk_pol; switch (fmt & SND_SOC_DAIFMT_MASTER_MASK) { @@ -612,8 +613,16 @@ static int adau17x1_set_dai_fmt(struct snd_soc_dai *dai, if (lrclk_pol) ctrl0 |= ADAU17X1_SERIAL_PORT0_LRCLK_POL; - regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT0, ctrl0); - regmap_write(adau->regmap, ADAU17X1_SERIAL_PORT1, ctrl1); + /* Set the mask to update all relevant bits in ADAU17X1_SERIAL_PORT0 */ + ctrl0_mask = ADAU17X1_SERIAL_PORT0_MASTER | + ADAU17X1_SERIAL_PORT0_LRCLK_POL | + ADAU17X1_SERIAL_PORT0_BCLK_POL | + ADAU17X1_SERIAL_PORT0_PULSE_MODE; + + regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT0, ctrl0_mask, + ctrl0); + regmap_update_bits(adau->regmap, ADAU17X1_SERIAL_PORT1, + ADAU17X1_SERIAL_PORT1_DELAY_MASK, ctrl1); adau->dai_fmt = fmt & SND_SOC_DAIFMT_FORMAT_MASK; From ccd4cc3ed0692aef8a3b4566391c37eb168d8d32 Mon Sep 17 00:00:00 2001 From: Arnd Bergmann Date: Thu, 22 Apr 2021 15:34:00 +0200 Subject: [PATCH 1083/1091] ASoC: tegra: mark runtime-pm functions as __maybe_unused A reorganization of the driver source led to two of them causing a compile time warning in some configurations: tegra/tegra20_spdif.c:36:12: error: 'tegra20_spdif_runtime_resume' defined but not used [-Werror=unused-function] 36 | static int tegra20_spdif_runtime_resume(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ tegra/tegra20_spdif.c:27:12: error: 'tegra20_spdif_runtime_suspend' defined but not used [-Werror=unused-function] 27 | static int tegra20_spdif_runtime_suspend(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~ tegra/tegra30_ahub.c:64:12: error: 'tegra30_ahub_runtime_resume' defined but not used [-Werror=unused-function] 64 | static int tegra30_ahub_runtime_resume(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~ tegra/tegra30_ahub.c:43:12: error: 'tegra30_ahub_runtime_suspend' defined but not used [-Werror=unused-function] 43 | static int tegra30_ahub_runtime_suspend(struct device *dev) | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~ Mark these functions as __maybe_unused to avoid this kind of warning. Fixes: b5571449e618 ("ASoC: tegra30: ahub: Remove handing of disabled runtime PM") Fixes: c53b396f0dd4 ("ASoC: tegra20: spdif: Remove handing of disabled runtime PM") Fixes: 80ec4a4cb36d ("ASoC: tegra20: i2s: Remove handing of disabled runtime PM") Fixes: b5f6f781fcb2 ("ASoC: tegra30: i2s: Remove handing of disabled runtime PM") Signed-off-by: Arnd Bergmann Link: https://lore.kernel.org/r/20210422133418.1757893-1-arnd@kernel.org Signed-off-by: Mark Brown --- sound/soc/tegra/tegra20_i2s.c | 4 ++-- sound/soc/tegra/tegra20_spdif.c | 4 ++-- sound/soc/tegra/tegra30_ahub.c | 4 ++-- sound/soc/tegra/tegra30_i2s.c | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/sound/soc/tegra/tegra20_i2s.c b/sound/soc/tegra/tegra20_i2s.c index 1b27f81c10fe..b280ebd72591 100644 --- a/sound/soc/tegra/tegra20_i2s.c +++ b/sound/soc/tegra/tegra20_i2s.c @@ -34,7 +34,7 @@ #define DRV_NAME "tegra20-i2s" -static int tegra20_i2s_runtime_suspend(struct device *dev) +static __maybe_unused int tegra20_i2s_runtime_suspend(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev); @@ -45,7 +45,7 @@ static int tegra20_i2s_runtime_suspend(struct device *dev) return 0; } -static int tegra20_i2s_runtime_resume(struct device *dev) +static __maybe_unused int tegra20_i2s_runtime_resume(struct device *dev) { struct tegra20_i2s *i2s = dev_get_drvdata(dev); int ret; diff --git a/sound/soc/tegra/tegra20_spdif.c b/sound/soc/tegra/tegra20_spdif.c index 7b597ee63cb5..de698ff2a69c 100644 --- a/sound/soc/tegra/tegra20_spdif.c +++ b/sound/soc/tegra/tegra20_spdif.c @@ -24,7 +24,7 @@ #define DRV_NAME "tegra20-spdif" -static int tegra20_spdif_runtime_suspend(struct device *dev) +static __maybe_unused int tegra20_spdif_runtime_suspend(struct device *dev) { struct tegra20_spdif *spdif = dev_get_drvdata(dev); @@ -33,7 +33,7 @@ static int tegra20_spdif_runtime_suspend(struct device *dev) return 0; } -static int tegra20_spdif_runtime_resume(struct device *dev) +static __maybe_unused int tegra20_spdif_runtime_resume(struct device *dev) { struct tegra20_spdif *spdif = dev_get_drvdata(dev); int ret; diff --git a/sound/soc/tegra/tegra30_ahub.c b/sound/soc/tegra/tegra30_ahub.c index d1718f3af3cd..4692c70ed933 100644 --- a/sound/soc/tegra/tegra30_ahub.c +++ b/sound/soc/tegra/tegra30_ahub.c @@ -40,7 +40,7 @@ static inline void tegra30_audio_write(u32 reg, u32 val) regmap_write(ahub->regmap_ahub, reg, val); } -static int tegra30_ahub_runtime_suspend(struct device *dev) +static __maybe_unused int tegra30_ahub_runtime_suspend(struct device *dev) { regcache_cache_only(ahub->regmap_apbif, true); regcache_cache_only(ahub->regmap_ahub, true); @@ -61,7 +61,7 @@ static int tegra30_ahub_runtime_suspend(struct device *dev) * stopping streams should dynamically adjust the clock as required. However, * this is not yet implemented. */ -static int tegra30_ahub_runtime_resume(struct device *dev) +static __maybe_unused int tegra30_ahub_runtime_resume(struct device *dev) { int ret; diff --git a/sound/soc/tegra/tegra30_i2s.c b/sound/soc/tegra/tegra30_i2s.c index 8730ffa0f691..36344f0a64c1 100644 --- a/sound/soc/tegra/tegra30_i2s.c +++ b/sound/soc/tegra/tegra30_i2s.c @@ -36,7 +36,7 @@ #define DRV_NAME "tegra30-i2s" -static int tegra30_i2s_runtime_suspend(struct device *dev) +static __maybe_unused int tegra30_i2s_runtime_suspend(struct device *dev) { struct tegra30_i2s *i2s = dev_get_drvdata(dev); @@ -47,7 +47,7 @@ static int tegra30_i2s_runtime_suspend(struct device *dev) return 0; } -static int tegra30_i2s_runtime_resume(struct device *dev) +static __maybe_unused int tegra30_i2s_runtime_resume(struct device *dev) { struct tegra30_i2s *i2s = dev_get_drvdata(dev); int ret; From 65d1cce726d4912793d0a84c55ecdb0ef5832130 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Apr 2021 14:05:08 +0200 Subject: [PATCH 1084/1091] ASoC: stm32: properly get clk from the provider Instead of using the clk embedded in the clk_hw (which is meant to go away), a clock provider which need to interact with its own clock should request clk reference through the clock provider API. Reviewed-by: Stephen Boyd Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210421120512.413057-2-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/stm/stm32_sai_sub.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/stm/stm32_sai_sub.c b/sound/soc/stm/stm32_sai_sub.c index 3aa1cf262402..c1561237ee24 100644 --- a/sound/soc/stm/stm32_sai_sub.c +++ b/sound/soc/stm/stm32_sai_sub.c @@ -484,7 +484,10 @@ static int stm32_sai_add_mclk_provider(struct stm32_sai_sub_data *sai) dev_err(dev, "mclk register returned %d\n", ret); return ret; } - sai->sai_mclk = hw->clk; + + sai->sai_mclk = devm_clk_hw_get_clk(dev, hw, NULL); + if (IS_ERR(sai->sai_mclk)) + return PTR_ERR(sai->sai_mclk); /* register mclk provider */ return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); From 104c3a9ed07411288efcd34f08a577df318aafc0 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Apr 2021 14:05:09 +0200 Subject: [PATCH 1085/1091] ASoC: wcd934x: use the clock provider API Clock providers should use the clk_hw API Reviewed-by: Stephen Boyd Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210421120512.413057-3-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/codecs/wcd934x.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/wcd934x.c b/sound/soc/codecs/wcd934x.c index cddc49bbb7f6..046874ef490e 100644 --- a/sound/soc/codecs/wcd934x.c +++ b/sound/soc/codecs/wcd934x.c @@ -2116,11 +2116,13 @@ static struct clk *wcd934x_register_mclk_output(struct wcd934x_codec *wcd) wcd->hw.init = &init; hw = &wcd->hw; - ret = clk_hw_register(wcd->dev->parent, hw); + ret = devm_clk_hw_register(wcd->dev->parent, hw); if (ret) return ERR_PTR(ret); - of_clk_add_provider(np, of_clk_src_simple_get, hw->clk); + ret = devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); + if (ret) + return ERR_PTR(ret); return NULL; } From 8691743c511d6f92d7647d78ea1e5f5ef69937b1 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Apr 2021 14:05:10 +0200 Subject: [PATCH 1086/1091] ASoC: rt5682: clock driver must use the clock provider API Clock drivers ops should not call the clk API but the clock provider (clk_hw) instead. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210421120512.413057-4-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt5682.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index a5aacfe01a0d..e4c91571abae 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -2634,7 +2634,7 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, container_of(hw, struct rt5682_priv, dai_clks_hw[RT5682_DAI_WCLK_IDX]); struct snd_soc_component *component = rt5682->component; - struct clk *parent_clk; + struct clk_hw *parent_hw; const char * const clk_name = clk_hw_get_name(hw); int pre_div; unsigned int clk_pll2_out; @@ -2649,8 +2649,8 @@ static int rt5682_wclk_set_rate(struct clk_hw *hw, unsigned long rate, * * It will set the codec anyway by assuming mclk is 48MHz. */ - parent_clk = clk_get_parent(hw->clk); - if (!parent_clk) + parent_hw = clk_hw_get_parent(hw); + if (!parent_hw) dev_warn(component->dev, "Parent mclk of wclk not acquired in driver. Please ensure mclk was provided as %d Hz.\n", CLK_PLL2_FIN); From 27dc72b44e85997dfd5f3b120e5ec847c43c272a Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Apr 2021 14:05:11 +0200 Subject: [PATCH 1087/1091] ASoC: lpass: use the clock provider API Clock providers should be registered using the clk_hw API. Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210421120512.413057-5-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/codecs/lpass-va-macro.c | 7 ++----- sound/soc/codecs/lpass-wsa-macro.c | 11 +++-------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/sound/soc/codecs/lpass-va-macro.c b/sound/soc/codecs/lpass-va-macro.c index 5294c57b2cd4..56c93f4465c9 100644 --- a/sound/soc/codecs/lpass-va-macro.c +++ b/sound/soc/codecs/lpass-va-macro.c @@ -1343,7 +1343,7 @@ static int va_macro_register_fsgen_output(struct va_macro *va) if (ret) return ret; - return of_clk_add_provider(np, of_clk_src_simple_get, va->hw.clk); + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, &va->hw); } static int va_macro_validate_dmic_sample_rate(u32 dmic_sample_rate, @@ -1452,12 +1452,10 @@ static int va_macro_probe(struct platform_device *pdev) va_macro_dais, ARRAY_SIZE(va_macro_dais)); if (ret) - goto soc_err; + goto err; return ret; -soc_err: - of_clk_del_provider(pdev->dev.of_node); err: clk_bulk_disable_unprepare(VA_NUM_CLKS_MAX, va->clks); @@ -1468,7 +1466,6 @@ static int va_macro_remove(struct platform_device *pdev) { struct va_macro *va = dev_get_drvdata(&pdev->dev); - of_clk_del_provider(pdev->dev.of_node); clk_bulk_disable_unprepare(VA_NUM_CLKS_MAX, va->clks); return 0; diff --git a/sound/soc/codecs/lpass-wsa-macro.c b/sound/soc/codecs/lpass-wsa-macro.c index e79a70386b4b..1a7fa5492f28 100644 --- a/sound/soc/codecs/lpass-wsa-macro.c +++ b/sound/soc/codecs/lpass-wsa-macro.c @@ -2337,10 +2337,9 @@ static const struct clk_ops swclk_gate_ops = { .recalc_rate = swclk_recalc_rate, }; -static struct clk *wsa_macro_register_mclk_output(struct wsa_macro *wsa) +static int wsa_macro_register_mclk_output(struct wsa_macro *wsa) { struct device *dev = wsa->dev; - struct device_node *np = dev->of_node; const char *parent_clk_name; const char *clk_name = "mclk"; struct clk_hw *hw; @@ -2358,11 +2357,9 @@ static struct clk *wsa_macro_register_mclk_output(struct wsa_macro *wsa) hw = &wsa->hw; ret = clk_hw_register(wsa->dev, hw); if (ret) - return ERR_PTR(ret); + return ret; - of_clk_add_provider(np, of_clk_src_simple_get, hw->clk); - - return NULL; + return devm_of_clk_add_hw_provider(dev, of_clk_hw_simple_get, hw); } static const struct snd_soc_component_driver wsa_macro_component_drv = { @@ -2438,8 +2435,6 @@ static int wsa_macro_remove(struct platform_device *pdev) { struct wsa_macro *wsa = dev_get_drvdata(&pdev->dev); - of_clk_del_provider(pdev->dev.of_node); - clk_bulk_disable_unprepare(WSA_NUM_CLKS_MAX, wsa->clks); return 0; From 12f8127fe9e6154dd4197df97e44f3fd67583071 Mon Sep 17 00:00:00 2001 From: Jerome Brunet Date: Wed, 21 Apr 2021 14:05:12 +0200 Subject: [PATCH 1088/1091] ASoC: da7219: properly get clk from the provider Instead of using the clk embedded in the clk_hw (which is meant to go away), a clock provider which need to interact with its own clock should request clk reference through the clock provider API. Reviewed-by: Stephen Boyd Signed-off-by: Jerome Brunet Link: https://lore.kernel.org/r/20210421120512.413057-6-jbrunet@baylibre.com Signed-off-by: Mark Brown --- sound/soc/codecs/da7219.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/sound/soc/codecs/da7219.c b/sound/soc/codecs/da7219.c index 13009d08b09a..bd3c523a8617 100644 --- a/sound/soc/codecs/da7219.c +++ b/sound/soc/codecs/da7219.c @@ -2181,7 +2181,10 @@ static int da7219_register_dai_clks(struct snd_soc_component *component) ret); goto err; } - da7219->dai_clks[i] = dai_clk_hw->clk; + + da7219->dai_clks[i] = devm_clk_hw_get_clk(dev, dai_clk_hw, NULL); + if (IS_ERR(da7219->dai_clks[i])) + return PTR_ERR(da7219->dai_clks[i]); /* For DT setup onecell data, otherwise create lookup */ if (np) { From ca5118c0c00f6bc8b7d0c82c95485159db3a5584 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Thu, 22 Apr 2021 18:32:20 +0800 Subject: [PATCH 1089/1091] ASoC: rt711-sdca: change capture switch controls The DAPM event and mixer control could mute/unmute the capture directly. That will be confused that capture still works if the user settings is unmute before the capture. Therefore, this patch uses the variables to record the capture switch status of DAPM and mixer. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210422103220.21987-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca.c | 168 +++++++++++++++++++++++++--------- sound/soc/codecs/rt711-sdca.h | 2 + 2 files changed, 127 insertions(+), 43 deletions(-) diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index bfb7f1c8ec8f..39848d2641c3 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -642,6 +642,114 @@ static int rt711_sdca_set_gain_get(struct snd_kcontrol *kcontrol, return 0; } +static int rt711_sdca_set_fu0f_capture_ctl(struct rt711_sdca_priv *rt711) +{ + int err; + unsigned int ch_l, ch_r; + + ch_l = (rt711->fu0f_dapm_mute || rt711->fu0f_mixer_l_mute) ? 0x01 : 0x00; + ch_r = (rt711->fu0f_dapm_mute || rt711->fu0f_mixer_r_mute) ? 0x01 : 0x00; + + err = regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, + RT711_SDCA_CTL_FU_MUTE, CH_L), ch_l); + if (err < 0) + return err; + + err = regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, + RT711_SDCA_CTL_FU_MUTE, CH_R), ch_r); + if (err < 0) + return err; + + return 0; +} + +static int rt711_sdca_set_fu1e_capture_ctl(struct rt711_sdca_priv *rt711) +{ + int err; + unsigned int ch_l, ch_r; + + ch_l = (rt711->fu1e_dapm_mute || rt711->fu1e_mixer_l_mute) ? 0x01 : 0x00; + ch_r = (rt711->fu1e_dapm_mute || rt711->fu1e_mixer_r_mute) ? 0x01 : 0x00; + + err = regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU1E, + RT711_SDCA_CTL_FU_MUTE, CH_L), ch_l); + if (err < 0) + return err; + + err = regmap_write(rt711->regmap, + SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU1E, + RT711_SDCA_CTL_FU_MUTE, CH_R), ch_r); + if (err < 0) + return err; + + return 0; +} + +static int rt711_sdca_fu1e_capture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = !rt711->fu1e_mixer_l_mute; + ucontrol->value.integer.value[1] = !rt711->fu1e_mixer_r_mute; + return 0; +} + +static int rt711_sdca_fu1e_capture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + int err, changed = 0; + + if (rt711->fu1e_mixer_l_mute != !ucontrol->value.integer.value[0] || + rt711->fu1e_mixer_r_mute != !ucontrol->value.integer.value[1]) + changed = 1; + + rt711->fu1e_mixer_l_mute = !ucontrol->value.integer.value[0]; + rt711->fu1e_mixer_r_mute = !ucontrol->value.integer.value[1]; + err = rt711_sdca_set_fu1e_capture_ctl(rt711); + if (err < 0) + return err; + + return changed; +} + +static int rt711_sdca_fu0f_capture_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + + ucontrol->value.integer.value[0] = !rt711->fu0f_mixer_l_mute; + ucontrol->value.integer.value[1] = !rt711->fu0f_mixer_r_mute; + return 0; +} + +static int rt711_sdca_fu0f_capture_put(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_soc_component *component = snd_kcontrol_chip(kcontrol); + struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); + int err, changed = 0; + + if (rt711->fu0f_mixer_l_mute != !ucontrol->value.integer.value[0] || + rt711->fu0f_mixer_r_mute != !ucontrol->value.integer.value[1]) + changed = 1; + + rt711->fu0f_mixer_l_mute = !ucontrol->value.integer.value[0]; + rt711->fu0f_mixer_r_mute = !ucontrol->value.integer.value[1]; + err = rt711_sdca_set_fu0f_capture_ctl(rt711); + if (err < 0) + return err; + + return changed; +} + static const DECLARE_TLV_DB_SCALE(out_vol_tlv, -6525, 75, 0); static const DECLARE_TLV_DB_SCALE(in_vol_tlv, -1725, 75, 0); static const DECLARE_TLV_DB_SCALE(mic_vol_tlv, 0, 1000, 0); @@ -652,14 +760,10 @@ static const struct snd_kcontrol_new rt711_sdca_snd_controls[] = { SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU05, RT711_SDCA_CTL_FU_VOLUME, CH_R), 0x57, 0x57, 0, rt711_sdca_set_gain_get, rt711_sdca_set_gain_put, out_vol_tlv), - SOC_DOUBLE_R("FU1E Capture Switch", - SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_MUTE, CH_L), - SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_MUTE, CH_R), - 0, 1, 1), - SOC_DOUBLE_R("FU0F Capture Switch", - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_MUTE, CH_L), - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, RT711_SDCA_CTL_FU_MUTE, CH_R), - 0, 1, 1), + SOC_DOUBLE_EXT("FU1E Capture Switch", SND_SOC_NOPM, 0, 1, 1, 0, + rt711_sdca_fu1e_capture_get, rt711_sdca_fu1e_capture_put), + SOC_DOUBLE_EXT("FU0F Capture Switch", SND_SOC_NOPM, 0, 1, 1, 0, + rt711_sdca_fu0f_capture_get, rt711_sdca_fu0f_capture_put), SOC_DOUBLE_R_EXT_TLV("FU1E Capture Volume", SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_L), SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, RT711_SDCA_CTL_FU_VOLUME, CH_R), @@ -809,28 +913,15 @@ static int rt711_sdca_fu0f_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); - unsigned char unmute = 0x0, mute = 0x1; switch (event) { case SND_SOC_DAPM_POST_PMU: - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, - RT711_SDCA_CTL_FU_MUTE, CH_L), - unmute); - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, - RT711_SDCA_CTL_FU_MUTE, CH_R), - unmute); + rt711->fu0f_dapm_mute = false; + rt711_sdca_set_fu0f_capture_ctl(rt711); break; case SND_SOC_DAPM_PRE_PMD: - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, - RT711_SDCA_CTL_FU_MUTE, CH_L), - mute); - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_JACK_CODEC, RT711_SDCA_ENT_USER_FU0F, - RT711_SDCA_CTL_FU_MUTE, CH_R), - mute); + rt711->fu0f_dapm_mute = true; + rt711_sdca_set_fu0f_capture_ctl(rt711); break; } return 0; @@ -842,29 +933,16 @@ static int rt711_sdca_fu1e_event(struct snd_soc_dapm_widget *w, struct snd_soc_component *component = snd_soc_dapm_to_component(w->dapm); struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); - unsigned char unmute = 0x0, mute = 0x1; switch (event) { case SND_SOC_DAPM_POST_PMU: - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, - RT711_SDCA_CTL_FU_MUTE, CH_L), - unmute); - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, - RT711_SDCA_CTL_FU_MUTE, CH_R), - unmute); + rt711->fu1e_dapm_mute = false; + rt711_sdca_set_fu1e_capture_ctl(rt711); break; case SND_SOC_DAPM_PRE_PMD: - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, - RT711_SDCA_CTL_FU_MUTE, CH_L), - mute); - regmap_write(rt711->regmap, - SDW_SDCA_CTL(FUNC_NUM_MIC_ARRAY, RT711_SDCA_ENT_USER_FU1E, - RT711_SDCA_CTL_FU_MUTE, CH_R), - mute); - break; + rt711->fu1e_dapm_mute = true; + rt711_sdca_set_fu1e_capture_ctl(rt711); + break; } return 0; } @@ -1330,6 +1408,10 @@ int rt711_sdca_init(struct device *dev, struct regmap *regmap, */ rt711->hw_init = false; rt711->first_hw_init = false; + rt711->fu0f_dapm_mute = true; + rt711->fu1e_dapm_mute = true; + rt711->fu0f_mixer_l_mute = rt711->fu0f_mixer_r_mute = true; + rt711->fu1e_mixer_l_mute = rt711->fu1e_mixer_r_mute = true; /* JD source uses JD2 in default */ rt711->jd_src = RT711_JD2; diff --git a/sound/soc/codecs/rt711-sdca.h b/sound/soc/codecs/rt711-sdca.h index 98a022cec0bd..43ae82b7fdb3 100644 --- a/sound/soc/codecs/rt711-sdca.h +++ b/sound/soc/codecs/rt711-sdca.h @@ -30,6 +30,8 @@ struct rt711_sdca_priv { int jack_type, jd_src; unsigned int scp_sdca_stat1, scp_sdca_stat2; int hw_ver; + bool fu0f_dapm_mute, fu0f_mixer_l_mute, fu0f_mixer_r_mute; + bool fu1e_dapm_mute, fu1e_mixer_l_mute, fu1e_mixer_r_mute; }; struct sdw_stream_data { From a1aee7f7b71155595a06f21f2d021b6a58d04017 Mon Sep 17 00:00:00 2001 From: Shuming Fan Date: Thu, 22 Apr 2021 18:32:35 +0800 Subject: [PATCH 1090/1091] ASoC: rt711-sdca: add the notification when volume changed This patch adds the return value when the volume settings were changed. The userspace application might monitor the kcontrols to check which control changed. Signed-off-by: Shuming Fan Link: https://lore.kernel.org/r/20210422103235.22048-1-shumingf@realtek.com Signed-off-by: Mark Brown --- sound/soc/codecs/rt711-sdca.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/sound/soc/codecs/rt711-sdca.c b/sound/soc/codecs/rt711-sdca.c index 39848d2641c3..cc36739f7fcf 100644 --- a/sound/soc/codecs/rt711-sdca.c +++ b/sound/soc/codecs/rt711-sdca.c @@ -509,12 +509,16 @@ static int rt711_sdca_set_gain_put(struct snd_kcontrol *kcontrol, (struct soc_mixer_control *)kcontrol->private_value; struct rt711_sdca_priv *rt711 = snd_soc_component_get_drvdata(component); unsigned int read_l, read_r, gain_l_val, gain_r_val; - unsigned int i, adc_vol_flag = 0; + unsigned int i, adc_vol_flag = 0, changed = 0; + unsigned int lvalue, rvalue; if (strstr(ucontrol->id.name, "FU1E Capture Volume") || strstr(ucontrol->id.name, "FU0F Capture Volume")) adc_vol_flag = 1; + regmap_read(rt711->mbq_regmap, mc->reg, &lvalue); + regmap_read(rt711->mbq_regmap, mc->rreg, &rvalue); + /* control value to 2's complement value */ /* L Channel */ gain_l_val = ucontrol->value.integer.value[0]; @@ -560,6 +564,11 @@ static int rt711_sdca_set_gain_put(struct snd_kcontrol *kcontrol, gain_r_val &= 0xffff; } + if (lvalue != gain_l_val || rvalue != gain_r_val) + changed = 1; + else + return 0; + for (i = 0; i < 3; i++) { /* retry 3 times at most */ /* Lch*/ regmap_write(rt711->mbq_regmap, mc->reg, gain_l_val); @@ -573,7 +582,7 @@ static int rt711_sdca_set_gain_put(struct snd_kcontrol *kcontrol, break; } - return i == 3 ? -EIO : 0; + return i == 3 ? -EIO : changed; } static int rt711_sdca_set_gain_get(struct snd_kcontrol *kcontrol, From 25c4a9b614f101bb9f3e687960815db7dc439c0f Mon Sep 17 00:00:00 2001 From: Mark Brown Date: Fri, 23 Apr 2021 18:07:54 +0100 Subject: [PATCH 1091/1091] ASoC: simple-card: Fix breakage on kontron-sl28-var3-ads2 A KernelCI bisection identified 59c35c44a9cf89 "ASoC: simple-card: add simple_parse_node()" as causing simple-card to fail to instantiate on kontron-sl28-var3-ads2 systems. Since the merge window is expected to open over the weekend drop that commit and subsequent ones which depend on it for now in case other systems are affected too. The boot log showed the error as: <4>[ 9.948821] sysfs: cannot create duplicate filename '/devices/platform/sound/(null)-wm8904-hifi' (backtrace) <3>[ 10.191982] kobject_add_internal failed for (null)-wm8904-hifi with -EEXIST, don't try to register things with the same name in the same directory. The dropped commits are: 73371bacf0475a20ab6 "ASoC: audio-graph: tidyup graph_dai_link_of_dpcm()" 434392271afcff350fe "ASoC: simple-card: add simple_link_init()" 59c35c44a9cf89a83a9 "ASoC: simple-card: add simple_parse_node()" Reported-by: Guillaume Tucker Reported-by: "kernelci.org bot" Signed-off-by: Mark Brown --- sound/soc/generic/audio-graph-card.c | 30 ++--- sound/soc/generic/simple-card.c | 178 ++++++++++++++------------- 2 files changed, 106 insertions(+), 102 deletions(-) diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 0159a4576e9c..2c8a2fcb7922 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -276,19 +276,24 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct link_info *li) { struct device *dev = simple_priv_to_dev(priv); + struct snd_soc_card *card = simple_priv_to_card(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); struct device_node *top = dev->of_node; struct device_node *ep = li->cpu ? cpu_ep : codec_ep; + struct device_node *port; + struct device_node *ports; + struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); + struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); char dai_name[64]; int ret; + port = of_get_parent(ep); + ports = of_get_parent(port); + dev_dbg(dev, "link_of DPCM (%pOF)\n", ep); if (li->cpu) { - struct snd_soc_card *card = simple_priv_to_card(priv); - struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); - /* Codec is dummy */ /* FE settings */ @@ -297,7 +302,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = graph_parse_node(priv, cpu_ep, li, 1); if (ret) - return ret; + goto out_put_node; snprintf(dai_name, sizeof(dai_name), "fe.%pOFP.%s", cpus->of_node, cpus->dai_name); @@ -314,10 +319,7 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (card->component_chaining && !soc_component_is_pcm(cpus)) dai_link->no_pcm = 1; } else { - struct snd_soc_codec_conf *cconf = simple_props_to_codec_conf(dai_props, 0); - struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); - struct device_node *port; - struct device_node *ports; + struct snd_soc_codec_conf *cconf; /* CPU is dummy */ @@ -325,25 +327,22 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; + cconf = simple_props_to_codec_conf(dai_props, 0); + ret = graph_parse_node(priv, codec_ep, li, 0); if (ret < 0) - return ret; + goto out_put_node; snprintf(dai_name, sizeof(dai_name), "be.%pOFP.%s", codecs->of_node, codecs->dai_name); /* check "prefix" from top node */ - port = of_get_parent(ep); - ports = of_get_parent(port); snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, "prefix"); if (of_node_name_eq(ports, "ports")) snd_soc_of_parse_node_prefix(ports, cconf, codecs->of_node, "prefix"); snd_soc_of_parse_node_prefix(port, cconf, codecs->of_node, "prefix"); - - of_node_put(ports); - of_node_put(port); } graph_parse_convert(dev, ep, &dai_props->adata); @@ -352,8 +351,11 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, ret = graph_link_init(priv, cpu_ep, codec_ep, li, dai_name); +out_put_node: li->link++; + of_node_put(ports); + of_node_put(port); return ret; } diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 6a04632944b8..a1373be4558f 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -93,11 +93,12 @@ static void simple_parse_convert(struct device *dev, } static void simple_parse_mclk_fs(struct device_node *top, - struct device_node *np, + struct device_node *cpu, + struct device_node *codec, struct simple_dai_props *props, char *prefix) { - struct device_node *node = of_get_parent(np); + struct device_node *node = of_get_parent(cpu); char prop[128]; snprintf(prop, sizeof(prop), "%smclk-fs", PREFIX); @@ -105,79 +106,12 @@ static void simple_parse_mclk_fs(struct device_node *top, snprintf(prop, sizeof(prop), "%smclk-fs", prefix); of_property_read_u32(node, prop, &props->mclk_fs); - of_property_read_u32(np, prop, &props->mclk_fs); + of_property_read_u32(cpu, prop, &props->mclk_fs); + of_property_read_u32(codec, prop, &props->mclk_fs); of_node_put(node); } -static int simple_parse_node(struct asoc_simple_priv *priv, - struct device_node *np, - struct link_info *li, - char *prefix, - int is_cpu) -{ - struct device *dev = simple_priv_to_dev(priv); - struct device_node *top = dev->of_node; - struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); - struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); - struct snd_soc_dai_link_component *dlc; - struct asoc_simple_dai *dai; - int ret, single = 0; - - if (is_cpu) { - dlc = asoc_link_to_cpu(dai_link, 0); - dai = simple_props_to_dai_cpu(dai_props, 0); - } else { - dlc = asoc_link_to_codec(dai_link, 0); - dai = simple_props_to_dai_codec(dai_props, 0); - } - - simple_parse_mclk_fs(top, np, dai_props, prefix); - - ret = asoc_simple_parse_dai(np, dlc, &single); - if (ret) - return ret; - - ret = asoc_simple_parse_clk(dev, np, dai, dlc); - if (ret) - return ret; - - ret = asoc_simple_parse_tdm(np, dai); - if (ret) - return ret; - - if (is_cpu) { - struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); - - asoc_simple_canonicalize_cpu(dlc, single); - asoc_simple_canonicalize_platform(platforms, dlc); - } - - return 0; -} - -static int simple_link_init(struct asoc_simple_priv *priv, - struct device_node *node, - struct device_node *codec, - struct link_info *li, - char *prefix, - char *name) -{ - struct device *dev = simple_priv_to_dev(priv); - struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); - int ret; - - ret = asoc_simple_parse_daifmt(dev, node, codec, - prefix, &dai_link->dai_fmt); - if (ret < 0) - return 0; - - dai_link->init = asoc_simple_dai_init; - dai_link->ops = &simple_ops; - - return asoc_simple_set_dailink_name(dev, dai_link, name); -} - static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device_node *np, struct device_node *codec, @@ -187,32 +121,50 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); + struct asoc_simple_dai *dai; struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); + struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); struct device_node *top = dev->of_node; struct device_node *node = of_get_parent(np); char *prefix = ""; - char dai_name[64]; int ret; dev_dbg(dev, "link_of DPCM (%pOF)\n", np); + li->link++; + /* For single DAI link & old style of DT node */ if (is_top) prefix = PREFIX; if (li->cpu) { + int is_single_links = 0; + /* Codec is dummy */ /* FE settings */ dai_link->dynamic = 1; dai_link->dpcm_merged_format = 1; - ret = simple_parse_node(priv, np, li, prefix, 1); + dai = simple_props_to_dai_cpu(dai_props, 0); + + ret = asoc_simple_parse_dai(np, cpus, &is_single_links); + if (ret) + goto out_put_node; + + ret = asoc_simple_parse_clk(dev, np, dai, cpus); if (ret < 0) goto out_put_node; - snprintf(dai_name, sizeof(dai_name), "fe.%s", cpus->dai_name); + ret = asoc_simple_set_dailink_name(dev, dai_link, + "fe.%s", + cpus->dai_name); + if (ret < 0) + goto out_put_node; + + asoc_simple_canonicalize_cpu(cpus, is_single_links); + asoc_simple_canonicalize_platform(platforms, cpus); } else { struct snd_soc_codec_conf *cconf; @@ -222,13 +174,22 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, dai_link->no_pcm = 1; dai_link->be_hw_params_fixup = asoc_simple_be_hw_params_fixup; + dai = simple_props_to_dai_codec(dai_props, 0); cconf = simple_props_to_codec_conf(dai_props, 0); - ret = simple_parse_node(priv, np, li, prefix, 0); + ret = asoc_simple_parse_dai(np, codecs, NULL); if (ret < 0) goto out_put_node; - snprintf(dai_name, sizeof(dai_name), "be.%s", codecs->dai_name); + ret = asoc_simple_parse_clk(dev, np, dai, codecs); + if (ret < 0) + goto out_put_node; + + ret = asoc_simple_set_dailink_name(dev, dai_link, + "be.%s", + codecs->dai_name); + if (ret < 0) + goto out_put_node; /* check "prefix" from top node */ snd_soc_of_parse_node_prefix(top, cconf, codecs->of_node, @@ -240,14 +201,23 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, } simple_parse_convert(dev, np, &dai_props->adata); + simple_parse_mclk_fs(top, np, codec, dai_props, prefix); + + ret = asoc_simple_parse_tdm(np, dai); + if (ret) + goto out_put_node; + + ret = asoc_simple_parse_daifmt(dev, node, codec, + prefix, &dai_link->dai_fmt); + if (ret < 0) + goto out_put_node; snd_soc_dai_link_set_capabilities(dai_link); - ret = simple_link_init(priv, node, codec, li, prefix, dai_name); + dai_link->ops = &simple_ops; + dai_link->init = asoc_simple_dai_init; out_put_node: - li->link++; - of_node_put(node); return ret; } @@ -260,19 +230,23 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, { struct device *dev = simple_priv_to_dev(priv); struct snd_soc_dai_link *dai_link = simple_priv_to_link(priv, li->link); + struct simple_dai_props *dai_props = simple_priv_to_props(priv, li->link); + struct asoc_simple_dai *cpu_dai = simple_props_to_dai_cpu(dai_props, 0); + struct asoc_simple_dai *codec_dai = simple_props_to_dai_codec(dai_props, 0); struct snd_soc_dai_link_component *cpus = asoc_link_to_cpu(dai_link, 0); struct snd_soc_dai_link_component *codecs = asoc_link_to_codec(dai_link, 0); struct snd_soc_dai_link_component *platforms = asoc_link_to_platform(dai_link, 0); + struct device_node *top = dev->of_node; struct device_node *cpu = NULL; struct device_node *node = NULL; struct device_node *plat = NULL; - char dai_name[64]; char prop[128]; char *prefix = ""; - int ret; + int ret, single_cpu = 0; cpu = np; node = of_get_parent(np); + li->link++; dev_dbg(dev, "link_of (%pOF)\n", node); @@ -283,11 +257,18 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, snprintf(prop, sizeof(prop), "%splat", prefix); plat = of_get_child_by_name(node, prop); - ret = simple_parse_node(priv, cpu, li, prefix, 1); + ret = asoc_simple_parse_daifmt(dev, node, codec, + prefix, &dai_link->dai_fmt); if (ret < 0) goto dai_link_of_err; - ret = simple_parse_node(priv, codec, li, prefix, 0); + simple_parse_mclk_fs(top, cpu, codec, dai_props, prefix); + + ret = asoc_simple_parse_dai(cpu, cpus, &single_cpu); + if (ret < 0) + goto dai_link_of_err; + + ret = asoc_simple_parse_dai(codec, codecs, NULL); if (ret < 0) goto dai_link_of_err; @@ -295,18 +276,39 @@ static int simple_dai_link_of(struct asoc_simple_priv *priv, if (ret < 0) goto dai_link_of_err; - snprintf(dai_name, sizeof(dai_name), - "%s-%s", cpus->dai_name, codecs->dai_name); - ret = simple_link_init(priv, node, codec, li, prefix, dai_name); + ret = asoc_simple_parse_tdm(cpu, cpu_dai); if (ret < 0) goto dai_link_of_err; + ret = asoc_simple_parse_tdm(codec, codec_dai); + if (ret < 0) + goto dai_link_of_err; + + ret = asoc_simple_parse_clk(dev, cpu, cpu_dai, cpus); + if (ret < 0) + goto dai_link_of_err; + + ret = asoc_simple_parse_clk(dev, codec, codec_dai, codecs); + if (ret < 0) + goto dai_link_of_err; + + ret = asoc_simple_set_dailink_name(dev, dai_link, + "%s-%s", + cpus->dai_name, + codecs->dai_name); + if (ret < 0) + goto dai_link_of_err; + + dai_link->ops = &simple_ops; + dai_link->init = asoc_simple_dai_init; + + asoc_simple_canonicalize_cpu(cpus, single_cpu); + asoc_simple_canonicalize_platform(platforms, cpus); + dai_link_of_err: of_node_put(plat); of_node_put(node); - li->link++; - return ret; }