diff options
237 files changed, 2896 insertions, 2880 deletions
@@ -198,6 +198,9 @@ Maxime Ripard <mripard@kernel.org> <maxime.ripard@free-electrons.com> Mayuresh Janorkar <mayur@ti.com> Michael Buesch <m@bues.ch> Michel Dänzer <michel@tungstengraphics.com> +Mike Rapoport <rppt@kernel.org> <mike@compulab.co.il> +Mike Rapoport <rppt@kernel.org> <mike.rapoport@gmail.com> +Mike Rapoport <rppt@kernel.org> <rppt@linux.ibm.com> Miodrag Dinic <miodrag.dinic@mips.com> <miodrag.dinic@imgtec.com> Miquel Raynal <miquel.raynal@bootlin.com> <miquel.raynal@free-electrons.com> Mitesh shah <mshah@teja.com> diff --git a/Documentation/devicetree/bindings/sound/simple-card.yaml b/Documentation/devicetree/bindings/sound/simple-card.yaml index 8132d0c0f00a..35e669020296 100644 --- a/Documentation/devicetree/bindings/sound/simple-card.yaml +++ b/Documentation/devicetree/bindings/sound/simple-card.yaml @@ -378,6 +378,8 @@ examples: - | sound { compatible = "simple-audio-card"; + #address-cells = <1>; + #size-cells = <0>; simple-audio-card,name = "rsnd-ak4643"; simple-audio-card,format = "left_j"; @@ -391,10 +393,12 @@ examples: "ak4642 Playback", "DAI1 Playback"; dpcmcpu: simple-audio-card,cpu@0 { + reg = <0>; sound-dai = <&rcar_sound 0>; }; simple-audio-card,cpu@1 { + reg = <1>; sound-dai = <&rcar_sound 1>; }; @@ -418,6 +422,8 @@ examples: - | sound { compatible = "simple-audio-card"; + #address-cells = <1>; + #size-cells = <0>; simple-audio-card,routing = "pcm3168a Playback", "DAI1 Playback", @@ -426,6 +432,7 @@ examples: "pcm3168a Playback", "DAI4 Playback"; simple-audio-card,dai-link@0 { + reg = <0>; format = "left_j"; bitclock-master = <&sndcpu0>; frame-master = <&sndcpu0>; @@ -439,22 +446,23 @@ examples: }; simple-audio-card,dai-link@1 { + reg = <1>; format = "i2s"; bitclock-master = <&sndcpu1>; frame-master = <&sndcpu1>; convert-channels = <8>; /* TDM Split */ - sndcpu1: cpu@0 { + sndcpu1: cpu0 { sound-dai = <&rcar_sound 1>; }; - cpu@1 { + cpu1 { sound-dai = <&rcar_sound 2>; }; - cpu@2 { + cpu2 { sound-dai = <&rcar_sound 3>; }; - cpu@3 { + cpu3 { sound-dai = <&rcar_sound 4>; }; codec { @@ -466,6 +474,7 @@ examples: }; simple-audio-card,dai-link@2 { + reg = <2>; format = "i2s"; bitclock-master = <&sndcpu2>; frame-master = <&sndcpu2>; diff --git a/Documentation/driver-api/ptp.rst b/Documentation/driver-api/ptp.rst index a15192e32347..664838ae7776 100644 --- a/Documentation/driver-api/ptp.rst +++ b/Documentation/driver-api/ptp.rst @@ -23,6 +23,7 @@ PTP hardware clock infrastructure for Linux + Ancillary clock features - Time stamp external events - Period output signals configurable from user space + - Low Pass Filter (LPF) access from user space - Synchronization of the Linux system time via the PPS subsystem PTP hardware clock kernel API @@ -94,3 +95,14 @@ Supported hardware - Auxiliary Slave/Master Mode Snapshot (optional interrupt) - Target Time (optional interrupt) + + * Renesas (IDT) ClockMatrixâ„¢ + + - Up to 4 independent PHC channels + - Integrated low pass filter (LPF), access via .adjPhase (compliant to ITU-T G.8273.2) + - Programmable output periodic signals + - Programmable inputs can time stamp external triggers + - Driver and/or hardware configuration through firmware (idtcm.bin) + - LPF settings (bandwidth, phase limiting, automatic holdover, physical layer assist (per ITU-T G.8273.2)) + - Programmable output PTP clocks, any frequency up to 1GHz (to other PHY/MAC time stampers, refclk to ASSPs/SoCs/FPGAs) + - Lock to GNSS input, automatic switching between GNSS and user-space PHC control (optional) diff --git a/Documentation/networking/bareudp.rst b/Documentation/networking/bareudp.rst index 465a8b251bfe..ff406563ea88 100644 --- a/Documentation/networking/bareudp.rst +++ b/Documentation/networking/bareudp.rst @@ -26,7 +26,7 @@ Usage 1) Device creation & deletion - a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype 0x8847. + a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype mpls_uc This creates a bareudp tunnel device which tunnels L3 traffic with ethertype 0x8847 (MPLS traffic). The destination port of the UDP header will be set to @@ -34,14 +34,21 @@ Usage b) ip link delete bareudp0 -2) Device creation with multiple proto mode enabled +2) Device creation with multiproto mode enabled -There are two ways to create a bareudp device for MPLS & IP with multiproto mode -enabled. +The multiproto mode allows bareudp tunnels to handle several protocols of the +same family. It is currently only available for IP and MPLS. This mode has to +be enabled explicitly with the "multiproto" flag. - a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype 0x8847 multiproto + a) ip link add dev bareudp0 type bareudp dstport 6635 ethertype ipv4 multiproto - b) ip link add dev bareudp0 type bareudp dstport 6635 ethertype mpls + For an IPv4 tunnel the multiproto mode allows the tunnel to also handle + IPv6. + + b) ip link add dev bareudp0 type bareudp dstport 6635 ethertype mpls_uc multiproto + + For MPLS, the multiproto mode allows the tunnel to handle both unicast + and multicast MPLS packets. 3) Device Usage diff --git a/MAINTAINERS b/MAINTAINERS index d53db30d1365..f0569cf304ca 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -6956,6 +6956,7 @@ M: Timur Tabi <timur@kernel.org> M: Nicolin Chen <nicoleotsuka@gmail.com> M: Xiubo Li <Xiubo.Lee@gmail.com> R: Fabio Estevam <festevam@gmail.com> +R: Shengjiu Wang <shengjiu.wang@gmail.com> L: alsa-devel@alsa-project.org (moderated for non-subscribers) L: linuxppc-dev@lists.ozlabs.org S: Maintained @@ -9305,6 +9306,17 @@ F: Documentation/kbuild/kconfig* F: scripts/Kconfig.include F: scripts/kconfig/ +KCOV +R: Dmitry Vyukov <dvyukov@google.com> +R: Andrey Konovalov <andreyknvl@google.com> +L: kasan-dev@googlegroups.com +S: Maintained +F: Documentation/dev-tools/kcov.rst +F: include/linux/kcov.h +F: include/uapi/linux/kcov.h +F: kernel/kcov.c +F: scripts/Makefile.kcov + KCSAN M: Marco Elver <elver@google.com> R: Dmitry Vyukov <dvyukov@google.com> @@ -11240,7 +11252,7 @@ S: Maintained F: drivers/crypto/atmel-ecc.* MICROCHIP I2C DRIVER -M: Ludovic Desroches <ludovic.desroches@microchip.com> +M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> L: linux-i2c@vger.kernel.org S: Supported F: drivers/i2c/busses/i2c-at91-*.c @@ -11333,17 +11345,17 @@ F: drivers/iio/adc/at91-sama5d2_adc.c F: include/dt-bindings/iio/adc/at91-sama5d2_adc.h MICROCHIP SAMA5D2-COMPATIBLE SHUTDOWN CONTROLLER -M: Nicolas Ferre <nicolas.ferre@microchip.com> +M: Claudiu Beznea <claudiu.beznea@microchip.com> S: Supported F: drivers/power/reset/at91-sama5d2_shdwc.c MICROCHIP SPI DRIVER -M: Nicolas Ferre <nicolas.ferre@microchip.com> +M: Tudor Ambarus <tudor.ambarus@microchip.com> S: Supported F: drivers/spi/spi-atmel.* MICROCHIP SSC DRIVER -M: Nicolas Ferre <nicolas.ferre@microchip.com> +M: Codrin Ciubotariu <codrin.ciubotariu@microchip.com> L: linux-arm-kernel@lists.infradead.org (moderated for non-subscribers) S: Supported F: drivers/misc/atmel-ssc.c @@ -14862,6 +14874,7 @@ F: drivers/s390/block/dasd* F: include/linux/dasd_mod.h S390 IOMMU (PCI) +M: Matthew Rosato <mjrosato@linux.ibm.com> M: Gerald Schaefer <gerald.schaefer@linux.ibm.com> L: linux-s390@vger.kernel.org S: Supported diff --git a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts index c8243da71041..eb01cc96ba7a 100644 --- a/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts +++ b/arch/arm64/boot/dts/marvell/armada-8040-clearfog-gt-8k.dts @@ -454,10 +454,7 @@ status = "okay"; phy-mode = "2500base-x"; phys = <&cp1_comphy5 2>; - fixed-link { - speed = <2500>; - full-duplex; - }; + managed = "in-band-status"; }; &cp1_spi1 { diff --git a/arch/arm64/kernel/vdso32/Makefile b/arch/arm64/kernel/vdso32/Makefile index d88148bef6b0..5139a5f19256 100644 --- a/arch/arm64/kernel/vdso32/Makefile +++ b/arch/arm64/kernel/vdso32/Makefile @@ -14,7 +14,7 @@ COMPAT_GCC_TOOLCHAIN_DIR := $(dir $(shell which $(CROSS_COMPILE_COMPAT)elfedit)) COMPAT_GCC_TOOLCHAIN := $(realpath $(COMPAT_GCC_TOOLCHAIN_DIR)/..) CC_COMPAT_CLANG_FLAGS := --target=$(notdir $(CROSS_COMPILE_COMPAT:%-=%)) -CC_COMPAT_CLANG_FLAGS += --prefix=$(COMPAT_GCC_TOOLCHAIN_DIR) +CC_COMPAT_CLANG_FLAGS += --prefix=$(COMPAT_GCC_TOOLCHAIN_DIR)$(notdir $(CROSS_COMPILE_COMPAT)) CC_COMPAT_CLANG_FLAGS += -no-integrated-as -Qunused-arguments ifneq ($(COMPAT_GCC_TOOLCHAIN),) CC_COMPAT_CLANG_FLAGS += --gcc-toolchain=$(COMPAT_GCC_TOOLCHAIN) diff --git a/arch/s390/kernel/perf_cpum_cf_events.c b/arch/s390/kernel/perf_cpum_cf_events.c index 1e3df52b2b65..37265f551a11 100644 --- a/arch/s390/kernel/perf_cpum_cf_events.c +++ b/arch/s390/kernel/perf_cpum_cf_events.c @@ -292,7 +292,7 @@ CPUMF_EVENT_ATTR(cf_z15, TX_C_TABORT_SPECIAL, 0x00f5); CPUMF_EVENT_ATTR(cf_z15, DFLT_ACCESS, 0x00f7); CPUMF_EVENT_ATTR(cf_z15, DFLT_CYCLES, 0x00fc); CPUMF_EVENT_ATTR(cf_z15, DFLT_CC, 0x00108); -CPUMF_EVENT_ATTR(cf_z15, DFLT_CCERROR, 0x00109); +CPUMF_EVENT_ATTR(cf_z15, DFLT_CCFINISH, 0x00109); CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE, 0x01c0); CPUMF_EVENT_ATTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE, 0x01c1); @@ -629,7 +629,7 @@ static struct attribute *cpumcf_z15_pmu_event_attr[] __initdata = { CPUMF_EVENT_PTR(cf_z15, DFLT_ACCESS), CPUMF_EVENT_PTR(cf_z15, DFLT_CYCLES), CPUMF_EVENT_PTR(cf_z15, DFLT_CC), - CPUMF_EVENT_PTR(cf_z15, DFLT_CCERROR), + CPUMF_EVENT_PTR(cf_z15, DFLT_CCFINISH), CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_ONE_THR_ACTIVE), CPUMF_EVENT_PTR(cf_z15, MT_DIAG_CYCLES_TWO_THR_ACTIVE), NULL, diff --git a/arch/x86/include/asm/iosf_mbi.h b/arch/x86/include/asm/iosf_mbi.h index 5270ff39b9af..a1911fea8739 100644 --- a/arch/x86/include/asm/iosf_mbi.h +++ b/arch/x86/include/asm/iosf_mbi.h @@ -39,6 +39,7 @@ #define BT_MBI_UNIT_PMC 0x04 #define BT_MBI_UNIT_GFX 0x06 #define BT_MBI_UNIT_SMI 0x0C +#define BT_MBI_UNIT_CCK 0x14 #define BT_MBI_UNIT_USB 0x43 #define BT_MBI_UNIT_SATA 0xA3 #define BT_MBI_UNIT_PCIE 0xA6 diff --git a/arch/x86/kernel/fpu/xstate.c b/arch/x86/kernel/fpu/xstate.c index bda2e5eaca0e..ad3a2b37927d 100644 --- a/arch/x86/kernel/fpu/xstate.c +++ b/arch/x86/kernel/fpu/xstate.c @@ -1074,7 +1074,7 @@ int copy_xstate_to_kernel(void *kbuf, struct xregs_state *xsave, unsigned int of copy_part(offsetof(struct fxregs_state, st_space), 128, &xsave->i387.st_space, &kbuf, &offset_start, &count); if (header.xfeatures & XFEATURE_MASK_SSE) - copy_part(xstate_offsets[XFEATURE_MASK_SSE], 256, + copy_part(xstate_offsets[XFEATURE_SSE], 256, &xsave->i387.xmm_space, &kbuf, &offset_start, &count); /* * Fill xsave->i387.sw_reserved value for ptrace frame: diff --git a/arch/xtensa/include/asm/checksum.h b/arch/xtensa/include/asm/checksum.h index d8292cc9ebdf..243a5fe79d3c 100644 --- a/arch/xtensa/include/asm/checksum.h +++ b/arch/xtensa/include/asm/checksum.h @@ -57,7 +57,7 @@ static inline __wsum csum_and_copy_from_user(const void __user *src, void *dst, int len, __wsum sum, int *err_ptr) { - if (access_ok(dst, len)) + if (access_ok(src, len)) return csum_partial_copy_generic((__force const void *)src, dst, len, sum, err_ptr, NULL); if (len) diff --git a/drivers/crypto/chelsio/chtls/chtls_cm.c b/drivers/crypto/chelsio/chtls/chtls_cm.c index f200fae6f7cb..54093115eb95 100644 --- a/drivers/crypto/chelsio/chtls/chtls_cm.c +++ b/drivers/crypto/chelsio/chtls/chtls_cm.c @@ -102,7 +102,7 @@ static struct net_device *chtls_find_netdev(struct chtls_dev *cdev, case PF_INET: if (likely(!inet_sk(sk)->inet_rcv_saddr)) return ndev; - ndev = ip_dev_find(&init_net, inet_sk(sk)->inet_rcv_saddr); + ndev = __ip_dev_find(&init_net, inet_sk(sk)->inet_rcv_saddr, false); break; #if IS_ENABLED(CONFIG_IPV6) case PF_INET6: diff --git a/drivers/crypto/chelsio/chtls/chtls_io.c b/drivers/crypto/chelsio/chtls/chtls_io.c index e1401d9cc756..2e9acae1cba3 100644 --- a/drivers/crypto/chelsio/chtls/chtls_io.c +++ b/drivers/crypto/chelsio/chtls/chtls_io.c @@ -1052,14 +1052,15 @@ int chtls_sendmsg(struct sock *sk, struct msghdr *msg, size_t size) &record_type); if (err) goto out_err; + + /* Avoid appending tls handshake, alert to tls data */ + if (skb) + tx_skb_finalize(skb); } recordsz = size; csk->tlshws.txleft = recordsz; csk->tlshws.type = record_type; - - if (skb) - ULP_SKB_CB(skb)->ulp.tls.type = record_type; } if (!skb || (ULP_SKB_CB(skb)->flags & ULPCB_FLAG_NO_APPEND) || diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 02e6f8c4dde0..ebb8a28ff002 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -778,8 +778,7 @@ static ssize_t amdgpu_set_pp_od_clk_voltage(struct device *dev, tmp_str++; while (isspace(*++tmp_str)); - while (tmp_str[0]) { - sub_str = strsep(&tmp_str, delimiter); + while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); if (ret) return -EINVAL; @@ -1039,8 +1038,7 @@ static ssize_t amdgpu_read_mask(const char *buf, size_t count, uint32_t *mask) memcpy(buf_cpy, buf, bytes); buf_cpy[bytes] = '\0'; tmp = buf_cpy; - while (tmp[0]) { - sub_str = strsep(&tmp, delimiter); + while ((sub_str = strsep(&tmp, delimiter)) != NULL) { if (strlen(sub_str)) { ret = kstrtol(sub_str, 0, &level); if (ret) @@ -1637,8 +1635,7 @@ static ssize_t amdgpu_set_pp_power_profile_mode(struct device *dev, i++; memcpy(buf_cpy, buf, count-i); tmp_str = buf_cpy; - while (tmp_str[0]) { - sub_str = strsep(&tmp_str, delimiter); + while ((sub_str = strsep(&tmp_str, delimiter)) != NULL) { ret = kstrtol(sub_str, 0, ¶meter[parameter_size]); if (ret) return -EINVAL; diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c index 3da71a088b92..0ecc18b55ffb 100644 --- a/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c +++ b/drivers/gpu/drm/amd/powerplay/smumgr/vegam_smumgr.c @@ -644,9 +644,6 @@ static int vegam_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, /* sclk is bigger than max sclk in the dependence table */ *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; - vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), - (dep_table->entries[i - 1].vddc - - (uint16_t)VDDC_VDDCI_DELTA)); if (SMU7_VOLTAGE_CONTROL_NONE == data->vddci_control) *voltage |= (data->vbios_boot_state.vddci_bootup_value * @@ -654,8 +651,13 @@ static int vegam_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, else if (dep_table->entries[i - 1].vddci) *voltage |= (dep_table->entries[i - 1].vddci * VOLTAGE_SCALE) << VDDC_SHIFT; - else + else { + vddci = phm_find_closest_vddci(&(data->vddci_voltage_table), + (dep_table->entries[i - 1].vddc - + (uint16_t)VDDC_VDDCI_DELTA)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } if (SMU7_VOLTAGE_CONTROL_NONE == data->mvdd_control) *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; diff --git a/drivers/gpu/drm/lima/lima_pp.c b/drivers/gpu/drm/lima/lima_pp.c index 33f01383409c..a5c95bed08c0 100644 --- a/drivers/gpu/drm/lima/lima_pp.c +++ b/drivers/gpu/drm/lima/lima_pp.c @@ -271,6 +271,8 @@ void lima_pp_fini(struct lima_ip *ip) int lima_pp_bcast_resume(struct lima_ip *ip) { + /* PP has been reset by individual PP resume */ + ip->data.async_reset = false; return 0; } diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c index 557cbe5ab35f..2f2c9f0a1071 100644 --- a/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c @@ -260,7 +260,7 @@ sun4i_hdmi_connector_detect(struct drm_connector *connector, bool force) unsigned long reg; reg = readl(hdmi->base + SUN4I_HDMI_HPD_REG); - if (reg & SUN4I_HDMI_HPD_HIGH) { + if (!(reg & SUN4I_HDMI_HPD_HIGH)) { cec_phys_addr_invalidate(hdmi->cec_adap); return connector_status_disconnected; } diff --git a/drivers/i2c/busses/i2c-cadence.c b/drivers/i2c/busses/i2c-cadence.c index 4b72398af505..e4b7f2a951ad 100644 --- a/drivers/i2c/busses/i2c-cadence.c +++ b/drivers/i2c/busses/i2c-cadence.c @@ -421,20 +421,21 @@ static irqreturn_t cdns_i2c_master_isr(void *ptr) /* Read data if receive data valid is set */ while (cdns_i2c_readreg(CDNS_I2C_SR_OFFSET) & CDNS_I2C_SR_RXDV) { - /* - * Clear hold bit that was set for FIFO control if - * RX data left is less than FIFO depth, unless - * repeated start is selected. - */ - if ((id->recv_count < CDNS_I2C_FIFO_DEPTH) && - !id->bus_hold_flag) - cdns_i2c_clear_bus_hold(id); - if (id->recv_count > 0) { *(id->p_recv_buf)++ = cdns_i2c_readreg(CDNS_I2C_DATA_OFFSET); id->recv_count--; id->curr_recv_count--; + + /* + * Clear hold bit that was set for FIFO control + * if RX data left is less than or equal to + * FIFO DEPTH unless repeated start is selected + */ + if (id->recv_count <= CDNS_I2C_FIFO_DEPTH && + !id->bus_hold_flag) + cdns_i2c_clear_bus_hold(id); + } else { dev_err(id->adap.dev.parent, "xfer_size reg rollover. xfer aborted!\n"); @@ -594,10 +595,8 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id) * Check for the message size against FIFO depth and set the * 'hold bus' bit if it is greater than FIFO depth. */ - if ((id->recv_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag) + if (id->recv_count > CDNS_I2C_FIFO_DEPTH) ctrl_reg |= CDNS_I2C_CR_HOLD; - else - ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD; cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); @@ -654,11 +653,8 @@ static void cdns_i2c_msend(struct cdns_i2c *id) * Check for the message size against FIFO depth and set the * 'hold bus' bit if it is greater than FIFO depth. */ - if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag) + if (id->send_count > CDNS_I2C_FIFO_DEPTH) ctrl_reg |= CDNS_I2C_CR_HOLD; - else - ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD; - cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET); /* Clear the interrupts in interrupt status register. */ diff --git a/drivers/i2c/busses/i2c-qcom-geni.c b/drivers/i2c/busses/i2c-qcom-geni.c index 18d1e4fd4cf3..7f130829bf01 100644 --- a/drivers/i2c/busses/i2c-qcom-geni.c +++ b/drivers/i2c/busses/i2c-qcom-geni.c @@ -367,7 +367,6 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); writel_relaxed(len, se->base + SE_I2C_RX_TRANS_LEN); - geni_se_setup_m_cmd(se, I2C_READ, m_param); if (dma_buf && geni_se_rx_dma_prep(se, dma_buf, len, &rx_dma)) { geni_se_select_mode(se, GENI_SE_FIFO); @@ -375,6 +374,8 @@ static int geni_i2c_rx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, dma_buf = NULL; } + geni_se_setup_m_cmd(se, I2C_READ, m_param); + time_left = wait_for_completion_timeout(&gi2c->done, XFER_TIMEOUT); if (!time_left) geni_i2c_abort_xfer(gi2c); @@ -408,7 +409,6 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, geni_se_select_mode(se, GENI_SE_FIFO); writel_relaxed(len, se->base + SE_I2C_TX_TRANS_LEN); - geni_se_setup_m_cmd(se, I2C_WRITE, m_param); if (dma_buf && geni_se_tx_dma_prep(se, dma_buf, len, &tx_dma)) { geni_se_select_mode(se, GENI_SE_FIFO); @@ -416,6 +416,8 @@ static int geni_i2c_tx_one_msg(struct geni_i2c_dev *gi2c, struct i2c_msg *msg, dma_buf = NULL; } + geni_se_setup_m_cmd(se, I2C_WRITE, m_param); + if (!dma_buf) /* Get FIFO IRQ */ writel_relaxed(1, se->base + SE_GENI_TX_WATERMARK_REG); diff --git a/drivers/i2c/busses/i2c-rcar.c b/drivers/i2c/busses/i2c-rcar.c index a45c4bf1ec01..2e3e1bb75013 100644 --- a/drivers/i2c/busses/i2c-rcar.c +++ b/drivers/i2c/busses/i2c-rcar.c @@ -868,6 +868,7 @@ static int rcar_unreg_slave(struct i2c_client *slave) /* disable irqs and ensure none is running before clearing ptr */ rcar_i2c_write(priv, ICSIER, 0); rcar_i2c_write(priv, ICSCR, 0); + rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */ synchronize_irq(priv->irq); priv->slave = NULL; @@ -969,6 +970,8 @@ static int rcar_i2c_probe(struct platform_device *pdev) if (ret < 0) goto out_pm_put; + rcar_i2c_write(priv, ICSAR, 0); /* Gen2: must be 0 if not using slave */ + if (priv->devtype == I2C_RCAR_GEN3) { priv->rstc = devm_reset_control_get_exclusive(&pdev->dev, NULL); if (!IS_ERR(priv->rstc)) { diff --git a/drivers/infiniband/core/cm.c b/drivers/infiniband/core/cm.c index 0d1377232933..dc0558b23158 100644 --- a/drivers/infiniband/core/cm.c +++ b/drivers/infiniband/core/cm.c @@ -3676,10 +3676,12 @@ static int cm_send_sidr_rep_locked(struct cm_id_private *cm_id_priv, return ret; } cm_id_priv->id.state = IB_CM_IDLE; + spin_lock_irq(&cm.lock); if (!RB_EMPTY_NODE(&cm_id_priv->sidr_id_node)) { rb_erase(&cm_id_priv->sidr_id_node, &cm.remote_sidr_table); RB_CLEAR_NODE(&cm_id_priv->sidr_id_node); } + spin_unlock_irq(&cm.lock); return 0; } diff --git a/drivers/infiniband/core/rdma_core.c b/drivers/infiniband/core/rdma_core.c index 3027cd2fb247..6d3ed7c6e19e 100644 --- a/drivers/infiniband/core/rdma_core.c +++ b/drivers/infiniband/core/rdma_core.c @@ -649,9 +649,6 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj, { struct ib_uverbs_file *ufile = attrs->ufile; - /* alloc_commit consumes the uobj kref */ - uobj->uapi_object->type_class->alloc_commit(uobj); - /* kref is held so long as the uobj is on the uobj list. */ uverbs_uobject_get(uobj); spin_lock_irq(&ufile->uobjects_lock); @@ -661,6 +658,9 @@ void rdma_alloc_commit_uobject(struct ib_uobject *uobj, /* matches atomic_set(-1) in alloc_uobj */ atomic_set(&uobj->usecnt, 0); + /* alloc_commit consumes the uobj kref */ + uobj->uapi_object->type_class->alloc_commit(uobj); + /* Matches the down_read in rdma_alloc_begin_uobject */ up_read(&ufile->hw_destroy_rwsem); } diff --git a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c index dd01a51816cc..0618ced45bf8 100644 --- a/drivers/infiniband/hw/hns/hns_roce_hw_v2.c +++ b/drivers/infiniband/hw/hns/hns_roce_hw_v2.c @@ -3954,6 +3954,15 @@ static int config_qp_sq_buf(struct hns_roce_dev *hr_dev, return 0; } +static inline enum ib_mtu get_mtu(struct ib_qp *ibqp, + const struct ib_qp_attr *attr) +{ + if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD) + return IB_MTU_4096; + + return attr->path_mtu; +} + static int modify_qp_init_to_rtr(struct ib_qp *ibqp, const struct ib_qp_attr *attr, int attr_mask, struct hns_roce_v2_qp_context *context, @@ -3965,6 +3974,7 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, struct ib_device *ibdev = &hr_dev->ib_dev; dma_addr_t trrl_ba; dma_addr_t irrl_ba; + enum ib_mtu mtu; u8 port_num; u64 *mtts; u8 *dmac; @@ -4062,23 +4072,23 @@ static int modify_qp_init_to_rtr(struct ib_qp *ibqp, roce_set_field(qpc_mask->byte_52_udpspn_dmac, V2_QPC_BYTE_52_DMAC_M, V2_QPC_BYTE_52_DMAC_S, 0); - /* mtu*(2^LP_PKTN_INI) should not bigger than 1 message length 64kb */ + mtu = get_mtu(ibqp, attr); + + if (attr_mask & IB_QP_PATH_MTU) { + roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, + V2_QPC_BYTE_24_MTU_S, mtu); + roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, + V2_QPC_BYTE_24_MTU_S, 0); + } + +#define MAX_LP_MSG_LEN 65536 + /* MTU*(2^LP_PKTN_INI) shouldn't be bigger than 64kb */ roce_set_field(context->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M, V2_QPC_BYTE_56_LP_PKTN_INI_S, - ilog2(hr_dev->caps.max_sq_inline / IB_MTU_4096)); + ilog2(MAX_LP_MSG_LEN / ib_mtu_enum_to_int(mtu))); roce_set_field(qpc_mask->byte_56_dqpn_err, V2_QPC_BYTE_56_LP_PKTN_INI_M, V2_QPC_BYTE_56_LP_PKTN_INI_S, 0); - if (ibqp->qp_type == IB_QPT_GSI || ibqp->qp_type == IB_QPT_UD) - roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, - V2_QPC_BYTE_24_MTU_S, IB_MTU_4096); - else if (attr_mask & IB_QP_PATH_MTU) - roce_set_field(context->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, - V2_QPC_BYTE_24_MTU_S, attr->path_mtu); - - roce_set_field(qpc_mask->byte_24_mtu_tc, V2_QPC_BYTE_24_MTU_M, - V2_QPC_BYTE_24_MTU_S, 0); - roce_set_bit(qpc_mask->byte_108_rx_reqepsn, V2_QPC_BYTE_108_RX_REQ_PSN_ERR_S, 0); roce_set_field(qpc_mask->byte_96_rx_reqmsn, V2_QPC_BYTE_96_RX_REQ_MSN_M, diff --git a/drivers/infiniband/hw/hns/hns_roce_mr.c b/drivers/infiniband/hw/hns/hns_roce_mr.c index 0e71ebee9e52..6b226a5eb7db 100644 --- a/drivers/infiniband/hw/hns/hns_roce_mr.c +++ b/drivers/infiniband/hw/hns/hns_roce_mr.c @@ -120,7 +120,7 @@ static int alloc_mr_pbl(struct hns_roce_dev *hr_dev, struct hns_roce_mr *mr, mr->pbl_hop_num = is_fast ? 1 : hr_dev->caps.pbl_hop_num; buf_attr.page_shift = is_fast ? PAGE_SHIFT : - hr_dev->caps.pbl_buf_pg_sz + HNS_HW_PAGE_SHIFT; + hr_dev->caps.pbl_buf_pg_sz + PAGE_SHIFT; buf_attr.region[0].size = length; buf_attr.region[0].hopnum = mr->pbl_hop_num; buf_attr.region_count = 1; diff --git a/drivers/infiniband/hw/mlx5/odp.c b/drivers/infiniband/hw/mlx5/odp.c index 7d2ec9ee5097..1ab676b66894 100644 --- a/drivers/infiniband/hw/mlx5/odp.c +++ b/drivers/infiniband/hw/mlx5/odp.c @@ -601,6 +601,23 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr) */ synchronize_srcu(&dev->odp_srcu); + /* + * All work on the prefetch list must be completed, xa_erase() prevented + * new work from being created. + */ + wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work)); + + /* + * At this point it is forbidden for any other thread to enter + * pagefault_mr() on this imr. It is already forbidden to call + * pagefault_mr() on an implicit child. Due to this additions to + * implicit_children are prevented. + */ + + /* + * Block destroy_unused_implicit_child_mr() from incrementing + * num_deferred_work. + */ xa_lock(&imr->implicit_children); xa_for_each (&imr->implicit_children, idx, mtt) { __xa_erase(&imr->implicit_children, idx); @@ -609,9 +626,8 @@ void mlx5_ib_free_implicit_mr(struct mlx5_ib_mr *imr) xa_unlock(&imr->implicit_children); /* - * num_deferred_work can only be incremented inside the odp_srcu, or - * under xa_lock while the child is in the xarray. Thus at this point - * it is only decreasing, and all work holding it is now on the wq. + * Wait for any concurrent destroy_unused_implicit_child_mr() to + * complete. */ wait_event(imr->q_deferred_work, !atomic_read(&imr->num_deferred_work)); diff --git a/drivers/infiniband/hw/mlx5/srq_cmd.c b/drivers/infiniband/hw/mlx5/srq_cmd.c index 6f5eadc4d183..37aaacebd3f2 100644 --- a/drivers/infiniband/hw/mlx5/srq_cmd.c +++ b/drivers/infiniband/hw/mlx5/srq_cmd.c @@ -83,11 +83,11 @@ struct mlx5_core_srq *mlx5_cmd_get_srq(struct mlx5_ib_dev *dev, u32 srqn) struct mlx5_srq_table *table = &dev->srq_table; struct mlx5_core_srq *srq; - xa_lock(&table->array); + xa_lock_irq(&table->array); srq = xa_load(&table->array, srqn); if (srq) refcount_inc(&srq->common.refcount); - xa_unlock(&table->array); + xa_unlock_irq(&table->array); return srq; } diff --git a/drivers/iommu/qcom_iommu.c b/drivers/iommu/qcom_iommu.c index c3e1fbd1988c..d176df569af8 100644 --- a/drivers/iommu/qcom_iommu.c +++ b/drivers/iommu/qcom_iommu.c @@ -65,6 +65,7 @@ struct qcom_iommu_domain { struct mutex init_mutex; /* Protects iommu pointer */ struct iommu_domain domain; struct qcom_iommu_dev *iommu; + struct iommu_fwspec *fwspec; }; static struct qcom_iommu_domain *to_qcom_iommu_domain(struct iommu_domain *dom) @@ -84,9 +85,9 @@ static struct qcom_iommu_dev * to_iommu(struct device *dev) return dev_iommu_priv_get(dev); } -static struct qcom_iommu_ctx * to_ctx(struct device *dev, unsigned asid) +static struct qcom_iommu_ctx * to_ctx(struct qcom_iommu_domain *d, unsigned asid) { - struct qcom_iommu_dev *qcom_iommu = to_iommu(dev); + struct qcom_iommu_dev *qcom_iommu = d->iommu; if (!qcom_iommu) return NULL; return qcom_iommu->ctxs[asid - 1]; @@ -118,14 +119,12 @@ iommu_readq(struct qcom_iommu_ctx *ctx, unsigned reg) static void qcom_iommu_tlb_sync(void *cookie) { - struct iommu_fwspec *fwspec; - struct device *dev = cookie; + struct qcom_iommu_domain *qcom_domain = cookie; + struct iommu_fwspec *fwspec = qcom_domain->fwspec; unsigned i; - fwspec = dev_iommu_fwspec_get(dev); - for (i = 0; i < fwspec->num_ids; i++) { - struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]); + struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); unsigned int val, ret; iommu_writel(ctx, ARM_SMMU_CB_TLBSYNC, 0); @@ -139,14 +138,12 @@ static void qcom_iommu_tlb_sync(void *cookie) static void qcom_iommu_tlb_inv_context(void *cookie) { - struct device *dev = cookie; - struct iommu_fwspec *fwspec; + struct qcom_iommu_domain *qcom_domain = cookie; + struct iommu_fwspec *fwspec = qcom_domain->fwspec; unsigned i; - fwspec = dev_iommu_fwspec_get(dev); - for (i = 0; i < fwspec->num_ids; i++) { - struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]); + struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); iommu_writel(ctx, ARM_SMMU_CB_S1_TLBIASID, ctx->asid); } @@ -156,16 +153,14 @@ static void qcom_iommu_tlb_inv_context(void *cookie) static void qcom_iommu_tlb_inv_range_nosync(unsigned long iova, size_t size, size_t granule, bool leaf, void *cookie) { - struct device *dev = cookie; - struct iommu_fwspec *fwspec; + struct qcom_iommu_domain *qcom_domain = cookie; + struct iommu_fwspec *fwspec = qcom_domain->fwspec; unsigned i, reg; reg = leaf ? ARM_SMMU_CB_S1_TLBIVAL : ARM_SMMU_CB_S1_TLBIVA; - fwspec = dev_iommu_fwspec_get(dev); - for (i = 0; i < fwspec->num_ids; i++) { - struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]); + struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); size_t s = size; iova = (iova >> 12) << 12; @@ -256,7 +251,9 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, }; qcom_domain->iommu = qcom_iommu; - pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, dev); + qcom_domain->fwspec = fwspec; + + pgtbl_ops = alloc_io_pgtable_ops(ARM_32_LPAE_S1, &pgtbl_cfg, qcom_domain); if (!pgtbl_ops) { dev_err(qcom_iommu->dev, "failed to allocate pagetable ops\n"); ret = -ENOMEM; @@ -269,7 +266,7 @@ static int qcom_iommu_init_domain(struct iommu_domain *domain, domain->geometry.force_aperture = true; for (i = 0; i < fwspec->num_ids; i++) { - struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]); + struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); if (!ctx->secure_init) { ret = qcom_scm_restore_sec_cfg(qcom_iommu->sec_id, ctx->asid); @@ -419,7 +416,7 @@ static void qcom_iommu_detach_dev(struct iommu_domain *domain, struct device *de pm_runtime_get_sync(qcom_iommu->dev); for (i = 0; i < fwspec->num_ids; i++) { - struct qcom_iommu_ctx *ctx = to_ctx(dev, fwspec->ids[i]); + struct qcom_iommu_ctx *ctx = to_ctx(qcom_domain, fwspec->ids[i]); /* Disable the context bank: */ iommu_writel(ctx, ARM_SMMU_CB_SCTLR, 0); diff --git a/drivers/md/dm-integrity.c b/drivers/md/dm-integrity.c index 81dc5ff08909..a83a1de1e03f 100644 --- a/drivers/md/dm-integrity.c +++ b/drivers/md/dm-integrity.c @@ -2420,7 +2420,7 @@ static void integrity_writer(struct work_struct *w) unsigned prev_free_sectors; /* the following test is not needed, but it tests the replay code */ - if (unlikely(dm_suspended(ic->ti)) && !ic->meta_dev) + if (unlikely(dm_post_suspending(ic->ti)) && !ic->meta_dev) return; spin_lock_irq(&ic->endio_wait.lock); @@ -2481,7 +2481,7 @@ static void integrity_recalc(struct work_struct *w) next_chunk: - if (unlikely(dm_suspended(ic->ti))) + if (unlikely(dm_post_suspending(ic->ti))) goto unlock_ret; range.logical_sector = le64_to_cpu(ic->sb->recalc_sector); diff --git a/drivers/md/dm.c b/drivers/md/dm.c index 52449afd58eb..5b9de2f71bb0 100644 --- a/drivers/md/dm.c +++ b/drivers/md/dm.c @@ -143,6 +143,7 @@ EXPORT_SYMBOL_GPL(dm_bio_get_target_bio_nr); #define DMF_NOFLUSH_SUSPENDING 5 #define DMF_DEFERRED_REMOVE 6 #define DMF_SUSPENDED_INTERNALLY 7 +#define DMF_POST_SUSPENDING 8 #define DM_NUMA_NODE NUMA_NO_NODE static int dm_numa_node = DM_NUMA_NODE; @@ -2408,6 +2409,7 @@ static void __dm_destroy(struct mapped_device *md, bool wait) if (!dm_suspended_md(md)) { dm_table_presuspend_targets(map); set_bit(DMF_SUSPENDED, &md->flags); + set_bit(DMF_POST_SUSPENDING, &md->flags); dm_table_postsuspend_targets(map); } /* dm_put_live_table must be before msleep, otherwise deadlock is possible */ @@ -2766,7 +2768,9 @@ retry: if (r) goto out_unlock; + set_bit(DMF_POST_SUSPENDING, &md->flags); dm_table_postsuspend_targets(map); + clear_bit(DMF_POST_SUSPENDING, &md->flags); out_unlock: mutex_unlock(&md->suspend_lock); @@ -2863,7 +2867,9 @@ static void __dm_internal_suspend(struct mapped_device *md, unsigned suspend_fla (void) __dm_suspend(md, map, suspend_flags, TASK_UNINTERRUPTIBLE, DMF_SUSPENDED_INTERNALLY); + set_bit(DMF_POST_SUSPENDING, &md->flags); dm_table_postsuspend_targets(map); + clear_bit(DMF_POST_SUSPENDING, &md->flags); } static void __dm_internal_resume(struct mapped_device *md) @@ -3024,6 +3030,11 @@ int dm_suspended_md(struct mapped_device *md) return test_bit(DMF_SUSPENDED, &md->flags); } +static int dm_post_suspending_md(struct mapped_device *md) +{ + return test_bit(DMF_POST_SUSPENDING, &md->flags); +} + int dm_suspended_internally_md(struct mapped_device *md) { return test_bit(DMF_SUSPENDED_INTERNALLY, &md->flags); @@ -3040,6 +3051,12 @@ int dm_suspended(struct dm_target *ti) } EXPORT_SYMBOL_GPL(dm_suspended); +int dm_post_suspending(struct dm_target *ti) +{ + return dm_post_suspending_md(dm_table_get_md(ti->table)); +} +EXPORT_SYMBOL_GPL(dm_post_suspending); + int dm_noflush_suspending(struct dm_target *ti) { return __noflush_suspending(dm_table_get_md(ti->table)); diff --git a/drivers/mmc/host/sdhci-of-aspeed.c b/drivers/mmc/host/sdhci-of-aspeed.c index 56912e30c47e..a1bcc0f4ba9e 100644 --- a/drivers/mmc/host/sdhci-of-aspeed.c +++ b/drivers/mmc/host/sdhci-of-aspeed.c @@ -68,7 +68,7 @@ static void aspeed_sdhci_set_clock(struct sdhci_host *host, unsigned int clock) if (WARN_ON(clock > host->max_clk)) clock = host->max_clk; - for (div = 1; div < 256; div *= 2) { + for (div = 2; div < 256; div *= 2) { if ((parent / div) <= clock) break; } diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index 004919aea5fb..f88cb097b022 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -5053,15 +5053,19 @@ int bond_create(struct net *net, const char *name) bond_dev->rtnl_link_ops = &bond_link_ops; res = register_netdevice(bond_dev); + if (res < 0) { + free_netdev(bond_dev); + rtnl_unlock(); + + return res; + } netif_carrier_off(bond_dev); bond_work_init_all(bond); rtnl_unlock(); - if (res < 0) - free_netdev(bond_dev); - return res; + return 0; } static int __net_init bond_net_init(struct net *net) diff --git a/drivers/net/bonding/bond_netlink.c b/drivers/net/bonding/bond_netlink.c index b43b51646b11..f0f9138e967f 100644 --- a/drivers/net/bonding/bond_netlink.c +++ b/drivers/net/bonding/bond_netlink.c @@ -456,11 +456,10 @@ static int bond_newlink(struct net *src_net, struct net_device *bond_dev, return err; err = register_netdevice(bond_dev); - - netif_carrier_off(bond_dev); if (!err) { struct bonding *bond = netdev_priv(bond_dev); + netif_carrier_off(bond_dev); bond_work_init_all(bond); } diff --git a/drivers/net/dsa/microchip/ksz9477.c b/drivers/net/dsa/microchip/ksz9477.c index 8d15c3016024..4a9239b2c2e4 100644 --- a/drivers/net/dsa/microchip/ksz9477.c +++ b/drivers/net/dsa/microchip/ksz9477.c @@ -974,23 +974,6 @@ static void ksz9477_port_mirror_del(struct dsa_switch *ds, int port, PORT_MIRROR_SNIFFER, false); } -static void ksz9477_phy_setup(struct ksz_device *dev, int port, - struct phy_device *phy) -{ - /* Only apply to port with PHY. */ - if (port >= dev->phy_port_cnt) - return; - - /* The MAC actually cannot run in 1000 half-duplex mode. */ - phy_remove_link_mode(phy, - ETHTOOL_LINK_MODE_1000baseT_Half_BIT); - - /* PHY does not support gigabit. */ - if (!(dev->features & GBIT_SUPPORT)) - phy_remove_link_mode(phy, - ETHTOOL_LINK_MODE_1000baseT_Full_BIT); -} - static bool ksz9477_get_gbit(struct ksz_device *dev, u8 data) { bool gbit; @@ -1603,7 +1586,6 @@ static const struct ksz_dev_ops ksz9477_dev_ops = { .get_port_addr = ksz9477_get_port_addr, .cfg_port_member = ksz9477_cfg_port_member, .flush_dyn_mac_table = ksz9477_flush_dyn_mac_table, - .phy_setup = ksz9477_phy_setup, .port_setup = ksz9477_port_setup, .r_mib_cnt = ksz9477_r_mib_cnt, .r_mib_pkt = ksz9477_r_mib_pkt, @@ -1617,7 +1599,29 @@ static const struct ksz_dev_ops ksz9477_dev_ops = { int ksz9477_switch_register(struct ksz_device *dev) { - return ksz_switch_register(dev, &ksz9477_dev_ops); + int ret, i; + struct phy_device *phydev; + + ret = ksz_switch_register(dev, &ksz9477_dev_ops); + if (ret) + return ret; + + for (i = 0; i < dev->phy_port_cnt; ++i) { + if (!dsa_is_user_port(dev->ds, i)) + continue; + + phydev = dsa_to_port(dev->ds, i)->slave->phydev; + + /* The MAC actually cannot run in 1000 half-duplex mode. */ + phy_remove_link_mode(phydev, + ETHTOOL_LINK_MODE_1000baseT_Half_BIT); + + /* PHY does not support gigabit. */ + if (!(dev->features & GBIT_SUPPORT)) + phy_remove_link_mode(phydev, + ETHTOOL_LINK_MODE_1000baseT_Full_BIT); + } + return ret; } EXPORT_SYMBOL(ksz9477_switch_register); diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c index fd1d6676ae4f..7b6c0dce7536 100644 --- a/drivers/net/dsa/microchip/ksz_common.c +++ b/drivers/net/dsa/microchip/ksz_common.c @@ -358,8 +358,6 @@ int ksz_enable_port(struct dsa_switch *ds, int port, struct phy_device *phy) /* setup slave port */ dev->dev_ops->port_setup(dev, port, false); - if (dev->dev_ops->phy_setup) - dev->dev_ops->phy_setup(dev, port, phy); /* port_stp_state_set() will be called after to enable the port so * there is no need to do anything. diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h index f2c9bb68fd33..7d11dd32ec0d 100644 --- a/drivers/net/dsa/microchip/ksz_common.h +++ b/drivers/net/dsa/microchip/ksz_common.h @@ -119,8 +119,6 @@ struct ksz_dev_ops { u32 (*get_port_addr)(int port, int offset); void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member); void (*flush_dyn_mac_table)(struct ksz_device *dev, int port); - void (*phy_setup)(struct ksz_device *dev, int port, - struct phy_device *phy); void (*port_cleanup)(struct ksz_device *dev, int port); void (*port_setup)(struct ksz_device *dev, int port, bool cpu_port); void (*r_phy)(struct ksz_device *dev, u16 phy, u16 reg, u16 *val); diff --git a/drivers/net/dsa/mv88e6xxx/chip.c b/drivers/net/dsa/mv88e6xxx/chip.c index 7627ea61e0ea..fee16c947c2e 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.c +++ b/drivers/net/dsa/mv88e6xxx/chip.c @@ -664,8 +664,11 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, const struct phylink_link_state *state) { struct mv88e6xxx_chip *chip = ds->priv; + struct mv88e6xxx_port *p; int err; + p = &chip->ports[port]; + /* FIXME: is this the correct test? If we're in fixed mode on an * internal port, why should we process this any different from * PHY mode? On the other hand, the port may be automedia between @@ -675,10 +678,14 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, return; mv88e6xxx_reg_lock(chip); - /* FIXME: should we force the link down here - but if we do, how - * do we restore the link force/unforce state? The driver layering - * gets in the way. + /* In inband mode, the link may come up at any time while the link + * is not forced down. Force the link down while we reconfigure the + * interface mode. */ + if (mode == MLO_AN_INBAND && p->interface != state->interface && + chip->info->ops->port_set_link) + chip->info->ops->port_set_link(chip, port, LINK_FORCED_DOWN); + err = mv88e6xxx_port_config_interface(chip, port, state->interface); if (err && err != -EOPNOTSUPP) goto err_unlock; @@ -691,6 +698,15 @@ static void mv88e6xxx_mac_config(struct dsa_switch *ds, int port, if (err > 0) err = 0; + /* Undo the forced down state above after completing configuration + * irrespective of its state on entry, which allows the link to come up. + */ + if (mode == MLO_AN_INBAND && p->interface != state->interface && + chip->info->ops->port_set_link) + chip->info->ops->port_set_link(chip, port, LINK_UNFORCED); + + p->interface = state->interface; + err_unlock: mv88e6xxx_reg_unlock(chip); diff --git a/drivers/net/dsa/mv88e6xxx/chip.h b/drivers/net/dsa/mv88e6xxx/chip.h index e5430cf2ad71..6476524e8239 100644 --- a/drivers/net/dsa/mv88e6xxx/chip.h +++ b/drivers/net/dsa/mv88e6xxx/chip.h @@ -232,6 +232,7 @@ struct mv88e6xxx_port { u64 atu_full_violation; u64 vtu_member_violation; u64 vtu_miss_violation; + phy_interface_t interface; u8 cmode; bool mirror_ingress; bool mirror_egress; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h index ed5b465bc664..992fedbe4ce3 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_hw.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_hw.h @@ -64,6 +64,7 @@ struct aq_hw_caps_s { u8 rx_rings; bool flow_control; bool is_64_dma; + u32 quirks; u32 priv_data_len; }; diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c index 4435c6374f7e..7c7bf6bf163f 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.c @@ -415,6 +415,15 @@ int aq_nic_init(struct aq_nic_s *self) self->aq_nic_cfg.aq_hw_caps->media_type == AQ_HW_MEDIA_TYPE_TP) { self->aq_hw->phy_id = HW_ATL_PHY_ID_MAX; err = aq_phy_init(self->aq_hw); + + /* Disable the PTP on NICs where it's known to cause datapath + * problems. + * Ideally this should have been done by PHY provisioning, but + * many units have been shipped with enabled PTP block already. + */ + if (self->aq_nic_cfg.aq_hw_caps->quirks & AQ_NIC_QUIRK_BAD_PTP) + if (self->aq_hw->phy_id != HW_ATL_PHY_ID_MAX) + aq_phy_disable_ptp(self->aq_hw); } for (i = 0U; i < self->aq_vecs; i++) { diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h index 2ab003065e62..439ce9692dac 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_nic.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_nic.h @@ -81,6 +81,8 @@ struct aq_nic_cfg_s { #define AQ_NIC_FLAG_ERR_UNPLUG 0x40000000U #define AQ_NIC_FLAG_ERR_HW 0x80000000U +#define AQ_NIC_QUIRK_BAD_PTP BIT(0) + #define AQ_NIC_WOL_MODES (WAKE_MAGIC |\ WAKE_PHY) diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_phy.c b/drivers/net/ethernet/aquantia/atlantic/aq_phy.c index 51ae921e3e1f..949ac2351701 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_phy.c +++ b/drivers/net/ethernet/aquantia/atlantic/aq_phy.c @@ -1,10 +1,14 @@ // SPDX-License-Identifier: GPL-2.0-only -/* aQuantia Corporation Network Driver - * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved +/* Atlantic Network Driver + * + * Copyright (C) 2018-2019 aQuantia Corporation + * Copyright (C) 2019-2020 Marvell International Ltd. */ #include "aq_phy.h" +#define HW_ATL_PTP_DISABLE_MSK BIT(10) + bool aq_mdio_busy_wait(struct aq_hw_s *aq_hw) { int err = 0; @@ -145,3 +149,24 @@ bool aq_phy_init(struct aq_hw_s *aq_hw) return true; } + +void aq_phy_disable_ptp(struct aq_hw_s *aq_hw) +{ + static const u16 ptp_registers[] = { + 0x031e, + 0x031d, + 0x031c, + 0x031b, + }; + u16 val; + int i; + + for (i = 0; i < ARRAY_SIZE(ptp_registers); i++) { + val = aq_phy_read_reg(aq_hw, MDIO_MMD_VEND1, + ptp_registers[i]); + + aq_phy_write_reg(aq_hw, MDIO_MMD_VEND1, + ptp_registers[i], + val & ~HW_ATL_PTP_DISABLE_MSK); + } +} diff --git a/drivers/net/ethernet/aquantia/atlantic/aq_phy.h b/drivers/net/ethernet/aquantia/atlantic/aq_phy.h index 84b72ad04a4a..86cc1ee836e2 100644 --- a/drivers/net/ethernet/aquantia/atlantic/aq_phy.h +++ b/drivers/net/ethernet/aquantia/atlantic/aq_phy.h @@ -1,6 +1,8 @@ /* SPDX-License-Identifier: GPL-2.0-only */ -/* aQuantia Corporation Network Driver - * Copyright (C) 2018-2019 aQuantia Corporation. All rights reserved +/* Atlantic Network Driver + * + * Copyright (C) 2018-2019 aQuantia Corporation + * Copyright (C) 2019-2020 Marvell International Ltd. */ #ifndef AQ_PHY_H @@ -29,4 +31,6 @@ bool aq_phy_init_phy_id(struct aq_hw_s *aq_hw); bool aq_phy_init(struct aq_hw_s *aq_hw); +void aq_phy_disable_ptp(struct aq_hw_s *aq_hw); + #endif /* AQ_PHY_H */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c index 14d79f70cad7..2125bc20ab6a 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.c @@ -93,6 +93,25 @@ const struct aq_hw_caps_s hw_atl_b0_caps_aqc109 = { AQ_NIC_RATE_100M, }; +const struct aq_hw_caps_s hw_atl_b0_caps_aqc111 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = AQ_NIC_RATE_5G | + AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + .quirks = AQ_NIC_QUIRK_BAD_PTP, +}; + +const struct aq_hw_caps_s hw_atl_b0_caps_aqc112 = { + DEFAULT_B0_BOARD_BASIC_CAPABILITIES, + .media_type = AQ_HW_MEDIA_TYPE_TP, + .link_speed_msk = AQ_NIC_RATE_2G5 | + AQ_NIC_RATE_1G | + AQ_NIC_RATE_100M, + .quirks = AQ_NIC_QUIRK_BAD_PTP, +}; + static int hw_atl_b0_hw_reset(struct aq_hw_s *self) { int err = 0; @@ -354,8 +373,13 @@ static int hw_atl_b0_hw_init_tx_tc_rate_limit(struct aq_hw_s *self) /* WSP, if min_rate is set for at least one TC. * RR otherwise. + * + * NB! MAC FW sets arb mode itself if PTP is enabled. We shouldn't + * overwrite it here in that case. */ - hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U); + if (!nic_cfg->is_ptp) + hw_atl_tps_tx_pkt_shed_data_arb_mode_set(self, min_rate_msk ? 1U : 0U); + /* Data TC Arbiter takes precedence over Descriptor TC Arbiter, * leave Descriptor TC Arbiter as RR. */ diff --git a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h index 30f468f2084d..16091af17980 100644 --- a/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h +++ b/drivers/net/ethernet/aquantia/atlantic/hw_atl/hw_atl_b0.h @@ -18,17 +18,15 @@ extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc100; extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc107; extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc108; extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc109; - -#define hw_atl_b0_caps_aqc111 hw_atl_b0_caps_aqc108 -#define hw_atl_b0_caps_aqc112 hw_atl_b0_caps_aqc109 +extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc111; +extern const struct aq_hw_caps_s hw_atl_b0_caps_aqc112; #define hw_atl_b0_caps_aqc100s hw_atl_b0_caps_aqc100 #define hw_atl_b0_caps_aqc107s hw_atl_b0_caps_aqc107 #define hw_atl_b0_caps_aqc108s hw_atl_b0_caps_aqc108 #define hw_atl_b0_caps_aqc109s hw_atl_b0_caps_aqc109 - -#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc108 -#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc109 +#define hw_atl_b0_caps_aqc111s hw_atl_b0_caps_aqc111 +#define hw_atl_b0_caps_aqc112s hw_atl_b0_caps_aqc112 extern const struct aq_hw_ops hw_atl_ops_b0; diff --git a/drivers/net/ethernet/atheros/ag71xx.c b/drivers/net/ethernet/atheros/ag71xx.c index 112edbd30823..38cce66ef212 100644 --- a/drivers/net/ethernet/atheros/ag71xx.c +++ b/drivers/net/ethernet/atheros/ag71xx.c @@ -556,7 +556,8 @@ static int ag71xx_mdio_probe(struct ag71xx *ag) ag->mdio_reset = of_reset_control_get_exclusive(np, "mdio"); if (IS_ERR(ag->mdio_reset)) { netif_err(ag, probe, ndev, "Failed to get reset mdio.\n"); - return PTR_ERR(ag->mdio_reset); + err = PTR_ERR(ag->mdio_reset); + goto mdio_err_put_clk; } mii_bus->name = "ag71xx_mdio"; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt.c b/drivers/net/ethernet/broadcom/bnxt/bnxt.c index 6a884df44612..7463a1847ceb 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt.c @@ -3418,7 +3418,7 @@ void bnxt_set_tpa_flags(struct bnxt *bp) */ void bnxt_set_ring_params(struct bnxt *bp) { - u32 ring_size, rx_size, rx_space; + u32 ring_size, rx_size, rx_space, max_rx_cmpl; u32 agg_factor = 0, agg_ring_size = 0; /* 8 for CRC and VLAN */ @@ -3474,7 +3474,15 @@ void bnxt_set_ring_params(struct bnxt *bp) bp->tx_nr_pages = bnxt_calc_nr_ring_pages(ring_size, TX_DESC_CNT); bp->tx_ring_mask = (bp->tx_nr_pages * TX_DESC_CNT) - 1; - ring_size = bp->rx_ring_size * (2 + agg_factor) + bp->tx_ring_size; + max_rx_cmpl = bp->rx_ring_size; + /* MAX TPA needs to be added because TPA_START completions are + * immediately recycled, so the TPA completions are not bound by + * the RX ring size. + */ + if (bp->flags & BNXT_FLAG_TPA) + max_rx_cmpl += bp->max_tpa; + /* RX and TPA completions are 32-byte, all others are 16-byte */ + ring_size = max_rx_cmpl * 2 + agg_ring_size + bp->tx_ring_size; bp->cp_ring_size = ring_size; bp->cp_nr_pages = bnxt_calc_nr_ring_pages(ring_size, CP_DESC_CNT); @@ -10385,15 +10393,15 @@ static void bnxt_sp_task(struct work_struct *work) &bp->sp_event)) bnxt_hwrm_phy_qcaps(bp); - if (test_and_clear_bit(BNXT_LINK_CFG_CHANGE_SP_EVENT, - &bp->sp_event)) - bnxt_init_ethtool_link_settings(bp); - rc = bnxt_update_link(bp, true); - mutex_unlock(&bp->link_lock); if (rc) netdev_err(bp->dev, "SP task can't update link (rc: %x)\n", rc); + + if (test_and_clear_bit(BNXT_LINK_CFG_CHANGE_SP_EVENT, + &bp->sp_event)) + bnxt_init_ethtool_link_settings(bp); + mutex_unlock(&bp->link_lock); } if (test_and_clear_bit(BNXT_UPDATE_PHY_SP_EVENT, &bp->sp_event)) { int rc; diff --git a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c index 6b88143af5ea..b4aa56dc4f9f 100644 --- a/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c +++ b/drivers/net/ethernet/broadcom/bnxt/bnxt_ethtool.c @@ -1765,8 +1765,11 @@ static int bnxt_set_pauseparam(struct net_device *dev, if (epause->tx_pause) link_info->req_flow_ctrl |= BNXT_LINK_PAUSE_TX; - if (netif_running(dev)) + if (netif_running(dev)) { + mutex_lock(&bp->link_lock); rc = bnxt_hwrm_set_pause(bp); + mutex_unlock(&bp->link_lock); + } return rc; } diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index af924a8b885f..e471b14fc6e9 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -543,14 +543,14 @@ static int bcmgenet_hfb_validate_mask(void *mask, size_t size) #define VALIDATE_MASK(x) \ bcmgenet_hfb_validate_mask(&(x), sizeof(x)) -static int bcmgenet_hfb_insert_data(u32 *f, int offset, - void *val, void *mask, size_t size) +static int bcmgenet_hfb_insert_data(struct bcmgenet_priv *priv, u32 f_index, + u32 offset, void *val, void *mask, + size_t size) { - int index; - u32 tmp; + u32 index, tmp; - index = offset / 2; - tmp = f[index]; + index = f_index * priv->hw_params->hfb_filter_size + offset / 2; + tmp = bcmgenet_hfb_readl(priv, index * sizeof(u32)); while (size--) { if (offset++ & 1) { @@ -567,9 +567,10 @@ static int bcmgenet_hfb_insert_data(u32 *f, int offset, tmp |= 0x10000; break; } - f[index++] = tmp; + bcmgenet_hfb_writel(priv, tmp, index++ * sizeof(u32)); if (size) - tmp = f[index]; + tmp = bcmgenet_hfb_readl(priv, + index * sizeof(u32)); } else { tmp &= ~0xCFF00; tmp |= (*(unsigned char *)val++) << 8; @@ -585,44 +586,26 @@ static int bcmgenet_hfb_insert_data(u32 *f, int offset, break; } if (!size) - f[index] = tmp; + bcmgenet_hfb_writel(priv, tmp, index * sizeof(u32)); } } return 0; } -static void bcmgenet_hfb_set_filter(struct bcmgenet_priv *priv, u32 *f_data, - u32 f_length, u32 rx_queue, int f_index) -{ - u32 base = f_index * priv->hw_params->hfb_filter_size; - int i; - - for (i = 0; i < f_length; i++) - bcmgenet_hfb_writel(priv, f_data[i], (base + i) * sizeof(u32)); - - bcmgenet_hfb_set_filter_length(priv, f_index, 2 * f_length); - bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f_index, rx_queue); -} - -static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv, - struct bcmgenet_rxnfc_rule *rule) +static void bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv, + struct bcmgenet_rxnfc_rule *rule) { struct ethtool_rx_flow_spec *fs = &rule->fs; - int err = 0, offset = 0, f_length = 0; + u32 offset = 0, f_length = 0, f; u8 val_8, mask_8; __be16 val_16; u16 mask_16; size_t size; - u32 *f_data; - - f_data = kcalloc(priv->hw_params->hfb_filter_size, sizeof(u32), - GFP_KERNEL); - if (!f_data) - return -ENOMEM; + f = fs->location; if (fs->flow_type & FLOW_MAC_EXT) { - bcmgenet_hfb_insert_data(f_data, 0, + bcmgenet_hfb_insert_data(priv, f, 0, &fs->h_ext.h_dest, &fs->m_ext.h_dest, sizeof(fs->h_ext.h_dest)); } @@ -630,11 +613,11 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv, if (fs->flow_type & FLOW_EXT) { if (fs->m_ext.vlan_etype || fs->m_ext.vlan_tci) { - bcmgenet_hfb_insert_data(f_data, 12, + bcmgenet_hfb_insert_data(priv, f, 12, &fs->h_ext.vlan_etype, &fs->m_ext.vlan_etype, sizeof(fs->h_ext.vlan_etype)); - bcmgenet_hfb_insert_data(f_data, 14, + bcmgenet_hfb_insert_data(priv, f, 14, &fs->h_ext.vlan_tci, &fs->m_ext.vlan_tci, sizeof(fs->h_ext.vlan_tci)); @@ -646,15 +629,15 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv, switch (fs->flow_type & ~(FLOW_EXT | FLOW_MAC_EXT)) { case ETHER_FLOW: f_length += DIV_ROUND_UP(ETH_HLEN, 2); - bcmgenet_hfb_insert_data(f_data, 0, + bcmgenet_hfb_insert_data(priv, f, 0, &fs->h_u.ether_spec.h_dest, &fs->m_u.ether_spec.h_dest, sizeof(fs->h_u.ether_spec.h_dest)); - bcmgenet_hfb_insert_data(f_data, ETH_ALEN, + bcmgenet_hfb_insert_data(priv, f, ETH_ALEN, &fs->h_u.ether_spec.h_source, &fs->m_u.ether_spec.h_source, sizeof(fs->h_u.ether_spec.h_source)); - bcmgenet_hfb_insert_data(f_data, (2 * ETH_ALEN) + offset, + bcmgenet_hfb_insert_data(priv, f, (2 * ETH_ALEN) + offset, &fs->h_u.ether_spec.h_proto, &fs->m_u.ether_spec.h_proto, sizeof(fs->h_u.ether_spec.h_proto)); @@ -664,21 +647,21 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv, /* Specify IP Ether Type */ val_16 = htons(ETH_P_IP); mask_16 = 0xFFFF; - bcmgenet_hfb_insert_data(f_data, (2 * ETH_ALEN) + offset, + bcmgenet_hfb_insert_data(priv, f, (2 * ETH_ALEN) + offset, &val_16, &mask_16, sizeof(val_16)); - bcmgenet_hfb_insert_data(f_data, 15 + offset, + bcmgenet_hfb_insert_data(priv, f, 15 + offset, &fs->h_u.usr_ip4_spec.tos, &fs->m_u.usr_ip4_spec.tos, sizeof(fs->h_u.usr_ip4_spec.tos)); - bcmgenet_hfb_insert_data(f_data, 23 + offset, + bcmgenet_hfb_insert_data(priv, f, 23 + offset, &fs->h_u.usr_ip4_spec.proto, &fs->m_u.usr_ip4_spec.proto, sizeof(fs->h_u.usr_ip4_spec.proto)); - bcmgenet_hfb_insert_data(f_data, 26 + offset, + bcmgenet_hfb_insert_data(priv, f, 26 + offset, &fs->h_u.usr_ip4_spec.ip4src, &fs->m_u.usr_ip4_spec.ip4src, sizeof(fs->h_u.usr_ip4_spec.ip4src)); - bcmgenet_hfb_insert_data(f_data, 30 + offset, + bcmgenet_hfb_insert_data(priv, f, 30 + offset, &fs->h_u.usr_ip4_spec.ip4dst, &fs->m_u.usr_ip4_spec.ip4dst, sizeof(fs->h_u.usr_ip4_spec.ip4dst)); @@ -688,11 +671,11 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv, /* Only supports 20 byte IPv4 header */ val_8 = 0x45; mask_8 = 0xFF; - bcmgenet_hfb_insert_data(f_data, ETH_HLEN + offset, + bcmgenet_hfb_insert_data(priv, f, ETH_HLEN + offset, &val_8, &mask_8, sizeof(val_8)); size = sizeof(fs->h_u.usr_ip4_spec.l4_4_bytes); - bcmgenet_hfb_insert_data(f_data, + bcmgenet_hfb_insert_data(priv, f, ETH_HLEN + 20 + offset, &fs->h_u.usr_ip4_spec.l4_4_bytes, &fs->m_u.usr_ip4_spec.l4_4_bytes, @@ -701,34 +684,42 @@ static int bcmgenet_hfb_create_rxnfc_filter(struct bcmgenet_priv *priv, break; } + bcmgenet_hfb_set_filter_length(priv, f, 2 * f_length); if (!fs->ring_cookie || fs->ring_cookie == RX_CLS_FLOW_WAKE) { /* Ring 0 flows can be handled by the default Descriptor Ring * We'll map them to ring 0, but don't enable the filter */ - bcmgenet_hfb_set_filter(priv, f_data, f_length, 0, - fs->location); + bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f, 0); rule->state = BCMGENET_RXNFC_STATE_DISABLED; } else { /* Other Rx rings are direct mapped here */ - bcmgenet_hfb_set_filter(priv, f_data, f_length, - fs->ring_cookie, fs->location); - bcmgenet_hfb_enable_filter(priv, fs->location); + bcmgenet_hfb_set_filter_rx_queue_mapping(priv, f, + fs->ring_cookie); + bcmgenet_hfb_enable_filter(priv, f); rule->state = BCMGENET_RXNFC_STATE_ENABLED; } - - kfree(f_data); - - return err; } /* bcmgenet_hfb_clear * * Clear Hardware Filter Block and disable all filtering. */ +static void bcmgenet_hfb_clear_filter(struct bcmgenet_priv *priv, u32 f_index) +{ + u32 base, i; + + base = f_index * priv->hw_params->hfb_filter_size; + for (i = 0; i < priv->hw_params->hfb_filter_size; i++) + bcmgenet_hfb_writel(priv, 0x0, (base + i) * sizeof(u32)); +} + static void bcmgenet_hfb_clear(struct bcmgenet_priv *priv) { u32 i; + if (GENET_IS_V1(priv) || GENET_IS_V2(priv)) + return; + bcmgenet_hfb_reg_writel(priv, 0x0, HFB_CTRL); bcmgenet_hfb_reg_writel(priv, 0x0, HFB_FLT_ENABLE_V3PLUS); bcmgenet_hfb_reg_writel(priv, 0x0, HFB_FLT_ENABLE_V3PLUS + 4); @@ -740,19 +731,18 @@ static void bcmgenet_hfb_clear(struct bcmgenet_priv *priv) bcmgenet_hfb_reg_writel(priv, 0x0, HFB_FLT_LEN_V3PLUS + i * sizeof(u32)); - for (i = 0; i < priv->hw_params->hfb_filter_cnt * - priv->hw_params->hfb_filter_size; i++) - bcmgenet_hfb_writel(priv, 0x0, i * sizeof(u32)); + for (i = 0; i < priv->hw_params->hfb_filter_cnt; i++) + bcmgenet_hfb_clear_filter(priv, i); } static void bcmgenet_hfb_init(struct bcmgenet_priv *priv) { int i; + INIT_LIST_HEAD(&priv->rxnfc_list); if (GENET_IS_V1(priv) || GENET_IS_V2(priv)) return; - INIT_LIST_HEAD(&priv->rxnfc_list); for (i = 0; i < MAX_NUM_OF_FS_RULES; i++) { INIT_LIST_HEAD(&priv->rxnfc_rules[i].list); priv->rxnfc_rules[i].state = BCMGENET_RXNFC_STATE_UNUSED; @@ -1437,18 +1427,15 @@ static int bcmgenet_insert_flow(struct net_device *dev, loc_rule = &priv->rxnfc_rules[cmd->fs.location]; if (loc_rule->state == BCMGENET_RXNFC_STATE_ENABLED) bcmgenet_hfb_disable_filter(priv, cmd->fs.location); - if (loc_rule->state != BCMGENET_RXNFC_STATE_UNUSED) + if (loc_rule->state != BCMGENET_RXNFC_STATE_UNUSED) { list_del(&loc_rule->list); + bcmgenet_hfb_clear_filter(priv, cmd->fs.location); + } loc_rule->state = BCMGENET_RXNFC_STATE_UNUSED; memcpy(&loc_rule->fs, &cmd->fs, sizeof(struct ethtool_rx_flow_spec)); - err = bcmgenet_hfb_create_rxnfc_filter(priv, loc_rule); - if (err) { - netdev_err(dev, "rxnfc: Could not install rule (%d)\n", - err); - return err; - } + bcmgenet_hfb_create_rxnfc_filter(priv, loc_rule); list_add_tail(&loc_rule->list, &priv->rxnfc_list); @@ -1473,8 +1460,10 @@ static int bcmgenet_delete_flow(struct net_device *dev, if (rule->state == BCMGENET_RXNFC_STATE_ENABLED) bcmgenet_hfb_disable_filter(priv, cmd->fs.location); - if (rule->state != BCMGENET_RXNFC_STATE_UNUSED) + if (rule->state != BCMGENET_RXNFC_STATE_UNUSED) { list_del(&rule->list); + bcmgenet_hfb_clear_filter(priv, cmd->fs.location); + } rule->state = BCMGENET_RXNFC_STATE_UNUSED; memset(&rule->fs, 0, sizeof(struct ethtool_rx_flow_spec)); @@ -3999,7 +3988,7 @@ static int bcmgenet_probe(struct platform_device *pdev) if (err) err = dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(32)); if (err) - goto err; + goto err_clk_disable; /* Mii wait queue */ init_waitqueue_head(&priv->wq); @@ -4011,14 +4000,14 @@ static int bcmgenet_probe(struct platform_device *pdev) if (IS_ERR(priv->clk_wol)) { dev_dbg(&priv->pdev->dev, "failed to get enet-wol clock\n"); err = PTR_ERR(priv->clk_wol); - goto err; + goto err_clk_disable; } priv->clk_eee = devm_clk_get_optional(&priv->pdev->dev, "enet-eee"); if (IS_ERR(priv->clk_eee)) { dev_dbg(&priv->pdev->dev, "failed to get enet-eee clock\n"); err = PTR_ERR(priv->clk_eee); - goto err; + goto err_clk_disable; } /* If this is an internal GPHY, power it on now, before UniMAC is @@ -4129,8 +4118,9 @@ static int bcmgenet_resume(struct device *d) { struct net_device *dev = dev_get_drvdata(d); struct bcmgenet_priv *priv = netdev_priv(dev); + struct bcmgenet_rxnfc_rule *rule; unsigned long dma_ctrl; - u32 offset, reg; + u32 reg; int ret; if (!netif_running(dev)) @@ -4161,10 +4151,11 @@ static int bcmgenet_resume(struct device *d) bcmgenet_set_hw_addr(priv, dev->dev_addr); - offset = HFB_FLT_ENABLE_V3PLUS; - bcmgenet_hfb_reg_writel(priv, priv->hfb_en[1], offset); - bcmgenet_hfb_reg_writel(priv, priv->hfb_en[2], offset + sizeof(u32)); - bcmgenet_hfb_reg_writel(priv, priv->hfb_en[0], HFB_CTRL); + /* Restore hardware filters */ + bcmgenet_hfb_clear(priv); + list_for_each_entry(rule, &priv->rxnfc_list, list) + if (rule->state != BCMGENET_RXNFC_STATE_UNUSED) + bcmgenet_hfb_create_rxnfc_filter(priv, rule); if (priv->internal_phy) { reg = bcmgenet_ext_readl(priv, EXT_EXT_PWR_MGMT); @@ -4208,7 +4199,6 @@ static int bcmgenet_suspend(struct device *d) { struct net_device *dev = dev_get_drvdata(d); struct bcmgenet_priv *priv = netdev_priv(dev); - u32 offset; if (!netif_running(dev)) return 0; @@ -4220,11 +4210,7 @@ static int bcmgenet_suspend(struct device *d) if (!device_may_wakeup(d)) phy_suspend(dev->phydev); - /* Preserve filter state and disable filtering */ - priv->hfb_en[0] = bcmgenet_hfb_reg_readl(priv, HFB_CTRL); - offset = HFB_FLT_ENABLE_V3PLUS; - priv->hfb_en[1] = bcmgenet_hfb_reg_readl(priv, offset); - priv->hfb_en[2] = bcmgenet_hfb_reg_readl(priv, offset + sizeof(u32)); + /* Disable filtering */ bcmgenet_hfb_reg_writel(priv, 0, HFB_CTRL); return 0; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h index a12cb59298f4..f6ca01da141d 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h @@ -696,7 +696,6 @@ struct bcmgenet_priv { u32 wolopts; u8 sopass[SOPASS_MAX]; bool wol_active; - u32 hfb_en[3]; struct bcmgenet_mib_counters mib; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c index 4ea6a26b04f7..1c86eddb1b51 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet_wol.c @@ -217,20 +217,28 @@ void bcmgenet_wol_power_up_cfg(struct bcmgenet_priv *priv, priv->wol_active = 0; clk_disable_unprepare(priv->clk_wol); + priv->crc_fwd_en = 0; /* Disable Magic Packet Detection */ - reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL); - reg &= ~(MPD_EN | MPD_PW_EN); - bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL); + if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE)) { + reg = bcmgenet_umac_readl(priv, UMAC_MPD_CTRL); + if (!(reg & MPD_EN)) + return; /* already reset so skip the rest */ + reg &= ~(MPD_EN | MPD_PW_EN); + bcmgenet_umac_writel(priv, reg, UMAC_MPD_CTRL); + } /* Disable WAKE_FILTER Detection */ - reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL); - reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN); - bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL); + if (priv->wolopts & WAKE_FILTER) { + reg = bcmgenet_hfb_reg_readl(priv, HFB_CTRL); + if (!(reg & RBUF_ACPI_EN)) + return; /* already reset so skip the rest */ + reg &= ~(RBUF_HFB_EN | RBUF_ACPI_EN); + bcmgenet_hfb_reg_writel(priv, reg, HFB_CTRL); + } /* Disable CRC Forward */ reg = bcmgenet_umac_readl(priv, UMAC_CMD); reg &= ~CMD_CRC_FWD; bcmgenet_umac_writel(priv, reg, UMAC_CMD); - priv->crc_fwd_en = 0; } diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index f1f0976e7669..2213e6ab8151 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -3736,7 +3736,7 @@ static int macb_init(struct platform_device *pdev) if (!(bp->caps & MACB_CAPS_USRIO_DISABLED)) { val = 0; - if (bp->phy_interface == PHY_INTERFACE_MODE_RGMII) + if (phy_interface_mode_is_rgmii(bp->phy_interface)) val = GEM_BIT(RGMII); else if (bp->phy_interface == PHY_INTERFACE_MODE_RMII && (bp->caps & MACB_CAPS_USRIO_DEFAULT_IS_MII_GMII)) diff --git a/drivers/net/ethernet/chelsio/cxgb4/sge.c b/drivers/net/ethernet/chelsio/cxgb4/sge.c index 32a45dc51ed7..92eee66cbc84 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/sge.c +++ b/drivers/net/ethernet/chelsio/cxgb4/sge.c @@ -2938,6 +2938,7 @@ static inline int uld_send(struct adapter *adap, struct sk_buff *skb, txq_info = adap->sge.uld_txq_info[tx_uld_type]; if (unlikely(!txq_info)) { WARN_ON(true); + kfree_skb(skb); return NET_XMIT_DROP; } diff --git a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c index 2972244e6eb0..43570f4911ea 100644 --- a/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c +++ b/drivers/net/ethernet/freescale/dpaa/dpaa_eth.c @@ -2938,7 +2938,7 @@ static int dpaa_eth_probe(struct platform_device *pdev) DMA_BIT_MASK(40)); if (err) { netdev_err(net_dev, "dma_coerce_mask_and_coherent() failed\n"); - return err; + goto free_netdev; } /* If fsl_fm_max_frm is set to a higher value than the all-common 1500, diff --git a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c index f150cd454fa4..0998ceb1a26e 100644 --- a/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c +++ b/drivers/net/ethernet/freescale/dpaa2/dpaa2-eth.c @@ -3632,7 +3632,7 @@ static int dpaa2_eth_connect_mac(struct dpaa2_eth_priv *priv) dpni_dev = to_fsl_mc_device(priv->net_dev->dev.parent); dpmac_dev = fsl_mc_get_endpoint(dpni_dev); - if (IS_ERR(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type) + if (IS_ERR_OR_NULL(dpmac_dev) || dpmac_dev->dev.type != &fsl_mc_bus_dpmac_type) return 0; if (dpaa2_mac_is_type_fixed(dpmac_dev, priv->mc_io)) diff --git a/drivers/net/ethernet/freescale/enetc/enetc_pf.c b/drivers/net/ethernet/freescale/enetc/enetc_pf.c index 4fac57dbb3c8..7a9675bd36e8 100644 --- a/drivers/net/ethernet/freescale/enetc/enetc_pf.c +++ b/drivers/net/ethernet/freescale/enetc/enetc_pf.c @@ -906,6 +906,7 @@ static int enetc_pf_probe(struct pci_dev *pdev, return 0; err_reg_netdev: + enetc_mdio_remove(pf); enetc_of_put_phy(priv); enetc_free_msix(priv); err_alloc_msix: diff --git a/drivers/net/ethernet/freescale/fec.h b/drivers/net/ethernet/freescale/fec.h index d8d76da51c5e..832a2175636d 100644 --- a/drivers/net/ethernet/freescale/fec.h +++ b/drivers/net/ethernet/freescale/fec.h @@ -590,6 +590,7 @@ struct fec_enet_private { void fec_ptp_init(struct platform_device *pdev, int irq_idx); void fec_ptp_stop(struct platform_device *pdev); void fec_ptp_start_cyclecounter(struct net_device *ndev); +void fec_ptp_disable_hwts(struct net_device *ndev); int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr); int fec_ptp_get(struct net_device *ndev, struct ifreq *ifr); diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 3982285ed020..cc7fbfc09354 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -1294,8 +1294,13 @@ fec_enet_tx_queue(struct net_device *ndev, u16 queue_id) ndev->stats.tx_bytes += skb->len; } - if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS) && - fep->bufdesc_ex) { + /* NOTE: SKBTX_IN_PROGRESS being set does not imply it's we who + * are to time stamp the packet, so we still need to check time + * stamping enabled flag. + */ + if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS && + fep->hwts_tx_en) && + fep->bufdesc_ex) { struct skb_shared_hwtstamps shhwtstamps; struct bufdesc_ex *ebdp = (struct bufdesc_ex *)bdp; @@ -2723,10 +2728,16 @@ static int fec_enet_ioctl(struct net_device *ndev, struct ifreq *rq, int cmd) return -ENODEV; if (fep->bufdesc_ex) { - if (cmd == SIOCSHWTSTAMP) - return fec_ptp_set(ndev, rq); - if (cmd == SIOCGHWTSTAMP) - return fec_ptp_get(ndev, rq); + bool use_fec_hwts = !phy_has_hwtstamp(phydev); + + if (cmd == SIOCSHWTSTAMP) { + if (use_fec_hwts) + return fec_ptp_set(ndev, rq); + fec_ptp_disable_hwts(ndev); + } else if (cmd == SIOCGHWTSTAMP) { + if (use_fec_hwts) + return fec_ptp_get(ndev, rq); + } } return phy_mii_ioctl(phydev, rq, cmd); diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c index 945643c02615..f8a592c96beb 100644 --- a/drivers/net/ethernet/freescale/fec_ptp.c +++ b/drivers/net/ethernet/freescale/fec_ptp.c @@ -452,6 +452,18 @@ static int fec_ptp_enable(struct ptp_clock_info *ptp, return -EOPNOTSUPP; } +/** + * fec_ptp_disable_hwts - disable hardware time stamping + * @ndev: pointer to net_device + */ +void fec_ptp_disable_hwts(struct net_device *ndev) +{ + struct fec_enet_private *fep = netdev_priv(ndev); + + fep->hwts_tx_en = 0; + fep->hwts_rx_en = 0; +} + int fec_ptp_set(struct net_device *ndev, struct ifreq *ifr) { struct fec_enet_private *fep = netdev_priv(ndev); diff --git a/drivers/net/ethernet/freescale/gianfar.c b/drivers/net/ethernet/freescale/gianfar.c index b3c69e9038ea..b513b8c5c3b5 100644 --- a/drivers/net/ethernet/freescale/gianfar.c +++ b/drivers/net/ethernet/freescale/gianfar.c @@ -779,8 +779,12 @@ static int gfar_of_init(struct platform_device *ofdev, struct net_device **pdev) mac_addr = of_get_mac_address(np); - if (!IS_ERR(mac_addr)) + if (!IS_ERR(mac_addr)) { ether_addr_copy(dev->dev_addr, mac_addr); + } else { + eth_hw_addr_random(dev); + dev_info(&ofdev->dev, "Using random MAC address: %pM\n", dev->dev_addr); + } if (model && !strcasecmp(model, "TSEC")) priv->device_flags |= FSL_GIANFAR_DEV_HAS_GIGABIT | diff --git a/drivers/net/ethernet/hisilicon/hns3/hnae3.h b/drivers/net/ethernet/hisilicon/hns3/hnae3.h index d041cac9a487..088550db2de7 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hnae3.h +++ b/drivers/net/ethernet/hisilicon/hns3/hnae3.h @@ -77,6 +77,7 @@ ((ring)->p = ((ring)->p - 1 + (ring)->desc_num) % (ring)->desc_num) enum hns_desc_type { + DESC_TYPE_UNKNOWN, DESC_TYPE_SKB, DESC_TYPE_FRAGLIST_SKB, DESC_TYPE_PAGE, diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c index c38f3bbe7d97..33c481d11116 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.c @@ -1118,12 +1118,12 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, return -ENOMEM; } + desc_cb->priv = priv; desc_cb->length = size; + desc_cb->dma = dma; + desc_cb->type = type; if (likely(size <= HNS3_MAX_BD_SIZE)) { - desc_cb->priv = priv; - desc_cb->dma = dma; - desc_cb->type = type; desc->addr = cpu_to_le64(dma); desc->tx.send_size = cpu_to_le16(size); desc->tx.bdtp_fe_sc_vld_ra_ri = @@ -1135,18 +1135,11 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, } frag_buf_num = hns3_tx_bd_count(size); - sizeoflast = size & HNS3_TX_LAST_SIZE_M; + sizeoflast = size % HNS3_MAX_BD_SIZE; sizeoflast = sizeoflast ? sizeoflast : HNS3_MAX_BD_SIZE; /* When frag size is bigger than hardware limit, split this frag */ for (k = 0; k < frag_buf_num; k++) { - /* The txbd's baseinfo of DESC_TYPE_PAGE & DESC_TYPE_SKB */ - desc_cb->priv = priv; - desc_cb->dma = dma + HNS3_MAX_BD_SIZE * k; - desc_cb->type = ((type == DESC_TYPE_FRAGLIST_SKB || - type == DESC_TYPE_SKB) && !k) ? - type : DESC_TYPE_PAGE; - /* now, fill the descriptor */ desc->addr = cpu_to_le64(dma + HNS3_MAX_BD_SIZE * k); desc->tx.send_size = cpu_to_le16((k == frag_buf_num - 1) ? @@ -1158,7 +1151,6 @@ static int hns3_fill_desc(struct hns3_enet_ring *ring, void *priv, /* move ring pointer to next */ ring_ptr_move_fw(ring, next_to_use); - desc_cb = &ring->desc_cb[ring->next_to_use]; desc = &ring->desc[ring->next_to_use]; } @@ -1346,6 +1338,10 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig) unsigned int i; for (i = 0; i < ring->desc_num; i++) { + struct hns3_desc *desc = &ring->desc[ring->next_to_use]; + + memset(desc, 0, sizeof(*desc)); + /* check if this is where we started */ if (ring->next_to_use == next_to_use_orig) break; @@ -1353,6 +1349,9 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig) /* rollback one */ ring_ptr_move_bw(ring, next_to_use); + if (!ring->desc_cb[ring->next_to_use].dma) + continue; + /* unmap the descriptor dma address */ if (ring->desc_cb[ring->next_to_use].type == DESC_TYPE_SKB || ring->desc_cb[ring->next_to_use].type == @@ -1369,6 +1368,7 @@ static void hns3_clear_desc(struct hns3_enet_ring *ring, int next_to_use_orig) ring->desc_cb[ring->next_to_use].length = 0; ring->desc_cb[ring->next_to_use].dma = 0; + ring->desc_cb[ring->next_to_use].type = DESC_TYPE_UNKNOWN; } } diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h index 66cd4395f781..a8776620acbc 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3_enet.h @@ -165,8 +165,6 @@ enum hns3_nic_state { #define HNS3_TXD_MSS_S 0 #define HNS3_TXD_MSS_M (0x3fff << HNS3_TXD_MSS_S) -#define HNS3_TX_LAST_SIZE_M 0xffff - #define HNS3_VECTOR_TX_IRQ BIT_ULL(0) #define HNS3_VECTOR_RX_IRQ BIT_ULL(1) diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c index d6bfdc6520df..bb4a6327035d 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.c @@ -2673,11 +2673,10 @@ void hclge_task_schedule(struct hclge_dev *hdev, unsigned long delay_time) delay_time); } -static int hclge_get_mac_link_status(struct hclge_dev *hdev) +static int hclge_get_mac_link_status(struct hclge_dev *hdev, int *link_status) { struct hclge_link_status_cmd *req; struct hclge_desc desc; - int link_status; int ret; hclge_cmd_setup_basic_desc(&desc, HCLGE_OPC_QUERY_LINK_STATUS, true); @@ -2689,33 +2688,25 @@ static int hclge_get_mac_link_status(struct hclge_dev *hdev) } req = (struct hclge_link_status_cmd *)desc.data; - link_status = req->status & HCLGE_LINK_STATUS_UP_M; + *link_status = (req->status & HCLGE_LINK_STATUS_UP_M) > 0 ? + HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN; - return !!link_status; + return 0; } -static int hclge_get_mac_phy_link(struct hclge_dev *hdev) +static int hclge_get_mac_phy_link(struct hclge_dev *hdev, int *link_status) { - unsigned int mac_state; - int link_stat; + struct phy_device *phydev = hdev->hw.mac.phydev; + + *link_status = HCLGE_LINK_STATUS_DOWN; if (test_bit(HCLGE_STATE_DOWN, &hdev->state)) return 0; - mac_state = hclge_get_mac_link_status(hdev); - - if (hdev->hw.mac.phydev) { - if (hdev->hw.mac.phydev->state == PHY_RUNNING) - link_stat = mac_state & - hdev->hw.mac.phydev->link; - else - link_stat = 0; - - } else { - link_stat = mac_state; - } + if (phydev && (phydev->state != PHY_RUNNING || !phydev->link)) + return 0; - return !!link_stat; + return hclge_get_mac_link_status(hdev, link_status); } static void hclge_update_link_status(struct hclge_dev *hdev) @@ -2725,6 +2716,7 @@ static void hclge_update_link_status(struct hclge_dev *hdev) struct hnae3_handle *rhandle; struct hnae3_handle *handle; int state; + int ret; int i; if (!client) @@ -2733,7 +2725,12 @@ static void hclge_update_link_status(struct hclge_dev *hdev) if (test_and_set_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state)) return; - state = hclge_get_mac_phy_link(hdev); + ret = hclge_get_mac_phy_link(hdev, &state); + if (ret) { + clear_bit(HCLGE_STATE_LINK_UPDATING, &hdev->state); + return; + } + if (state != hdev->hw.mac.link) { for (i = 0; i < hdev->num_vmdq_vport + 1; i++) { handle = &hdev->vport[i].nic; @@ -6524,14 +6521,15 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret) { #define HCLGE_MAC_LINK_STATUS_NUM 100 + int link_status; int i = 0; int ret; do { - ret = hclge_get_mac_link_status(hdev); - if (ret < 0) + ret = hclge_get_mac_link_status(hdev, &link_status); + if (ret) return ret; - else if (ret == link_ret) + if (link_status == link_ret) return 0; msleep(HCLGE_LINK_STATUS_MS); @@ -6542,9 +6540,6 @@ static int hclge_mac_link_status_wait(struct hclge_dev *hdev, int link_ret) static int hclge_mac_phy_link_status_wait(struct hclge_dev *hdev, bool en, bool is_phy) { -#define HCLGE_LINK_STATUS_DOWN 0 -#define HCLGE_LINK_STATUS_UP 1 - int link_ret; link_ret = en ? HCLGE_LINK_STATUS_UP : HCLGE_LINK_STATUS_DOWN; diff --git a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h index 46e6e0fef3ba..9bbdd4557c27 100644 --- a/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h +++ b/drivers/net/ethernet/hisilicon/hns3/hns3pf/hclge_main.h @@ -317,6 +317,9 @@ enum hclge_link_fail_code { HCLGE_LF_XSFP_ABSENT, }; +#define HCLGE_LINK_STATUS_DOWN 0 +#define HCLGE_LINK_STATUS_UP 1 + #define HCLGE_PG_NUM 4 #define HCLGE_SCH_MODE_SP 0 #define HCLGE_SCH_MODE_DWRR 1 diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.c b/drivers/net/ethernet/mellanox/mlxsw/core.c index e9ccd333f61d..d6d6fe64887b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core.c @@ -710,7 +710,7 @@ static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) err = mlxsw_core_trap_register(mlxsw_core, &mlxsw_emad_rx_listener, mlxsw_core); if (err) - return err; + goto err_trap_register; err = mlxsw_core->driver->basic_trap_groups_set(mlxsw_core); if (err) @@ -722,6 +722,7 @@ static int mlxsw_emad_init(struct mlxsw_core *mlxsw_core) err_emad_trap_set: mlxsw_core_trap_unregister(mlxsw_core, &mlxsw_emad_rx_listener, mlxsw_core); +err_trap_register: destroy_workqueue(mlxsw_core->emad_wq); return err; } diff --git a/drivers/net/ethernet/mellanox/mlxsw/core_env.c b/drivers/net/ethernet/mellanox/mlxsw/core_env.c index 08215fed193d..a7d86df7123f 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core_env.c +++ b/drivers/net/ethernet/mellanox/mlxsw/core_env.c @@ -45,7 +45,7 @@ static int mlxsw_env_validate_cable_ident(struct mlxsw_core *core, int id, static int mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, u16 offset, u16 size, void *data, - unsigned int *p_read_size) + bool qsfp, unsigned int *p_read_size) { char eeprom_tmp[MLXSW_REG_MCIA_EEPROM_SIZE]; char mcia_pl[MLXSW_REG_MCIA_LEN]; @@ -54,6 +54,10 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, int status; int err; + /* MCIA register accepts buffer size <= 48. Page of size 128 should be + * read by chunks of size 48, 48, 32. Align the size of the last chunk + * to avoid reading after the end of the page. + */ size = min_t(u16, size, MLXSW_REG_MCIA_EEPROM_SIZE); if (offset < MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH && @@ -63,18 +67,25 @@ mlxsw_env_query_module_eeprom(struct mlxsw_core *mlxsw_core, int module, i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_LOW; if (offset >= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) { - page = MLXSW_REG_MCIA_PAGE_GET(offset); - offset -= MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH * page; - /* When reading upper pages 1, 2 and 3 the offset starts at - * 128. Please refer to "QSFP+ Memory Map" figure in SFF-8436 - * specification for graphical depiction. - * MCIA register accepts buffer size <= 48. Page of size 128 - * should be read by chunks of size 48, 48, 32. Align the size - * of the last chunk to avoid reading after the end of the - * page. - */ - if (offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) - size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset; + if (qsfp) { + /* When reading upper pages 1, 2 and 3 the offset + * starts at 128. Please refer to "QSFP+ Memory Map" + * figure in SFF-8436 specification for graphical + * depiction. + */ + page = MLXSW_REG_MCIA_PAGE_GET(offset); + offset -= MLXSW_REG_MCIA_EEPROM_UP_PAGE_LENGTH * page; + if (offset + size > MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH) + size = MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH - offset; + } else { + /* When reading upper pages 1, 2 and 3 the offset + * starts at 0 and I2C high address is used. Please refer + * refer to "Memory Organization" figure in SFF-8472 + * specification for graphical depiction. + */ + i2c_addr = MLXSW_REG_MCIA_I2C_ADDR_HIGH; + offset -= MLXSW_REG_MCIA_EEPROM_PAGE_LENGTH; + } } mlxsw_reg_mcia_pack(mcia_pl, module, 0, page, offset, size, i2c_addr); @@ -166,7 +177,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, int err; err = mlxsw_env_query_module_eeprom(mlxsw_core, module, 0, offset, - module_info, &read_size); + module_info, false, &read_size); if (err) return err; @@ -197,7 +208,7 @@ int mlxsw_env_get_module_info(struct mlxsw_core *mlxsw_core, int module, /* Verify if transceiver provides diagnostic monitoring page */ err = mlxsw_env_query_module_eeprom(mlxsw_core, module, SFP_DIAGMON, 1, &diag_mon, - &read_size); + false, &read_size); if (err) return err; @@ -225,17 +236,22 @@ int mlxsw_env_get_module_eeprom(struct net_device *netdev, int offset = ee->offset; unsigned int read_size; int i = 0; + bool qsfp; int err; if (!ee->len) return -EINVAL; memset(data, 0, ee->len); + /* Validate module identifier value. */ + err = mlxsw_env_validate_cable_ident(mlxsw_core, module, &qsfp); + if (err) + return err; while (i < ee->len) { err = mlxsw_env_query_module_eeprom(mlxsw_core, module, offset, ee->len - i, data + i, - &read_size); + qsfp, &read_size); if (err) { netdev_err(netdev, "Eeprom query failed\n"); return err; diff --git a/drivers/net/ethernet/neterion/vxge/vxge-main.c b/drivers/net/ethernet/neterion/vxge/vxge-main.c index 9b63574b6202..b5f1849fd280 100644 --- a/drivers/net/ethernet/neterion/vxge/vxge-main.c +++ b/drivers/net/ethernet/neterion/vxge/vxge-main.c @@ -98,7 +98,7 @@ static inline void VXGE_COMPLETE_VPATH_TX(struct vxge_fifo *fifo) { struct sk_buff **skb_ptr = NULL; struct sk_buff **temp; -#define NR_SKB_COMPLETED 128 +#define NR_SKB_COMPLETED 16 struct sk_buff *completed[NR_SKB_COMPLETED]; int more; diff --git a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c index e03ea9b18f95..095561924bdc 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_ethtool.c @@ -103,15 +103,18 @@ static void ionic_get_regs(struct net_device *netdev, struct ethtool_regs *regs, void *p) { struct ionic_lif *lif = netdev_priv(netdev); + unsigned int offset; unsigned int size; regs->version = IONIC_DEV_CMD_REG_VERSION; + offset = 0; size = IONIC_DEV_INFO_REG_COUNT * sizeof(u32); - memcpy_fromio(p, lif->ionic->idev.dev_info_regs->words, size); + memcpy_fromio(p + offset, lif->ionic->idev.dev_info_regs->words, size); + offset += size; size = IONIC_DEV_CMD_REG_COUNT * sizeof(u32); - memcpy_fromio(p, lif->ionic->idev.dev_cmd_regs->words, size); + memcpy_fromio(p + offset, lif->ionic->idev.dev_cmd_regs->words, size); } static int ionic_get_link_ksettings(struct net_device *netdev, diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.c b/drivers/net/ethernet/pensando/ionic/ionic_lif.c index f49486b6d04d..5fd31ba56937 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.c @@ -96,8 +96,7 @@ static void ionic_link_status_check(struct ionic_lif *lif) u16 link_status; bool link_up; - if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state) || - test_bit(IONIC_LIF_F_QUEUE_RESET, lif->state)) + if (!test_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state)) return; link_status = le16_to_cpu(lif->info->status.link_status); @@ -114,16 +113,22 @@ static void ionic_link_status_check(struct ionic_lif *lif) netif_carrier_on(netdev); } - if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) + if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) { + mutex_lock(&lif->queue_lock); ionic_start_queues(lif); + mutex_unlock(&lif->queue_lock); + } } else { if (netif_carrier_ok(netdev)) { netdev_info(netdev, "Link down\n"); netif_carrier_off(netdev); } - if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) + if (lif->netdev->flags & IFF_UP && netif_running(lif->netdev)) { + mutex_lock(&lif->queue_lock); ionic_stop_queues(lif); + mutex_unlock(&lif->queue_lock); + } } clear_bit(IONIC_LIF_F_LINK_CHECK_REQUESTED, lif->state); @@ -863,8 +868,7 @@ static int ionic_lif_addr_add(struct ionic_lif *lif, const u8 *addr) if (f) return 0; - netdev_dbg(lif->netdev, "rx_filter add ADDR %pM (id %d)\n", addr, - ctx.comp.rx_filter_add.filter_id); + netdev_dbg(lif->netdev, "rx_filter add ADDR %pM\n", addr); memcpy(ctx.cmd.rx_filter_add.mac.addr, addr, ETH_ALEN); err = ionic_adminq_post_wait(lif, &ctx); @@ -893,6 +897,9 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) return -ENOENT; } + netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", + addr, f->filter_id); + ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id); ionic_rx_filter_free(lif, f); spin_unlock_bh(&lif->rx_filters.lock); @@ -901,9 +908,6 @@ static int ionic_lif_addr_del(struct ionic_lif *lif, const u8 *addr) if (err && err != -EEXIST) return err; - netdev_dbg(lif->netdev, "rx_filter del ADDR %pM (id %d)\n", addr, - ctx.cmd.rx_filter_del.filter_id); - return 0; } @@ -1351,13 +1355,11 @@ static int ionic_vlan_rx_add_vid(struct net_device *netdev, __be16 proto, }; int err; + netdev_dbg(netdev, "rx_filter add VLAN %d\n", vid); err = ionic_adminq_post_wait(lif, &ctx); if (err) return err; - netdev_dbg(netdev, "rx_filter add VLAN %d (id %d)\n", vid, - ctx.comp.rx_filter_add.filter_id); - return ionic_rx_filter_save(lif, 0, IONIC_RXQ_INDEX_ANY, 0, &ctx); } @@ -1382,8 +1384,8 @@ static int ionic_vlan_rx_kill_vid(struct net_device *netdev, __be16 proto, return -ENOENT; } - netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n", vid, - le32_to_cpu(ctx.cmd.rx_filter_del.filter_id)); + netdev_dbg(netdev, "rx_filter del VLAN %d (id %d)\n", + vid, f->filter_id); ctx.cmd.rx_filter_del.filter_id = cpu_to_le32(f->filter_id); ionic_rx_filter_free(lif, f); @@ -1993,16 +1995,13 @@ int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg) bool running; int err = 0; - err = ionic_wait_for_bit(lif, IONIC_LIF_F_QUEUE_RESET); - if (err) - return err; - + mutex_lock(&lif->queue_lock); running = netif_running(lif->netdev); if (running) { netif_device_detach(lif->netdev); err = ionic_stop(lif->netdev); if (err) - goto reset_out; + return err; } if (cb) @@ -2012,9 +2011,7 @@ int ionic_reset_queues(struct ionic_lif *lif, ionic_reset_cb cb, void *arg) err = ionic_open(lif->netdev); netif_device_attach(lif->netdev); } - -reset_out: - clear_bit(IONIC_LIF_F_QUEUE_RESET, lif->state); + mutex_unlock(&lif->queue_lock); return err; } @@ -2161,7 +2158,9 @@ static void ionic_lif_handle_fw_down(struct ionic_lif *lif) if (test_bit(IONIC_LIF_F_UP, lif->state)) { dev_info(ionic->dev, "Surprise FW stop, stopping queues\n"); + mutex_lock(&lif->queue_lock); ionic_stop_queues(lif); + mutex_unlock(&lif->queue_lock); } if (netif_running(lif->netdev)) { @@ -2280,15 +2279,15 @@ static void ionic_lif_deinit(struct ionic_lif *lif) cancel_work_sync(&lif->deferred.work); cancel_work_sync(&lif->tx_timeout_work); ionic_rx_filters_deinit(lif); + if (lif->netdev->features & NETIF_F_RXHASH) + ionic_lif_rss_deinit(lif); } - if (lif->netdev->features & NETIF_F_RXHASH) - ionic_lif_rss_deinit(lif); - napi_disable(&lif->adminqcq->napi); ionic_lif_qcq_deinit(lif, lif->notifyqcq); ionic_lif_qcq_deinit(lif, lif->adminqcq); + mutex_destroy(&lif->queue_lock); ionic_lif_reset(lif); } @@ -2465,6 +2464,7 @@ static int ionic_lif_init(struct ionic_lif *lif) return err; lif->hw_index = le16_to_cpu(comp.hw_index); + mutex_init(&lif->queue_lock); /* now that we have the hw_index we can figure out our doorbell page */ lif->dbid_count = le32_to_cpu(lif->ionic->ident.dev.ndbpgs_per_lif); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_lif.h b/drivers/net/ethernet/pensando/ionic/ionic_lif.h index ed126dd74e01..8dc2c5d77424 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_lif.h +++ b/drivers/net/ethernet/pensando/ionic/ionic_lif.h @@ -135,7 +135,6 @@ enum ionic_lif_state_flags { IONIC_LIF_F_SW_DEBUG_STATS, IONIC_LIF_F_UP, IONIC_LIF_F_LINK_CHECK_REQUESTED, - IONIC_LIF_F_QUEUE_RESET, IONIC_LIF_F_FW_RESET, /* leave this as last */ @@ -165,6 +164,7 @@ struct ionic_lif { unsigned int hw_index; unsigned int kern_pid; u64 __iomem *kern_dbpage; + struct mutex queue_lock; /* lock for queue structures */ spinlock_t adminq_lock; /* lock for AdminQ operations */ struct ionic_qcq *adminqcq; struct ionic_qcq *notifyqcq; @@ -213,12 +213,6 @@ struct ionic_lif { #define lif_to_txq(lif, i) (&lif_to_txqcq((lif), i)->q) #define lif_to_rxq(lif, i) (&lif_to_txqcq((lif), i)->q) -/* return 0 if successfully set the bit, else non-zero */ -static inline int ionic_wait_for_bit(struct ionic_lif *lif, int bitname) -{ - return wait_on_bit_lock(lif->state, bitname, TASK_INTERRUPTIBLE); -} - static inline u32 ionic_coal_usec_to_hw(struct ionic *ionic, u32 usecs) { u32 mult = le32_to_cpu(ionic->ident.dev.intr_coal_mult); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c index 80eeb7696e01..cd0076fc3044 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_rx_filter.c @@ -21,13 +21,16 @@ void ionic_rx_filter_free(struct ionic_lif *lif, struct ionic_rx_filter *f) void ionic_rx_filter_replay(struct ionic_lif *lif) { struct ionic_rx_filter_add_cmd *ac; + struct hlist_head new_id_list; struct ionic_admin_ctx ctx; struct ionic_rx_filter *f; struct hlist_head *head; struct hlist_node *tmp; + unsigned int key; unsigned int i; int err; + INIT_HLIST_HEAD(&new_id_list); ac = &ctx.cmd.rx_filter_add; for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) { @@ -58,9 +61,30 @@ void ionic_rx_filter_replay(struct ionic_lif *lif) ac->mac.addr); break; } + spin_lock_bh(&lif->rx_filters.lock); + ionic_rx_filter_free(lif, f); + spin_unlock_bh(&lif->rx_filters.lock); + + continue; } + + /* remove from old id list, save new id in tmp list */ + spin_lock_bh(&lif->rx_filters.lock); + hlist_del(&f->by_id); + spin_unlock_bh(&lif->rx_filters.lock); + f->filter_id = le32_to_cpu(ctx.comp.rx_filter_add.filter_id); + hlist_add_head(&f->by_id, &new_id_list); } } + + /* rebuild the by_id hash lists with the new filter ids */ + spin_lock_bh(&lif->rx_filters.lock); + hlist_for_each_entry_safe(f, tmp, &new_id_list, by_id) { + key = f->filter_id & IONIC_RX_FILTER_HLISTS_MASK; + head = &lif->rx_filters.by_id[key]; + hlist_add_head(&f->by_id, head); + } + spin_unlock_bh(&lif->rx_filters.lock); } int ionic_rx_filters_init(struct ionic_lif *lif) @@ -69,10 +93,12 @@ int ionic_rx_filters_init(struct ionic_lif *lif) spin_lock_init(&lif->rx_filters.lock); + spin_lock_bh(&lif->rx_filters.lock); for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) { INIT_HLIST_HEAD(&lif->rx_filters.by_hash[i]); INIT_HLIST_HEAD(&lif->rx_filters.by_id[i]); } + spin_unlock_bh(&lif->rx_filters.lock); return 0; } @@ -84,11 +110,13 @@ void ionic_rx_filters_deinit(struct ionic_lif *lif) struct hlist_node *tmp; unsigned int i; + spin_lock_bh(&lif->rx_filters.lock); for (i = 0; i < IONIC_RX_FILTER_HLISTS; i++) { head = &lif->rx_filters.by_id[i]; hlist_for_each_entry_safe(f, tmp, head, by_id) ionic_rx_filter_free(lif, f); } + spin_unlock_bh(&lif->rx_filters.lock); } int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index, @@ -124,6 +152,7 @@ int ionic_rx_filter_save(struct ionic_lif *lif, u32 flow_id, u16 rxq_index, f->filter_id = le32_to_cpu(ctx->comp.rx_filter_add.filter_id); f->rxq_index = rxq_index; memcpy(&f->cmd, ac, sizeof(f->cmd)); + netdev_dbg(lif->netdev, "rx_filter add filter_id %d\n", f->filter_id); INIT_HLIST_NODE(&f->by_hash); INIT_HLIST_NODE(&f->by_id); diff --git a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c index b7f900c11834..85eb8f276a37 100644 --- a/drivers/net/ethernet/pensando/ionic/ionic_txrx.c +++ b/drivers/net/ethernet/pensando/ionic/ionic_txrx.c @@ -161,12 +161,6 @@ static void ionic_rx_clean(struct ionic_queue *q, return; } - /* no packet processing while resetting */ - if (unlikely(test_bit(IONIC_LIF_F_QUEUE_RESET, q->lif->state))) { - stats->dropped++; - return; - } - stats->pkts++; stats->bytes += le16_to_cpu(comp->len); diff --git a/drivers/net/ethernet/qlogic/qed/qed_cxt.c b/drivers/net/ethernet/qlogic/qed/qed_cxt.c index 08ba9d54ab63..d13ec88313c3 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_cxt.c +++ b/drivers/net/ethernet/qlogic/qed/qed_cxt.c @@ -2008,8 +2008,8 @@ static void qed_rdma_set_pf_params(struct qed_hwfn *p_hwfn, enum protocol_type proto; if (p_hwfn->mcp_info->func_info.protocol == QED_PCI_ETH_RDMA) { - DP_NOTICE(p_hwfn, - "Current day drivers don't support RoCE & iWARP simultaneously on the same PF. Default to RoCE-only\n"); + DP_VERBOSE(p_hwfn, QED_MSG_SP, + "Current day drivers don't support RoCE & iWARP simultaneously on the same PF. Default to RoCE-only\n"); p_hwfn->hw_info.personality = QED_PCI_ETH_ROCE; } diff --git a/drivers/net/ethernet/qlogic/qed/qed_dev.c b/drivers/net/ethernet/qlogic/qed/qed_dev.c index 9c26fde663b3..dbdac983ccde 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_dev.c +++ b/drivers/net/ethernet/qlogic/qed/qed_dev.c @@ -3102,7 +3102,7 @@ int qed_hw_init(struct qed_dev *cdev, struct qed_hw_init_params *p_params) } /* Log and clear previous pglue_b errors if such exist */ - qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt); + qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_main_ptt, true); /* Enable the PF's internal FID_enable in the PXP */ rc = qed_pglueb_set_pfid_enable(p_hwfn, p_hwfn->p_main_ptt, diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.c b/drivers/net/ethernet/qlogic/qed/qed_int.c index b7b974f0ef21..5eec1fc6229d 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.c +++ b/drivers/net/ethernet/qlogic/qed/qed_int.c @@ -257,9 +257,10 @@ out: #define PGLUE_ATTENTION_ZLR_VALID (1 << 25) #define PGLUE_ATTENTION_ILT_VALID (1 << 23) -int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt) +int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + bool hw_init) { + char msg[256]; u32 tmp; tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS2); @@ -273,22 +274,23 @@ int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, details = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS); - DP_NOTICE(p_hwfn, - "Illegal write by chip to [%08x:%08x] blocked.\n" - "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" - "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]\n", - addr_hi, addr_lo, details, - (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), - (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), - GET_FIELD(details, - PGLUE_ATTENTION_DETAILS_VF_VALID) ? 1 : 0, - tmp, - GET_FIELD(tmp, - PGLUE_ATTENTION_DETAILS2_WAS_ERR) ? 1 : 0, - GET_FIELD(tmp, - PGLUE_ATTENTION_DETAILS2_BME) ? 1 : 0, - GET_FIELD(tmp, - PGLUE_ATTENTION_DETAILS2_FID_EN) ? 1 : 0); + snprintf(msg, sizeof(msg), + "Illegal write by chip to [%08x:%08x] blocked.\n" + "Details: %08x [PFID %02x, VFID %02x, VF_VALID %02x]\n" + "Details2 %08x [Was_error %02x BME deassert %02x FID_enable deassert %02x]", + addr_hi, addr_lo, details, + (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_PFID), + (u8)GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VFID), + !!GET_FIELD(details, PGLUE_ATTENTION_DETAILS_VF_VALID), + tmp, + !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_WAS_ERR), + !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_BME), + !!GET_FIELD(tmp, PGLUE_ATTENTION_DETAILS2_FID_EN)); + + if (hw_init) + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "%s\n", msg); + else + DP_NOTICE(p_hwfn, "%s\n", msg); } tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_RD_DETAILS2); @@ -321,8 +323,14 @@ int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, } tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_TX_ERR_WR_DETAILS_ICPL); - if (tmp & PGLUE_ATTENTION_ICPL_VALID) - DP_NOTICE(p_hwfn, "ICPL error - %08x\n", tmp); + if (tmp & PGLUE_ATTENTION_ICPL_VALID) { + snprintf(msg, sizeof(msg), "ICPL error - %08x", tmp); + + if (hw_init) + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "%s\n", msg); + else + DP_NOTICE(p_hwfn, "%s\n", msg); + } tmp = qed_rd(p_hwfn, p_ptt, PGLUE_B_REG_MASTER_ZLR_ERR_DETAILS); if (tmp & PGLUE_ATTENTION_ZLR_VALID) { @@ -361,7 +369,7 @@ int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, static int qed_pglueb_rbc_attn_cb(struct qed_hwfn *p_hwfn) { - return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt); + return qed_pglueb_rbc_attn_handler(p_hwfn, p_hwfn->p_dpc_ptt, false); } static int qed_fw_assertion(struct qed_hwfn *p_hwfn) @@ -1193,7 +1201,8 @@ static int qed_int_attentions(struct qed_hwfn *p_hwfn) index, attn_bits, attn_acks, asserted_bits, deasserted_bits, p_sb_attn_sw->known_attn); } else if (asserted_bits == 0x100) { - DP_INFO(p_hwfn, "MFW indication via attention\n"); + DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, + "MFW indication via attention\n"); } else { DP_VERBOSE(p_hwfn, NETIF_MSG_INTR, "MFW indication [deassertion]\n"); diff --git a/drivers/net/ethernet/qlogic/qed/qed_int.h b/drivers/net/ethernet/qlogic/qed/qed_int.h index e09db3386367..110169e90121 100644 --- a/drivers/net/ethernet/qlogic/qed/qed_int.h +++ b/drivers/net/ethernet/qlogic/qed/qed_int.h @@ -442,7 +442,7 @@ int qed_int_set_timer_res(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, #define QED_MAPPING_MEMORY_SIZE(dev) (NUM_OF_SBS(dev)) -int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, - struct qed_ptt *p_ptt); +int qed_pglueb_rbc_attn_handler(struct qed_hwfn *p_hwfn, struct qed_ptt *p_ptt, + bool hw_init); #endif diff --git a/drivers/net/ethernet/renesas/ravb_main.c b/drivers/net/ethernet/renesas/ravb_main.c index a442bcf64b9c..99f7aae102ce 100644 --- a/drivers/net/ethernet/renesas/ravb_main.c +++ b/drivers/net/ethernet/renesas/ravb_main.c @@ -1450,6 +1450,7 @@ static void ravb_tx_timeout_work(struct work_struct *work) struct ravb_private *priv = container_of(work, struct ravb_private, work); struct net_device *ndev = priv->ndev; + int error; netif_tx_stop_all_queues(ndev); @@ -1458,15 +1459,36 @@ static void ravb_tx_timeout_work(struct work_struct *work) ravb_ptp_stop(ndev); /* Wait for DMA stopping */ - ravb_stop_dma(ndev); + if (ravb_stop_dma(ndev)) { + /* If ravb_stop_dma() fails, the hardware is still operating + * for TX and/or RX. So, this should not call the following + * functions because ravb_dmac_init() is possible to fail too. + * Also, this should not retry ravb_stop_dma() again and again + * here because it's possible to wait forever. So, this just + * re-enables the TX and RX and skip the following + * re-initialization procedure. + */ + ravb_rcv_snd_enable(ndev); + goto out; + } ravb_ring_free(ndev, RAVB_BE); ravb_ring_free(ndev, RAVB_NC); /* Device init */ - ravb_dmac_init(ndev); + error = ravb_dmac_init(ndev); + if (error) { + /* If ravb_dmac_init() fails, descriptors are freed. So, this + * should return here to avoid re-enabling the TX and RX in + * ravb_emac_init(). + */ + netdev_err(ndev, "%s: ravb_dmac_init() failed, error %d\n", + __func__, error); + return; + } ravb_emac_init(ndev); +out: /* Initialise PTP Clock driver */ if (priv->chip_id == RCAR_GEN2) ravb_ptp_init(ndev, priv->pdev); diff --git a/drivers/net/ethernet/smsc/smc91x.c b/drivers/net/ethernet/smsc/smc91x.c index 90410f9d3b1a..1c4fea9c3ec4 100644 --- a/drivers/net/ethernet/smsc/smc91x.c +++ b/drivers/net/ethernet/smsc/smc91x.c @@ -2274,7 +2274,7 @@ static int smc_drv_probe(struct platform_device *pdev) ret = try_toggle_control_gpio(&pdev->dev, &lp->power_gpio, "power", 0, 0, 100); if (ret) - return ret; + goto out_free_netdev; /* * Optional reset GPIO configured? Minimum 100 ns reset needed @@ -2283,7 +2283,7 @@ static int smc_drv_probe(struct platform_device *pdev) ret = try_toggle_control_gpio(&pdev->dev, &lp->reset_gpio, "reset", 0, 0, 100); if (ret) - return ret; + goto out_free_netdev; /* * Need to wait for optional EEPROM to load, max 750 us according diff --git a/drivers/net/ethernet/socionext/sni_ave.c b/drivers/net/ethernet/socionext/sni_ave.c index f2638446b62e..81b554dd7221 100644 --- a/drivers/net/ethernet/socionext/sni_ave.c +++ b/drivers/net/ethernet/socionext/sni_ave.c @@ -1191,7 +1191,7 @@ static int ave_init(struct net_device *ndev) ret = regmap_update_bits(priv->regmap, SG_ETPINMODE, priv->pinmode_mask, priv->pinmode_val); if (ret) - return ret; + goto out_reset_assert; ave_global_reset(ndev); diff --git a/drivers/net/ethernet/ti/am65-cpsw-nuss.c b/drivers/net/ethernet/ti/am65-cpsw-nuss.c index 1492648247d9..6d778bc3d012 100644 --- a/drivers/net/ethernet/ti/am65-cpsw-nuss.c +++ b/drivers/net/ethernet/ti/am65-cpsw-nuss.c @@ -1850,7 +1850,8 @@ static int am65_cpsw_nuss_init_ndev_2g(struct am65_cpsw_common *common) port->ndev->max_mtu = AM65_CPSW_MAX_PACKET_SIZE; port->ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | - NETIF_F_HW_CSUM; + NETIF_F_HW_CSUM | + NETIF_F_HW_TC; port->ndev->features = port->ndev->hw_features | NETIF_F_HW_VLAN_CTAG_FILTER; port->ndev->vlan_features |= NETIF_F_SG; diff --git a/drivers/net/geneve.c b/drivers/net/geneve.c index 4661ef865807..dec52b763d50 100644 --- a/drivers/net/geneve.c +++ b/drivers/net/geneve.c @@ -1615,11 +1615,11 @@ static int geneve_changelink(struct net_device *dev, struct nlattr *tb[], struct netlink_ext_ack *extack) { struct geneve_dev *geneve = netdev_priv(dev); + enum ifla_geneve_df df = geneve->df; struct geneve_sock *gs4, *gs6; struct ip_tunnel_info info; bool metadata; bool use_udp6_rx_checksums; - enum ifla_geneve_df df; bool ttl_inherit; int err; diff --git a/drivers/net/hippi/rrunner.c b/drivers/net/hippi/rrunner.c index 2a6ec5394966..a4b3fce69ecd 100644 --- a/drivers/net/hippi/rrunner.c +++ b/drivers/net/hippi/rrunner.c @@ -1242,7 +1242,7 @@ static int rr_open(struct net_device *dev) rrpriv->info = NULL; } if (rrpriv->rx_ctrl) { - pci_free_consistent(pdev, sizeof(struct ring_ctrl), + pci_free_consistent(pdev, 256 * sizeof(struct ring_ctrl), rrpriv->rx_ctrl, rrpriv->rx_ctrl_dma); rrpriv->rx_ctrl = NULL; } diff --git a/drivers/net/ieee802154/adf7242.c b/drivers/net/ieee802154/adf7242.c index 5a37514e4234..c11f32f644db 100644 --- a/drivers/net/ieee802154/adf7242.c +++ b/drivers/net/ieee802154/adf7242.c @@ -4,7 +4,7 @@ * * Copyright 2009-2017 Analog Devices Inc. * - * http://www.analog.com/ADF7242 + * https://www.analog.com/ADF7242 */ #include <linux/kernel.h> @@ -1262,7 +1262,7 @@ static int adf7242_probe(struct spi_device *spi) WQ_MEM_RECLAIM); if (unlikely(!lp->wqueue)) { ret = -ENOMEM; - goto err_hw_init; + goto err_alloc_wq; } ret = adf7242_hw_init(lp); @@ -1294,6 +1294,8 @@ static int adf7242_probe(struct spi_device *spi) return ret; err_hw_init: + destroy_workqueue(lp->wqueue); +err_alloc_wq: mutex_destroy(&lp->bmux); ieee802154_free_hw(lp->hw); diff --git a/drivers/net/netdevsim/netdev.c b/drivers/net/netdevsim/netdev.c index 2908e0a0d6e1..23950e7a0f81 100644 --- a/drivers/net/netdevsim/netdev.c +++ b/drivers/net/netdevsim/netdev.c @@ -302,7 +302,7 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) rtnl_lock(); err = nsim_bpf_init(ns); if (err) - goto err_free_netdev; + goto err_rtnl_unlock; nsim_ipsec_init(ns); @@ -316,8 +316,8 @@ nsim_create(struct nsim_dev *nsim_dev, struct nsim_dev_port *nsim_dev_port) err_ipsec_teardown: nsim_ipsec_teardown(ns); nsim_bpf_uninit(ns); +err_rtnl_unlock: rtnl_unlock(); -err_free_netdev: free_netdev(dev); return ERR_PTR(err); } diff --git a/drivers/net/phy/dp83640.c b/drivers/net/phy/dp83640.c index ecbd5e0d685c..acb0aae60755 100644 --- a/drivers/net/phy/dp83640.c +++ b/drivers/net/phy/dp83640.c @@ -1260,6 +1260,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) dp83640->hwts_rx_en = 1; dp83640->layer = PTP_CLASS_L4; dp83640->version = PTP_CLASS_V1; + cfg.rx_filter = HWTSTAMP_FILTER_PTP_V1_L4_EVENT; break; case HWTSTAMP_FILTER_PTP_V2_L4_EVENT: case HWTSTAMP_FILTER_PTP_V2_L4_SYNC: @@ -1267,6 +1268,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) dp83640->hwts_rx_en = 1; dp83640->layer = PTP_CLASS_L4; dp83640->version = PTP_CLASS_V2; + cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L4_EVENT; break; case HWTSTAMP_FILTER_PTP_V2_L2_EVENT: case HWTSTAMP_FILTER_PTP_V2_L2_SYNC: @@ -1274,6 +1276,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) dp83640->hwts_rx_en = 1; dp83640->layer = PTP_CLASS_L2; dp83640->version = PTP_CLASS_V2; + cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_L2_EVENT; break; case HWTSTAMP_FILTER_PTP_V2_EVENT: case HWTSTAMP_FILTER_PTP_V2_SYNC: @@ -1281,6 +1284,7 @@ static int dp83640_hwtstamp(struct mii_timestamper *mii_ts, struct ifreq *ifr) dp83640->hwts_rx_en = 1; dp83640->layer = PTP_CLASS_L4 | PTP_CLASS_L2; dp83640->version = PTP_CLASS_V2; + cfg.rx_filter = HWTSTAMP_FILTER_PTP_V2_EVENT; break; default: return -ERANGE; diff --git a/drivers/net/usb/ax88172a.c b/drivers/net/usb/ax88172a.c index 4e514f5d7c6c..fd3a04d98dc1 100644 --- a/drivers/net/usb/ax88172a.c +++ b/drivers/net/usb/ax88172a.c @@ -187,6 +187,7 @@ static int ax88172a_bind(struct usbnet *dev, struct usb_interface *intf) ret = asix_read_cmd(dev, AX_CMD_READ_NODE_ID, 0, 0, ETH_ALEN, buf, 0); if (ret < ETH_ALEN) { netdev_err(dev->net, "Failed to read MAC address: %d\n", ret); + ret = -EIO; goto free; } memcpy(dev->net->dev_addr, buf, ETH_ALEN); diff --git a/drivers/net/usb/hso.c b/drivers/net/usb/hso.c index bb8c34d746ab..5f123a8cf68e 100644 --- a/drivers/net/usb/hso.c +++ b/drivers/net/usb/hso.c @@ -1390,8 +1390,9 @@ static void hso_serial_set_termios(struct tty_struct *tty, struct ktermios *old) unsigned long flags; if (old) - hso_dbg(0x16, "Termios called with: cflags new[%d] - old[%d]\n", - tty->termios.c_cflag, old->c_cflag); + hso_dbg(0x16, "Termios called with: cflags new[%u] - old[%u]\n", + (unsigned int)tty->termios.c_cflag, + (unsigned int)old->c_cflag); /* the actual setup */ spin_lock_irqsave(&serial->serial_lock, flags); diff --git a/drivers/net/wan/hdlc_x25.c b/drivers/net/wan/hdlc_x25.c index c84536b03aa8..f70336bb6f52 100644 --- a/drivers/net/wan/hdlc_x25.c +++ b/drivers/net/wan/hdlc_x25.c @@ -71,8 +71,10 @@ static int x25_data_indication(struct net_device *dev, struct sk_buff *skb) { unsigned char *ptr; - if (skb_cow(skb, 1)) + if (skb_cow(skb, 1)) { + kfree_skb(skb); return NET_RX_DROP; + } skb_push(skb, 1); skb_reset_network_header(skb); diff --git a/drivers/net/wan/lapbether.c b/drivers/net/wan/lapbether.c index 284832314f31..b2868433718f 100644 --- a/drivers/net/wan/lapbether.c +++ b/drivers/net/wan/lapbether.c @@ -128,10 +128,12 @@ static int lapbeth_data_indication(struct net_device *dev, struct sk_buff *skb) { unsigned char *ptr; - skb_push(skb, 1); - - if (skb_cow(skb, 1)) + if (skb_cow(skb, 1)) { + kfree_skb(skb); return NET_RX_DROP; + } + + skb_push(skb, 1); ptr = skb->data; *ptr = X25_IFACE_DATA; diff --git a/drivers/net/wan/x25_asy.c b/drivers/net/wan/x25_asy.c index 69773d228ec1..84640a0c13f3 100644 --- a/drivers/net/wan/x25_asy.c +++ b/drivers/net/wan/x25_asy.c @@ -183,7 +183,7 @@ static inline void x25_asy_unlock(struct x25_asy *sl) netif_wake_queue(sl->dev); } -/* Send one completely decapsulated IP datagram to the IP layer. */ +/* Send an LAPB frame to the LAPB module to process. */ static void x25_asy_bump(struct x25_asy *sl) { @@ -195,13 +195,12 @@ static void x25_asy_bump(struct x25_asy *sl) count = sl->rcount; dev->stats.rx_bytes += count; - skb = dev_alloc_skb(count+1); + skb = dev_alloc_skb(count); if (skb == NULL) { netdev_warn(sl->dev, "memory squeeze, dropping packet\n"); dev->stats.rx_dropped++; return; } - skb_push(skb, 1); /* LAPB internal control */ skb_put_data(skb, sl->rbuff, count); skb->protocol = x25_type_trans(skb, sl->dev); err = lapb_data_received(skb->dev, skb); @@ -209,7 +208,6 @@ static void x25_asy_bump(struct x25_asy *sl) kfree_skb(skb); printk(KERN_DEBUG "x25_asy: data received err - %d\n", err); } else { - netif_rx(skb); dev->stats.rx_packets++; } } @@ -356,12 +354,21 @@ static netdev_tx_t x25_asy_xmit(struct sk_buff *skb, */ /* - * Called when I frame data arrives. We did the work above - throw it - * at the net layer. + * Called when I frame data arrive. We add a pseudo header for upper + * layers and pass it to upper layers. */ static int x25_asy_data_indication(struct net_device *dev, struct sk_buff *skb) { + if (skb_cow(skb, 1)) { + kfree_skb(skb); + return NET_RX_DROP; + } + skb_push(skb, 1); + skb->data[0] = X25_IFACE_DATA; + + skb->protocol = x25_type_trans(skb, dev); + return netif_rx(skb); } @@ -657,7 +664,7 @@ static void x25_asy_unesc(struct x25_asy *sl, unsigned char s) switch (s) { case X25_END: if (!test_and_clear_bit(SLF_ERROR, &sl->flags) && - sl->rcount > 2) + sl->rcount >= 2) x25_asy_bump(sl); clear_bit(SLF_ESCAPE, &sl->flags); sl->rcount = 0; diff --git a/drivers/net/wireless/ath/ath10k/ahb.c b/drivers/net/wireless/ath/ath10k/ahb.c index 342a7e58018a..05a61975c83f 100644 --- a/drivers/net/wireless/ath/ath10k/ahb.c +++ b/drivers/net/wireless/ath/ath10k/ahb.c @@ -820,7 +820,7 @@ err_free_irq: ath10k_ahb_release_irq_legacy(ar); err_free_pipes: - ath10k_pci_free_pipes(ar); + ath10k_pci_release_resource(ar); err_resource_deinit: ath10k_ahb_resource_deinit(ar); diff --git a/drivers/net/wireless/ath/ath10k/pci.c b/drivers/net/wireless/ath/ath10k/pci.c index 1d941d53fdc9..cfde7791291a 100644 --- a/drivers/net/wireless/ath/ath10k/pci.c +++ b/drivers/net/wireless/ath/ath10k/pci.c @@ -3473,6 +3473,28 @@ int ath10k_pci_setup_resource(struct ath10k *ar) timer_setup(&ar_pci->rx_post_retry, ath10k_pci_rx_replenish_retry, 0); + ar_pci->attr = kmemdup(pci_host_ce_config_wlan, + sizeof(pci_host_ce_config_wlan), + GFP_KERNEL); + if (!ar_pci->attr) + return -ENOMEM; + + ar_pci->pipe_config = kmemdup(pci_target_ce_config_wlan, + sizeof(pci_target_ce_config_wlan), + GFP_KERNEL); + if (!ar_pci->pipe_config) { + ret = -ENOMEM; + goto err_free_attr; + } + + ar_pci->serv_to_pipe = kmemdup(pci_target_service_to_ce_map_wlan, + sizeof(pci_target_service_to_ce_map_wlan), + GFP_KERNEL); + if (!ar_pci->serv_to_pipe) { + ret = -ENOMEM; + goto err_free_pipe_config; + } + if (QCA_REV_6174(ar) || QCA_REV_9377(ar)) ath10k_pci_override_ce_config(ar); @@ -3480,18 +3502,31 @@ int ath10k_pci_setup_resource(struct ath10k *ar) if (ret) { ath10k_err(ar, "failed to allocate copy engine pipes: %d\n", ret); - return ret; + goto err_free_serv_to_pipe; } return 0; + +err_free_serv_to_pipe: + kfree(ar_pci->serv_to_pipe); +err_free_pipe_config: + kfree(ar_pci->pipe_config); +err_free_attr: + kfree(ar_pci->attr); + return ret; } void ath10k_pci_release_resource(struct ath10k *ar) { + struct ath10k_pci *ar_pci = ath10k_pci_priv(ar); + ath10k_pci_rx_retry_sync(ar); netif_napi_del(&ar->napi); ath10k_pci_ce_deinit(ar); ath10k_pci_free_pipes(ar); + kfree(ar_pci->attr); + kfree(ar_pci->pipe_config); + kfree(ar_pci->serv_to_pipe); } static const struct ath10k_bus_ops ath10k_pci_bus_ops = { @@ -3601,30 +3636,6 @@ static int ath10k_pci_probe(struct pci_dev *pdev, timer_setup(&ar_pci->ps_timer, ath10k_pci_ps_timer, 0); - ar_pci->attr = kmemdup(pci_host_ce_config_wlan, - sizeof(pci_host_ce_config_wlan), - GFP_KERNEL); - if (!ar_pci->attr) { - ret = -ENOMEM; - goto err_free; - } - - ar_pci->pipe_config = kmemdup(pci_target_ce_config_wlan, - sizeof(pci_target_ce_config_wlan), - GFP_KERNEL); - if (!ar_pci->pipe_config) { - ret = -ENOMEM; - goto err_free; - } - - ar_pci->serv_to_pipe = kmemdup(pci_target_service_to_ce_map_wlan, - sizeof(pci_target_service_to_ce_map_wlan), - GFP_KERNEL); - if (!ar_pci->serv_to_pipe) { - ret = -ENOMEM; - goto err_free; - } - ret = ath10k_pci_setup_resource(ar); if (ret) { ath10k_err(ar, "failed to setup resource: %d\n", ret); @@ -3705,10 +3716,9 @@ err_unsupported: err_free_irq: ath10k_pci_free_irq(ar); - ath10k_pci_rx_retry_sync(ar); err_deinit_irq: - ath10k_pci_deinit_irq(ar); + ath10k_pci_release_resource(ar); err_sleep: ath10k_pci_sleep_sync(ar); @@ -3720,29 +3730,18 @@ err_free_pipes: err_core_destroy: ath10k_core_destroy(ar); -err_free: - kfree(ar_pci->attr); - kfree(ar_pci->pipe_config); - kfree(ar_pci->serv_to_pipe); - return ret; } static void ath10k_pci_remove(struct pci_dev *pdev) { struct ath10k *ar = pci_get_drvdata(pdev); - struct ath10k_pci *ar_pci; ath10k_dbg(ar, ATH10K_DBG_PCI, "pci remove\n"); if (!ar) return; - ar_pci = ath10k_pci_priv(ar); - - if (!ar_pci) - return; - ath10k_core_unregister(ar); ath10k_pci_free_irq(ar); ath10k_pci_deinit_irq(ar); @@ -3750,9 +3749,6 @@ static void ath10k_pci_remove(struct pci_dev *pdev) ath10k_pci_sleep_sync(ar); ath10k_pci_release(ar); ath10k_core_destroy(ar); - kfree(ar_pci->attr); - kfree(ar_pci->pipe_config); - kfree(ar_pci->serv_to_pipe); } MODULE_DEVICE_TABLE(pci, ath10k_pci_id_table); diff --git a/drivers/net/wireless/ath/ath9k/hif_usb.c b/drivers/net/wireless/ath/ath9k/hif_usb.c index 4ed21dad6a8e..3f563e02d17d 100644 --- a/drivers/net/wireless/ath/ath9k/hif_usb.c +++ b/drivers/net/wireless/ath/ath9k/hif_usb.c @@ -733,11 +733,13 @@ static void ath9k_hif_usb_reg_in_cb(struct urb *urb) return; } + rx_buf->skb = nskb; + usb_fill_int_urb(urb, hif_dev->udev, usb_rcvintpipe(hif_dev->udev, USB_REG_IN_PIPE), nskb->data, MAX_REG_IN_BUF_SIZE, - ath9k_hif_usb_reg_in_cb, nskb, 1); + ath9k_hif_usb_reg_in_cb, rx_buf, 1); } resubmit: diff --git a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c index 7987a288917b..27116c7d3f4f 100644 --- a/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c +++ b/drivers/net/wireless/intel/iwlwifi/iwl-dbg-tlv.c @@ -271,6 +271,8 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans, { struct iwl_fw_ini_trigger_tlv *trig = (void *)tlv->data; u32 tp = le32_to_cpu(trig->time_point); + struct iwl_ucode_tlv *dup = NULL; + int ret; if (le32_to_cpu(tlv->length) < sizeof(*trig)) return -EINVAL; @@ -283,10 +285,20 @@ static int iwl_dbg_tlv_alloc_trigger(struct iwl_trans *trans, return -EINVAL; } - if (!le32_to_cpu(trig->occurrences)) + if (!le32_to_cpu(trig->occurrences)) { + dup = kmemdup(tlv, sizeof(*tlv) + le32_to_cpu(tlv->length), + GFP_KERNEL); + if (!dup) + return -ENOMEM; + trig = (void *)dup->data; trig->occurrences = cpu_to_le32(-1); + tlv = dup; + } + + ret = iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].trig_list); + kfree(dup); - return iwl_dbg_tlv_add(tlv, &trans->dbg.time_point[tp].trig_list); + return ret; } static int (*dbg_tlv_alloc[])(struct iwl_trans *trans, diff --git a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c index fee01cbbd3ac..27977992fd7f 100644 --- a/drivers/net/wireless/intel/iwlwifi/mvm/sta.c +++ b/drivers/net/wireless/intel/iwlwifi/mvm/sta.c @@ -1189,17 +1189,15 @@ static int iwl_mvm_inactivity_check(struct iwl_mvm *mvm, u8 alloc_for_sta) for_each_set_bit(i, &changetid_queues, IWL_MAX_HW_QUEUES) iwl_mvm_change_queue_tid(mvm, i); + rcu_read_unlock(); + if (free_queue >= 0 && alloc_for_sta != IWL_MVM_INVALID_STA) { ret = iwl_mvm_free_inactive_queue(mvm, free_queue, queue_owner, alloc_for_sta); - if (ret) { - rcu_read_unlock(); + if (ret) return ret; - } } - rcu_read_unlock(); - return free_queue; } diff --git a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c index 65d65c6baf4c..e02bafb8921f 100644 --- a/drivers/net/wireless/intel/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/intel/iwlwifi/pcie/drv.c @@ -582,6 +582,8 @@ static const struct iwl_dev_info iwl_dev_info_table[] = { IWL_DEV_INFO(0x30DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), IWL_DEV_INFO(0x31DC, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name), IWL_DEV_INFO(0x31DC, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), + IWL_DEV_INFO(0xA370, 0x1551, iwl9560_2ac_cfg_soc, iwl9560_killer_1550s_name), + IWL_DEV_INFO(0xA370, 0x1552, iwl9560_2ac_cfg_soc, iwl9560_killer_1550i_name), IWL_DEV_INFO(0x271C, 0x0214, iwl9260_2ac_cfg, iwl9260_1_name), diff --git a/drivers/net/wireless/mediatek/mt76/mt76.h b/drivers/net/wireless/mediatek/mt76/mt76.h index dfe625a53c63..3d7db6ffb599 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76.h +++ b/drivers/net/wireless/mediatek/mt76/mt76.h @@ -301,6 +301,7 @@ struct mt76_hw_cap { #define MT_DRV_TX_ALIGNED4_SKBS BIT(1) #define MT_DRV_SW_RX_AIRTIME BIT(2) #define MT_DRV_RX_DMA_HDR BIT(3) +#define MT_DRV_HW_MGMT_TXQ BIT(4) struct mt76_driver_ops { u32 drv_flags; diff --git a/drivers/net/wireless/mediatek/mt76/mt7603/main.c b/drivers/net/wireless/mediatek/mt76/mt7603/main.c index 26cb711b465f..83dfa6da4761 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7603/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7603/main.c @@ -642,8 +642,10 @@ mt7603_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { struct mt7603_dev *dev = hw->priv; + mutex_lock(&dev->mt76.mutex); dev->coverage_class = max_t(s16, coverage_class, 0); mt7603_mac_set_timing(dev); + mutex_unlock(&dev->mt76.mutex); } static void mt7603_tx(struct ieee80211_hw *hw, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c index fd3ef483a87c..d06afcf46d67 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/debugfs.c @@ -234,10 +234,11 @@ mt7615_queues_acq(struct seq_file *s, void *data) int i; for (i = 0; i < 16; i++) { - int j, acs = i / 4, index = i % 4; + int j, wmm_idx = i % MT7615_MAX_WMM_SETS; + int acs = i / MT7615_MAX_WMM_SETS; u32 ctrl, val, qlen = 0; - val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, index)); + val = mt76_rr(dev, MT_PLE_AC_QEMPTY(acs, wmm_idx)); ctrl = BIT(31) | BIT(15) | (acs << 8); for (j = 0; j < 32; j++) { @@ -245,11 +246,11 @@ mt7615_queues_acq(struct seq_file *s, void *data) continue; mt76_wr(dev, MT_PLE_FL_Q0_CTRL, - ctrl | (j + (index << 5))); + ctrl | (j + (wmm_idx << 5))); qlen += mt76_get_field(dev, MT_PLE_FL_Q3_CTRL, GENMASK(11, 0)); } - seq_printf(s, "AC%d%d: queued=%d\n", acs, index, qlen); + seq_printf(s, "AC%d%d: queued=%d\n", wmm_idx, acs, qlen); } return 0; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c index 5a124610d4af..e5a965df899a 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/dma.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/dma.c @@ -36,10 +36,10 @@ static int mt7622_init_tx_queues_multi(struct mt7615_dev *dev) { static const u8 wmm_queue_map[] = { - MT7622_TXQ_AC0, - MT7622_TXQ_AC1, - MT7622_TXQ_AC2, - MT7622_TXQ_AC3, + [IEEE80211_AC_BK] = MT7622_TXQ_AC0, + [IEEE80211_AC_BE] = MT7622_TXQ_AC1, + [IEEE80211_AC_VI] = MT7622_TXQ_AC2, + [IEEE80211_AC_VO] = MT7622_TXQ_AC3, }; int ret; int i; @@ -100,6 +100,7 @@ mt7615_tx_cleanup(struct mt7615_dev *dev) int i; mt76_queue_tx_cleanup(dev, MT_TXQ_MCU, false); + mt76_queue_tx_cleanup(dev, MT_TXQ_PSD, false); if (is_mt7615(&dev->mt76)) { mt76_queue_tx_cleanup(dev, MT_TXQ_BE, false); } else { diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c index edac37e7847b..22e4eabe6578 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.c @@ -72,8 +72,7 @@ static int mt7615_eeprom_load(struct mt7615_dev *dev, u32 addr) { int ret; - ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_SIZE + - MT7615_EEPROM_EXTRA_DATA); + ret = mt76_eeprom_init(&dev->mt76, MT7615_EEPROM_FULL_SIZE); if (ret < 0) return ret; diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h index 40fed7adc58a..a024dee10362 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/eeprom.h @@ -17,7 +17,7 @@ #define MT7615_EEPROM_TXDPD_SIZE 216 #define MT7615_EEPROM_TXDPD_COUNT (44 + 3) -#define MT7615_EEPROM_EXTRA_DATA (MT7615_EEPROM_TXDPD_OFFSET + \ +#define MT7615_EEPROM_FULL_SIZE (MT7615_EEPROM_TXDPD_OFFSET + \ MT7615_EEPROM_TXDPD_COUNT * \ MT7615_EEPROM_TXDPD_SIZE) diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c index 9f1c6ca7a665..d97315ec7265 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.c @@ -526,22 +526,16 @@ int mt7615_mac_write_txwi(struct mt7615_dev *dev, __le32 *txwi, fc_type = (le16_to_cpu(fc) & IEEE80211_FCTL_FTYPE) >> 2; fc_stype = (le16_to_cpu(fc) & IEEE80211_FCTL_STYPE) >> 4; - if (ieee80211_is_data(fc) || ieee80211_is_bufferable_mmpdu(fc)) { - q_idx = wmm_idx * MT7615_MAX_WMM_SETS + - skb_get_queue_mapping(skb); - p_fmt = is_usb ? MT_TX_TYPE_SF : MT_TX_TYPE_CT; - } else if (beacon) { - if (ext_phy) - q_idx = MT_LMAC_BCN1; - else - q_idx = MT_LMAC_BCN0; + if (beacon) { p_fmt = MT_TX_TYPE_FW; + q_idx = ext_phy ? MT_LMAC_BCN1 : MT_LMAC_BCN0; + } else if (skb_get_queue_mapping(skb) >= MT_TXQ_PSD) { + p_fmt = is_usb ? MT_TX_TYPE_SF : MT_TX_TYPE_CT; + q_idx = ext_phy ? MT_LMAC_ALTX1 : MT_LMAC_ALTX0; } else { - if (ext_phy) - q_idx = MT_LMAC_ALTX1; - else - q_idx = MT_LMAC_ALTX0; p_fmt = is_usb ? MT_TX_TYPE_SF : MT_TX_TYPE_CT; + q_idx = wmm_idx * MT7615_MAX_WMM_SETS + + mt7615_lmac_mapping(dev, skb_get_queue_mapping(skb)); } val = FIELD_PREP(MT_TXD0_TX_BYTES, skb->len + sz_txd) | diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h index f0d4b29a52a2..81608ab656b8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mac.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mac.h @@ -124,21 +124,6 @@ enum tx_pkt_type { MT_TX_TYPE_FW, }; -enum tx_pkt_queue_idx { - MT_LMAC_AC00, - MT_LMAC_AC01, - MT_LMAC_AC02, - MT_LMAC_AC03, - MT_LMAC_ALTX0 = 0x10, - MT_LMAC_BMC0, - MT_LMAC_BCN0, - MT_LMAC_PSMP0, - MT_LMAC_ALTX1, - MT_LMAC_BMC1, - MT_LMAC_BCN1, - MT_LMAC_PSMP1, -}; - enum tx_port_idx { MT_TX_PORT_IDX_LMAC, MT_TX_PORT_IDX_MCU diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/main.c b/drivers/net/wireless/mediatek/mt76/mt7615/main.c index c26f99b368d9..beaca8127680 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/main.c @@ -397,6 +397,7 @@ mt7615_conf_tx(struct ieee80211_hw *hw, struct ieee80211_vif *vif, u16 queue, struct mt7615_vif *mvif = (struct mt7615_vif *)vif->drv_priv; struct mt7615_dev *dev = mt7615_hw_dev(hw); + queue = mt7615_lmac_mapping(dev, queue); queue += mvif->wmm_idx * MT7615_MAX_WMM_SETS; return mt7615_mcu_set_wmm(dev, queue, params); @@ -735,9 +736,12 @@ static void mt7615_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { struct mt7615_phy *phy = mt7615_hw_phy(hw); + struct mt7615_dev *dev = phy->dev; + mutex_lock(&dev->mt76.mutex); phy->coverage_class = max_t(s16, coverage_class, 0); mt7615_mac_set_timing(phy); + mutex_unlock(&dev->mt76.mutex); } static int diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c index e670393506f0..2e99845b9c96 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mmio.c @@ -146,7 +146,7 @@ int mt7615_mmio_probe(struct device *pdev, void __iomem *mem_base, static const struct mt76_driver_ops drv_ops = { /* txwi_size = txd size + txp size */ .txwi_size = MT_TXD_SIZE + sizeof(struct mt7615_txp_common), - .drv_flags = MT_DRV_TXWI_NO_FREE, + .drv_flags = MT_DRV_TXWI_NO_FREE | MT_DRV_HW_MGMT_TXQ, .survey_flags = SURVEY_INFO_TIME_TX | SURVEY_INFO_TIME_RX | SURVEY_INFO_TIME_BSS_RX, diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h index d6176d316bee..3e7d51bf42a4 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h +++ b/drivers/net/wireless/mediatek/mt76/mt7615/mt7615.h @@ -282,6 +282,21 @@ struct mt7615_dev { struct list_head wd_head; }; +enum tx_pkt_queue_idx { + MT_LMAC_AC00, + MT_LMAC_AC01, + MT_LMAC_AC02, + MT_LMAC_AC03, + MT_LMAC_ALTX0 = 0x10, + MT_LMAC_BMC0, + MT_LMAC_BCN0, + MT_LMAC_PSMP0, + MT_LMAC_ALTX1, + MT_LMAC_BMC1, + MT_LMAC_BCN1, + MT_LMAC_PSMP1, +}; + enum { HW_BSSID_0 = 0x0, HW_BSSID_1, @@ -447,6 +462,21 @@ static inline u16 mt7615_wtbl_size(struct mt7615_dev *dev) return MT7615_WTBL_SIZE; } +static inline u8 mt7615_lmac_mapping(struct mt7615_dev *dev, u8 ac) +{ + static const u8 lmac_queue_map[] = { + [IEEE80211_AC_BK] = MT_LMAC_AC00, + [IEEE80211_AC_BE] = MT_LMAC_AC01, + [IEEE80211_AC_VI] = MT_LMAC_AC02, + [IEEE80211_AC_VO] = MT_LMAC_AC03, + }; + + if (WARN_ON_ONCE(ac >= ARRAY_SIZE(lmac_queue_map))) + return MT_LMAC_AC01; /* BE */ + + return lmac_queue_map[ac]; +} + void mt7615_dma_reset(struct mt7615_dev *dev); void mt7615_scan_work(struct work_struct *work); void mt7615_roc_work(struct work_struct *work); diff --git a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c index a50077eb24d7..5be6704770ad 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7615/usb.c +++ b/drivers/net/wireless/mediatek/mt76/mt7615/usb.c @@ -270,7 +270,7 @@ static int mt7663u_probe(struct usb_interface *usb_intf, { static const struct mt76_driver_ops drv_ops = { .txwi_size = MT_USB_TXD_SIZE, - .drv_flags = MT_DRV_RX_DMA_HDR, + .drv_flags = MT_DRV_RX_DMA_HDR | MT_DRV_HW_MGMT_TXQ, .tx_prepare_skb = mt7663u_tx_prepare_skb, .tx_complete_skb = mt7663u_tx_complete_skb, .tx_status_data = mt7663u_tx_status_data, @@ -329,25 +329,26 @@ static int mt7663u_probe(struct usb_interface *usb_intf, if (!mt76_poll_msec(dev, MT_CONN_ON_MISC, MT_TOP_MISC2_FW_PWR_ON, FW_STATE_PWR_ON << 1, 500)) { dev_err(dev->mt76.dev, "Timeout for power on\n"); - return -EIO; + ret = -EIO; + goto error; } alloc_queues: ret = mt76u_alloc_mcu_queue(&dev->mt76); if (ret) - goto error; + goto error_free_q; ret = mt76u_alloc_queues(&dev->mt76); if (ret) - goto error; + goto error_free_q; ret = mt7663u_register_device(dev); if (ret) - goto error_freeq; + goto error_free_q; return 0; -error_freeq: +error_free_q: mt76u_queues_deinit(&dev->mt76); error: mt76u_deinit(&dev->mt76); diff --git a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c index cbbe986655fe..5fda6e7b120c 100644 --- a/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c +++ b/drivers/net/wireless/mediatek/mt76/mt76x02_mmio.c @@ -456,8 +456,9 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) tasklet_disable(&dev->mt76.tx_tasklet); napi_disable(&dev->mt76.tx_napi); - for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) + mt76_for_each_q_rx(&dev->mt76, i) { napi_disable(&dev->mt76.napi[i]); + } mutex_lock(&dev->mt76.mutex); @@ -515,7 +516,7 @@ static void mt76x02_watchdog_reset(struct mt76x02_dev *dev) tasklet_enable(&dev->mt76.pre_tbtt_tasklet); - for (i = 0; i < ARRAY_SIZE(dev->mt76.napi); i++) { + mt76_for_each_q_rx(&dev->mt76, i) { napi_enable(&dev->mt76.napi[i]); napi_schedule(&dev->mt76.napi[i]); } diff --git a/drivers/net/wireless/mediatek/mt76/mt7915/main.c b/drivers/net/wireless/mediatek/mt76/mt7915/main.c index 0575c259f245..05b5650c56c8 100644 --- a/drivers/net/wireless/mediatek/mt76/mt7915/main.c +++ b/drivers/net/wireless/mediatek/mt76/mt7915/main.c @@ -716,9 +716,12 @@ static void mt7915_set_coverage_class(struct ieee80211_hw *hw, s16 coverage_class) { struct mt7915_phy *phy = mt7915_hw_phy(hw); + struct mt7915_dev *dev = phy->dev; + mutex_lock(&dev->mt76.mutex); phy->coverage_class = max_t(s16, coverage_class, 0); mt7915_mac_set_timing(phy); + mutex_unlock(&dev->mt76.mutex); } static int diff --git a/drivers/net/wireless/mediatek/mt76/tx.c b/drivers/net/wireless/mediatek/mt76/tx.c index fca38ea2441f..f10c98aa883c 100644 --- a/drivers/net/wireless/mediatek/mt76/tx.c +++ b/drivers/net/wireless/mediatek/mt76/tx.c @@ -264,6 +264,13 @@ mt76_tx(struct mt76_phy *phy, struct ieee80211_sta *sta, skb_set_queue_mapping(skb, qid); } + if ((dev->drv->drv_flags & MT_DRV_HW_MGMT_TXQ) && + !ieee80211_is_data(hdr->frame_control) && + !ieee80211_is_bufferable_mmpdu(hdr->frame_control)) { + qid = MT_TXQ_PSD; + skb_set_queue_mapping(skb, qid); + } + if (!(wcid->tx_info & MT_WCID_TX_INFO_SET)) ieee80211_get_tx_rates(info->control.vif, sta, skb, info->control.rates, 1); diff --git a/drivers/net/wireless/mediatek/mt76/usb.c b/drivers/net/wireless/mediatek/mt76/usb.c index fb97ea25b4d4..87382b2f7443 100644 --- a/drivers/net/wireless/mediatek/mt76/usb.c +++ b/drivers/net/wireless/mediatek/mt76/usb.c @@ -1010,17 +1010,18 @@ static void mt76u_tx_kick(struct mt76_dev *dev, struct mt76_queue *q) static u8 mt76u_ac_to_hwq(struct mt76_dev *dev, u8 ac) { if (mt76_chip(dev) == 0x7663) { - static const u8 wmm_queue_map[] = { - [IEEE80211_AC_VO] = 0, - [IEEE80211_AC_VI] = 1, - [IEEE80211_AC_BE] = 2, - [IEEE80211_AC_BK] = 4, + static const u8 lmac_queue_map[] = { + /* ac to lmac mapping */ + [IEEE80211_AC_BK] = 0, + [IEEE80211_AC_BE] = 1, + [IEEE80211_AC_VI] = 2, + [IEEE80211_AC_VO] = 4, }; - if (WARN_ON(ac >= ARRAY_SIZE(wmm_queue_map))) - return 2; /* BE */ + if (WARN_ON(ac >= ARRAY_SIZE(lmac_queue_map))) + return 1; /* BE */ - return wmm_queue_map[ac]; + return lmac_queue_map[ac]; } return mt76_ac_to_hwq(ac); @@ -1066,11 +1067,16 @@ static int mt76u_alloc_tx(struct mt76_dev *dev) static void mt76u_free_tx(struct mt76_dev *dev) { - struct mt76_queue *q; - int i, j; + int i; for (i = 0; i < IEEE80211_NUM_ACS; i++) { + struct mt76_queue *q; + int j; + q = dev->q_tx[i].q; + if (!q) + continue; + for (j = 0; j < q->ndesc; j++) usb_free_urb(q->entry[j].urb); } @@ -1078,17 +1084,22 @@ static void mt76u_free_tx(struct mt76_dev *dev) void mt76u_stop_tx(struct mt76_dev *dev) { - struct mt76_queue_entry entry; - struct mt76_queue *q; - int i, j, ret; + int ret; ret = wait_event_timeout(dev->tx_wait, !mt76_has_tx_pending(&dev->phy), HZ / 5); if (!ret) { + struct mt76_queue_entry entry; + struct mt76_queue *q; + int i, j; + dev_err(dev->dev, "timed out waiting for pending tx\n"); for (i = 0; i < IEEE80211_NUM_ACS; i++) { q = dev->q_tx[i].q; + if (!q) + continue; + for (j = 0; j < q->ndesc; j++) usb_kill_urb(q->entry[j].urb); } @@ -1100,6 +1111,8 @@ void mt76u_stop_tx(struct mt76_dev *dev) */ for (i = 0; i < IEEE80211_NUM_ACS; i++) { q = dev->q_tx[i].q; + if (!q) + continue; /* Assure we are in sync with killed tasklet. */ spin_lock_bh(&q->lock); diff --git a/drivers/net/xen-netfront.c b/drivers/net/xen-netfront.c index 482c6c8b0fb7..88280057e032 100644 --- a/drivers/net/xen-netfront.c +++ b/drivers/net/xen-netfront.c @@ -63,6 +63,8 @@ module_param_named(max_queues, xennet_max_queues, uint, 0644); MODULE_PARM_DESC(max_queues, "Maximum number of queues per virtual interface"); +#define XENNET_TIMEOUT (5 * HZ) + static const struct ethtool_ops xennet_ethtool_ops; struct netfront_cb { @@ -1334,12 +1336,15 @@ static struct net_device *xennet_create_dev(struct xenbus_device *dev) netif_carrier_off(netdev); - xenbus_switch_state(dev, XenbusStateInitialising); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) != - XenbusStateClosed && - xenbus_read_driver_state(dev->otherend) != - XenbusStateUnknown); + do { + xenbus_switch_state(dev, XenbusStateInitialising); + err = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) != + XenbusStateClosed && + xenbus_read_driver_state(dev->otherend) != + XenbusStateUnknown, XENNET_TIMEOUT); + } while (!err); + return netdev; exit: @@ -2139,28 +2144,43 @@ static const struct attribute_group xennet_dev_group = { }; #endif /* CONFIG_SYSFS */ -static int xennet_remove(struct xenbus_device *dev) +static void xennet_bus_close(struct xenbus_device *dev) { - struct netfront_info *info = dev_get_drvdata(&dev->dev); - - dev_dbg(&dev->dev, "%s\n", dev->nodename); + int ret; - if (xenbus_read_driver_state(dev->otherend) != XenbusStateClosed) { + if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) + return; + do { xenbus_switch_state(dev, XenbusStateClosing); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosing || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); + ret = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosing || + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosed || + xenbus_read_driver_state(dev->otherend) == + XenbusStateUnknown, + XENNET_TIMEOUT); + } while (!ret); + + if (xenbus_read_driver_state(dev->otherend) == XenbusStateClosed) + return; + do { xenbus_switch_state(dev, XenbusStateClosed); - wait_event(module_wq, - xenbus_read_driver_state(dev->otherend) == - XenbusStateClosed || - xenbus_read_driver_state(dev->otherend) == - XenbusStateUnknown); - } + ret = wait_event_timeout(module_wq, + xenbus_read_driver_state(dev->otherend) == + XenbusStateClosed || + xenbus_read_driver_state(dev->otherend) == + XenbusStateUnknown, + XENNET_TIMEOUT); + } while (!ret); +} + +static int xennet_remove(struct xenbus_device *dev) +{ + struct netfront_info *info = dev_get_drvdata(&dev->dev); + xennet_bus_close(dev); xennet_disconnect_backend(info); if (info->netdev->reg_state == NETREG_REGISTERED) diff --git a/drivers/nfc/s3fwrn5/core.c b/drivers/nfc/s3fwrn5/core.c index 91d4d5b28a7d..ba6c486d6465 100644 --- a/drivers/nfc/s3fwrn5/core.c +++ b/drivers/nfc/s3fwrn5/core.c @@ -198,6 +198,7 @@ int s3fwrn5_recv_frame(struct nci_dev *ndev, struct sk_buff *skb, case S3FWRN5_MODE_FW: return s3fwrn5_fw_recv_frame(ndev, skb); default: + kfree_skb(skb); return -ENODEV; } } diff --git a/drivers/pci/pci.c b/drivers/pci/pci.c index ce096272f52b..c9338f914a0e 100644 --- a/drivers/pci/pci.c +++ b/drivers/pci/pci.c @@ -4638,8 +4638,7 @@ static int pci_pm_reset(struct pci_dev *dev, int probe) * pcie_wait_for_link_delay - Wait until link is active or inactive * @pdev: Bridge device * @active: waiting for active or inactive? - * @delay: Delay to wait after link has become active (in ms). Specify %0 - * for no delay. + * @delay: Delay to wait after link has become active (in ms) * * Use this to wait till link becomes active or inactive. */ @@ -4680,7 +4679,7 @@ static bool pcie_wait_for_link_delay(struct pci_dev *pdev, bool active, msleep(10); timeout -= 10; } - if (active && ret && delay) + if (active && ret) msleep(delay); else if (ret != active) pci_info(pdev, "Data Link Layer Link Active not %s in 1000 msec\n", @@ -4801,28 +4800,17 @@ void pci_bridge_wait_for_secondary_bus(struct pci_dev *dev) if (!pcie_downstream_port(dev)) return; - /* - * Per PCIe r5.0, sec 6.6.1, for downstream ports that support - * speeds > 5 GT/s, we must wait for link training to complete - * before the mandatory delay. - * - * We can only tell when link training completes via DLL Link - * Active, which is required for downstream ports that support - * speeds > 5 GT/s (sec 7.5.3.6). Unfortunately some common - * devices do not implement Link Active reporting even when it's - * required, so we'll check for that directly instead of checking - * the supported link speed. We assume devices without Link Active - * reporting can train in 100 ms regardless of speed. - */ - if (dev->link_active_reporting) { - pci_dbg(dev, "waiting for link to train\n"); - if (!pcie_wait_for_link_delay(dev, true, 0)) { + if (pcie_get_speed_cap(dev) <= PCIE_SPEED_5_0GT) { + pci_dbg(dev, "waiting %d ms for downstream link\n", delay); + msleep(delay); + } else { + pci_dbg(dev, "waiting %d ms for downstream link, after activation\n", + delay); + if (!pcie_wait_for_link_delay(dev, true, delay)) { /* Did not train, no need to wait any further */ return; } } - pci_dbg(child, "waiting %d ms to become accessible\n", delay); - msleep(delay); if (!pci_device_is_present(child)) { pci_dbg(child, "waiting additional %d ms to become accessible\n", delay); diff --git a/drivers/staging/media/atomisp/Kconfig b/drivers/staging/media/atomisp/Kconfig index fea06cb0eb48..37577bb72998 100644 --- a/drivers/staging/media/atomisp/Kconfig +++ b/drivers/staging/media/atomisp/Kconfig @@ -22,7 +22,7 @@ config VIDEO_ATOMISP module will be called atomisp config VIDEO_ATOMISP_ISP2401 - bool "VIDEO_ATOMISP_ISP2401" + bool "Use Intel Atom ISP on Cherrytail/Anniedale (ISP2401)" depends on VIDEO_ATOMISP help Enable support for Atom ISP2401-based boards. diff --git a/drivers/staging/media/atomisp/Makefile b/drivers/staging/media/atomisp/Makefile index 9dc8072799e3..205d0f8cc2e1 100644 --- a/drivers/staging/media/atomisp/Makefile +++ b/drivers/staging/media/atomisp/Makefile @@ -156,6 +156,7 @@ atomisp-objs += \ pci/hive_isp_css_common/host/timed_ctrl.o \ pci/hive_isp_css_common/host/vmem.o \ pci/hive_isp_css_shared/host/tag.o \ + pci/system_local.o \ obj-byt = \ pci/css_2400_system/hive/ia_css_isp_configs.o \ @@ -182,7 +183,6 @@ INCLUDES += \ -I$(atomisp)/include/hmm/ \ -I$(atomisp)/include/mmu/ \ -I$(atomisp)/pci/ \ - -I$(atomisp)/pci/hrt/ \ -I$(atomisp)/pci/base/circbuf/interface/ \ -I$(atomisp)/pci/base/refcount/interface/ \ -I$(atomisp)/pci/camera/pipe/interface/ \ @@ -192,7 +192,6 @@ INCLUDES += \ -I$(atomisp)/pci/hive_isp_css_include/ \ -I$(atomisp)/pci/hive_isp_css_include/device_access/ \ -I$(atomisp)/pci/hive_isp_css_include/host/ \ - -I$(atomisp)/pci/hive_isp_css_include/memory_access/ \ -I$(atomisp)/pci/hive_isp_css_shared/ \ -I$(atomisp)/pci/hive_isp_css_shared/host/ \ -I$(atomisp)/pci/isp/kernels/ \ @@ -311,9 +310,7 @@ INCLUDES += \ -I$(atomisp)/pci/runtime/tagger/interface/ INCLUDES_byt += \ - -I$(atomisp)/pci/css_2400_system/ \ -I$(atomisp)/pci/css_2400_system/hive/ \ - -I$(atomisp)/pci/css_2400_system/hrt/ \ INCLUDES_cht += \ -I$(atomisp)/pci/css_2401_system/ \ @@ -321,7 +318,6 @@ INCLUDES_cht += \ -I$(atomisp)/pci/css_2401_system/hive/ \ -I$(atomisp)/pci/css_2401_system/hrt/ \ -# -I$(atomisp)/pci/css_2401_system/hrt/ \ # -I$(atomisp)/pci/css_2401_system/hive_isp_css_2401_system_generated/ \ DEFINES := -DHRT_HW -DHRT_ISP_CSS_CUSTOM_HOST -DHRT_USE_VIR_ADDRS -D__HOST__ diff --git a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c index 90d125ba080f..c90730513438 100644 --- a/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c +++ b/drivers/staging/media/atomisp/i2c/atomisp-ov2680.c @@ -495,11 +495,11 @@ static int ov2680_h_flip(struct v4l2_subdev *sd, s32 value) ret = ov2680_read_reg(client, 1, OV2680_MIRROR_REG, &val); if (ret) return ret; - if (value) { + if (value) val |= OV2680_FLIP_MIRROR_BIT_ENABLE; - } else { + else val &= ~OV2680_FLIP_MIRROR_BIT_ENABLE; - } + ret = ov2680_write_reg(client, 1, OV2680_MIRROR_REG, val); if (ret) diff --git a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c index 97ab10bc45ca..e698b63d6cb7 100644 --- a/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c +++ b/drivers/staging/media/atomisp/i2c/ov5693/atomisp-ov5693.c @@ -1899,7 +1899,7 @@ static int ov5693_probe(struct i2c_client *client) { struct ov5693_device *dev; int i2c; - int ret = 0; + int ret; void *pdata; unsigned int i; @@ -1929,8 +1929,10 @@ static int ov5693_probe(struct i2c_client *client) pdata = gmin_camera_platform_data(&dev->sd, ATOMISP_INPUT_FORMAT_RAW_10, atomisp_bayer_order_bggr); - if (!pdata) + if (!pdata) { + ret = -EINVAL; goto out_free; + } ret = ov5693_s_config(&dev->sd, client->irq, pdata); if (ret) diff --git a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h index 873344a02ccf..5a5121d958ed 100644 --- a/drivers/staging/media/atomisp/include/linux/atomisp_platform.h +++ b/drivers/staging/media/atomisp/include/linux/atomisp_platform.h @@ -250,6 +250,7 @@ const struct atomisp_camera_caps *atomisp_get_default_camera_caps(void); #define IS_MFLD __IS_SOC(INTEL_FAM6_ATOM_SALTWELL_MID) #define IS_BYT __IS_SOC(INTEL_FAM6_ATOM_SILVERMONT) #define IS_CHT __IS_SOC(INTEL_FAM6_ATOM_AIRMONT) +#define IS_MRFD __IS_SOC(INTEL_FAM6_ATOM_SILVERMONT_MID) #define IS_MOFD __IS_SOC(INTEL_FAM6_ATOM_AIRMONT_MID) /* Both CHT and MOFD come with ISP2401 */ diff --git a/drivers/staging/media/atomisp/pci/atomisp-regs.h b/drivers/staging/media/atomisp/pci/atomisp-regs.h index de34ee28e390..022997f47121 100644 --- a/drivers/staging/media/atomisp/pci/atomisp-regs.h +++ b/drivers/staging/media/atomisp/pci/atomisp-regs.h @@ -20,9 +20,6 @@ #define ATOMISP_REGS_H /* common register definitions */ -#define PUNIT_PORT 0x04 -#define CCK_PORT 0x14 - #define PCICMDSTS 0x01 #define INTR 0x0f #define MSI_CAPID 0x24 diff --git a/drivers/staging/media/atomisp/pci/atomisp_acc.c b/drivers/staging/media/atomisp/pci/atomisp_acc.c index 76861396ba86..f638d0bd09fe 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_acc.c +++ b/drivers/staging/media/atomisp/pci/atomisp_acc.c @@ -355,11 +355,11 @@ int atomisp_acc_map(struct atomisp_sub_device *asd, struct atomisp_acc_map *map) pgnr = DIV_ROUND_UP(map->length, PAGE_SIZE); if (pgnr < ((PAGE_ALIGN(map->length)) >> PAGE_SHIFT)) { - dev_err(atomisp_dev, + dev_err(asd->isp->dev, "user space memory size is less than the expected size..\n"); return -ENOMEM; } else if (pgnr > ((PAGE_ALIGN(map->length)) >> PAGE_SHIFT)) { - dev_err(atomisp_dev, + dev_err(asd->isp->dev, "user space memory size is large than the expected size..\n"); return -ENOMEM; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.c b/drivers/staging/media/atomisp/pci/atomisp_cmd.c index 7b936e5a5f03..8ea65bef35d2 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.c +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.c @@ -21,6 +21,7 @@ #include <linux/firmware.h> #include <linux/pci.h> #include <linux/interrupt.h> +#include <linux/io.h> #include <linux/kernel.h> #include <linux/kfifo.h> #include <linux/pm_runtime.h> @@ -109,7 +110,7 @@ struct atomisp_acc_pipe *atomisp_to_acc_pipe(struct video_device *dev) static unsigned short atomisp_get_sensor_fps(struct atomisp_sub_device *asd) { - struct v4l2_subdev_frame_interval fi; + struct v4l2_subdev_frame_interval fi = { 0 }; struct atomisp_device *isp = asd->isp; unsigned short fps = 0; @@ -206,6 +207,7 @@ int atomisp_freq_scaling(struct atomisp_device *isp, enum atomisp_dfs_mode mode, bool force) { + struct pci_dev *pdev = to_pci_dev(isp->dev); /* FIXME! Only use subdev[0] status yet */ struct atomisp_sub_device *asd = &isp->asd[0]; const struct atomisp_dfs_config *dfs; @@ -219,7 +221,7 @@ int atomisp_freq_scaling(struct atomisp_device *isp, return -EINVAL; } - if ((isp->pdev->device & ATOMISP_PCI_DEVICE_SOC_MASK) == + if ((pdev->device & ATOMISP_PCI_DEVICE_SOC_MASK) == ATOMISP_PCI_DEVICE_SOC_CHT && ATOMISP_USE_YUVPP(asd)) isp->dfs = &dfs_config_cht_soc; @@ -357,39 +359,41 @@ static void clear_isp_irq(enum hrt_isp_css_irq irq) irq_clear_all(IRQ0_ID); } -void atomisp_msi_irq_init(struct atomisp_device *isp, struct pci_dev *dev) +void atomisp_msi_irq_init(struct atomisp_device *isp) { + struct pci_dev *pdev = to_pci_dev(isp->dev); u32 msg32; u16 msg16; - pci_read_config_dword(dev, PCI_MSI_CAPID, &msg32); + pci_read_config_dword(pdev, PCI_MSI_CAPID, &msg32); msg32 |= 1 << MSI_ENABLE_BIT; - pci_write_config_dword(dev, PCI_MSI_CAPID, msg32); + pci_write_config_dword(pdev, PCI_MSI_CAPID, msg32); msg32 = (1 << INTR_IER) | (1 << INTR_IIR); - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, msg32); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg32); - pci_read_config_word(dev, PCI_COMMAND, &msg16); + pci_read_config_word(pdev, PCI_COMMAND, &msg16); msg16 |= (PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER | PCI_COMMAND_INTX_DISABLE); - pci_write_config_word(dev, PCI_COMMAND, msg16); + pci_write_config_word(pdev, PCI_COMMAND, msg16); } -void atomisp_msi_irq_uninit(struct atomisp_device *isp, struct pci_dev *dev) +void atomisp_msi_irq_uninit(struct atomisp_device *isp) { + struct pci_dev *pdev = to_pci_dev(isp->dev); u32 msg32; u16 msg16; - pci_read_config_dword(dev, PCI_MSI_CAPID, &msg32); + pci_read_config_dword(pdev, PCI_MSI_CAPID, &msg32); msg32 &= ~(1 << MSI_ENABLE_BIT); - pci_write_config_dword(dev, PCI_MSI_CAPID, msg32); + pci_write_config_dword(pdev, PCI_MSI_CAPID, msg32); msg32 = 0x0; - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, msg32); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg32); - pci_read_config_word(dev, PCI_COMMAND, &msg16); + pci_read_config_word(pdev, PCI_COMMAND, &msg16); msg16 &= ~(PCI_COMMAND_MASTER); - pci_write_config_word(dev, PCI_COMMAND, msg16); + pci_write_config_word(pdev, PCI_COMMAND, msg16); } static void atomisp_sof_event(struct atomisp_sub_device *asd) @@ -480,11 +484,12 @@ static void print_csi_rx_errors(enum mipi_port_id port, /* Clear irq reg */ static void clear_irq_reg(struct atomisp_device *isp) { + struct pci_dev *pdev = to_pci_dev(isp->dev); u32 msg_ret; - pci_read_config_dword(isp->pdev, PCI_INTERRUPT_CTRL, &msg_ret); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &msg_ret); msg_ret |= 1 << INTR_IIR; - pci_write_config_dword(isp->pdev, PCI_INTERRUPT_CTRL, msg_ret); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, msg_ret); } static struct atomisp_sub_device * @@ -665,11 +670,10 @@ bool atomisp_buffers_queued_pipe(struct atomisp_video_pipe *pipe) void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr, unsigned int size) { - u32 __iomem *io_virt_addr; unsigned int data = 0; unsigned int size32 = DIV_ROUND_UP(size, sizeof(u32)); - dev_dbg(isp->dev, "atomisp_io_base:%p\n", atomisp_io_base); + dev_dbg(isp->dev, "atomisp mmio base: %p\n", isp->base); dev_dbg(isp->dev, "%s, addr:0x%x, size: %d, size32: %d\n", __func__, addr, size, size32); if (size32 * 4 + addr > 0x4000) { @@ -678,13 +682,12 @@ void dump_sp_dmem(struct atomisp_device *isp, unsigned int addr, return; } addr += SP_DMEM_BASE; - io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + addr &= 0x003FFFFF; do { - data = *io_virt_addr; + data = readl(isp->base + addr); dev_dbg(isp->dev, "%s, \t [0x%x]:0x%x\n", __func__, addr, data); - io_virt_addr += sizeof(u32); - size32 -= 1; - } while (size32 > 0); + addr += sizeof(u32); + } while (--size32); } static struct videobuf_buffer *atomisp_css_frame_to_vbuf( @@ -1289,6 +1292,7 @@ void atomisp_delayed_init_work(struct work_struct *work) static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) { + struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; bool stream_restart[MAX_STREAM_NUM] = {0}; bool depth_mode = false; @@ -1372,8 +1376,8 @@ static void __atomisp_css_recover(struct atomisp_device *isp, bool isp_timeout) clear_isp_irq(hrt_isp_css_irq_sp); /* Set the SRSE to 3 before resetting */ - pci_write_config_dword(isp->pdev, PCI_I_CONTROL, isp->saved_regs.i_control | - MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); + pci_write_config_dword(pdev, PCI_I_CONTROL, + isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); /* reset ISP and restore its state */ isp->isp_timeout = true; @@ -6158,6 +6162,7 @@ out: /*Turn off ISP dphy */ int atomisp_ospm_dphy_down(struct atomisp_device *isp) { + struct pci_dev *pdev = to_pci_dev(isp->dev); unsigned long flags; u32 reg; @@ -6179,9 +6184,9 @@ done: * MRFLD HW design need all CSI ports are disabled before * powering down the IUNIT. */ - pci_read_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, ®); + pci_read_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, ®); reg |= MRFLD_ALL_CSI_PORTS_OFF_MASK; - pci_write_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, reg); + pci_write_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, reg); return 0; } diff --git a/drivers/staging/media/atomisp/pci/atomisp_cmd.h b/drivers/staging/media/atomisp/pci/atomisp_cmd.h index 0bde995f1a8d..1c0d464c2ac1 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_cmd.h +++ b/drivers/staging/media/atomisp/pci/atomisp_cmd.h @@ -68,8 +68,8 @@ bool atomisp_buffers_queued_pipe(struct atomisp_video_pipe *pipe); /* * Interrupt functions */ -void atomisp_msi_irq_init(struct atomisp_device *isp, struct pci_dev *dev); -void atomisp_msi_irq_uninit(struct atomisp_device *isp, struct pci_dev *dev); +void atomisp_msi_irq_init(struct atomisp_device *isp); +void atomisp_msi_irq_uninit(struct atomisp_device *isp); void atomisp_wdt_work(struct work_struct *work); void atomisp_wdt(struct timer_list *t); void atomisp_setup_flash(struct atomisp_sub_device *asd); diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat.h b/drivers/staging/media/atomisp/pci/atomisp_compat.h index b2ed83c2f337..6a2a81a3eb23 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat.h @@ -29,8 +29,6 @@ struct atomisp_sub_device; struct video_device; enum atomisp_input_stream_id; -extern void __iomem *atomisp_io_base; - struct atomisp_metadata_buf { struct ia_css_metadata *metadata; void *md_vptr; diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c index c1e282a974d0..cccc5bfa1057 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.c @@ -33,13 +33,12 @@ #include "atomisp_ioctl.h" #include "atomisp_acc.h" -#include <asm/intel-mid.h> - #include "ia_css_debug.h" #include "ia_css_isp_param.h" #include "sh_css_hrt.h" #include "ia_css_isys.h" +#include <linux/io.h> #include <linux/pm_runtime.h> /* Assume max number of ACC stages */ @@ -69,92 +68,94 @@ struct bayer_ds_factor { static void atomisp_css2_hw_store_8(hrt_address addr, uint8_t data) { - s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; spin_lock_irqsave(&mmio_lock, flags); - *io_virt_addr = data; + writeb(data, isp->base + (addr & 0x003FFFFF)); spin_unlock_irqrestore(&mmio_lock, flags); } static void atomisp_css2_hw_store_16(hrt_address addr, uint16_t data) { - s16 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; spin_lock_irqsave(&mmio_lock, flags); - *io_virt_addr = data; + writew(data, isp->base + (addr & 0x003FFFFF)); spin_unlock_irqrestore(&mmio_lock, flags); } void atomisp_css2_hw_store_32(hrt_address addr, uint32_t data) { - s32 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; spin_lock_irqsave(&mmio_lock, flags); - *io_virt_addr = data; + writel(data, isp->base + (addr & 0x003FFFFF)); spin_unlock_irqrestore(&mmio_lock, flags); } static uint8_t atomisp_css2_hw_load_8(hrt_address addr) { - s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; u8 ret; spin_lock_irqsave(&mmio_lock, flags); - ret = *io_virt_addr; + ret = readb(isp->base + (addr & 0x003FFFFF)); spin_unlock_irqrestore(&mmio_lock, flags); return ret; } static uint16_t atomisp_css2_hw_load_16(hrt_address addr) { - s16 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; u16 ret; spin_lock_irqsave(&mmio_lock, flags); - ret = *io_virt_addr; + ret = readw(isp->base + (addr & 0x003FFFFF)); spin_unlock_irqrestore(&mmio_lock, flags); return ret; } static uint32_t atomisp_css2_hw_load_32(hrt_address addr) { - s32 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; u32 ret; spin_lock_irqsave(&mmio_lock, flags); - ret = *io_virt_addr; + ret = readl(isp->base + (addr & 0x003FFFFF)); spin_unlock_irqrestore(&mmio_lock, flags); return ret; } -static void atomisp_css2_hw_store(hrt_address addr, - const void *from, uint32_t n) +static void atomisp_css2_hw_store(hrt_address addr, const void *from, uint32_t n) { - s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; unsigned int i; + addr &= 0x003FFFFF; spin_lock_irqsave(&mmio_lock, flags); - for (i = 0; i < n; i++, io_virt_addr++, from++) - *io_virt_addr = *(s8 *)from; + for (i = 0; i < n; i++, from++) + writeb(*(s8 *)from, isp->base + addr + i); + spin_unlock_irqrestore(&mmio_lock, flags); } static void atomisp_css2_hw_load(hrt_address addr, void *to, uint32_t n) { - s8 __iomem *io_virt_addr = atomisp_io_base + (addr & 0x003FFFFF); + struct atomisp_device *isp = dev_get_drvdata(atomisp_dev); unsigned long flags; unsigned int i; + addr &= 0x003FFFFF; spin_lock_irqsave(&mmio_lock, flags); - for (i = 0; i < n; i++, to++, io_virt_addr++) - *(s8 *)to = *io_virt_addr; + for (i = 0; i < n; i++, to++) + *(s8 *)to = readb(isp->base + addr + i); spin_unlock_irqrestore(&mmio_lock, flags); } @@ -181,10 +182,10 @@ void atomisp_load_uint32(hrt_address addr, uint32_t *data) *data = atomisp_css2_hw_load_32(addr); } -static int hmm_get_mmu_base_addr(unsigned int *mmu_base_addr) +static int hmm_get_mmu_base_addr(struct device *dev, unsigned int *mmu_base_addr) { if (!sh_mmu_mrfld.get_pd_base) { - dev_err(atomisp_dev, "get mmu base address failed.\n"); + dev_err(dev, "get mmu base address failed.\n"); return -EINVAL; } @@ -839,7 +840,7 @@ int atomisp_css_init(struct atomisp_device *isp) int ret; int err; - ret = hmm_get_mmu_base_addr(&mmu_base_addr); + ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr); if (ret) return ret; @@ -941,7 +942,7 @@ int atomisp_css_resume(struct atomisp_device *isp) unsigned int mmu_base_addr; int ret; - ret = hmm_get_mmu_base_addr(&mmu_base_addr); + ret = hmm_get_mmu_base_addr(isp->dev, &mmu_base_addr); if (ret) { dev_err(isp->dev, "get base address error.\n"); return -EINVAL; @@ -1966,8 +1967,7 @@ void atomisp_css_input_set_mode(struct atomisp_sub_device *asd, true, 0x13000, &size_mem_words) != 0) { - if (intel_mid_identify_cpu() == - INTEL_MID_CPU_CHIP_TANGIER) + if (IS_MRFD) size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_2; else size_mem_words = CSS_MIPI_FRAME_BUFFER_SIZE_1; @@ -2414,13 +2414,13 @@ static void __configure_preview_pp_input(struct atomisp_sub_device *asd, struct ia_css_resolution *effective_res = &stream_config->input_config.effective_res; - const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} }; + static const struct bayer_ds_factor bds_fct[] = {{2, 1}, {3, 2}, {5, 4} }; /* * BZ201033: YUV decimation factor of 4 causes couple of rightmost * columns to be shaded. Remove this factor to work around the CSS bug. * const unsigned int yuv_dec_fct[] = {4, 2}; */ - const unsigned int yuv_dec_fct[] = { 2 }; + static const unsigned int yuv_dec_fct[] = { 2 }; unsigned int i; if (width == 0 && height == 0) @@ -2540,7 +2540,7 @@ static void __configure_video_pp_input(struct atomisp_sub_device *asd, struct ia_css_resolution *effective_res = &stream_config->input_config.effective_res; - const struct bayer_ds_factor bds_factors[] = { + static const struct bayer_ds_factor bds_factors[] = { {8, 1}, {6, 1}, {4, 1}, {3, 1}, {2, 1}, {3, 2} }; unsigned int i; @@ -4337,7 +4337,7 @@ static const char * const fw_acc_type_name[] = { [IA_CSS_ACC_STANDALONE] = "Stand-alone acceleration", }; -int atomisp_css_dump_blob_infor(void) +int atomisp_css_dump_blob_infor(struct atomisp_device *isp) { struct ia_css_blob_descr *bd = sh_css_blob_info; unsigned int i, nm = sh_css_num_binaries; @@ -4354,8 +4354,7 @@ int atomisp_css_dump_blob_infor(void) for (i = 0; i < sh_css_num_binaries - NUM_OF_SPS; i++) { switch (bd[i].header.type) { case ia_css_isp_firmware: - dev_dbg(atomisp_dev, - "Num%2d type %s (%s), binary id is %2d, name is %s\n", + dev_dbg(isp->dev, "Num%2d type %s (%s), binary id is %2d, name is %s\n", i + NUM_OF_SPS, fw_type_name[bd[i].header.type], fw_acc_type_name[bd[i].header.info.isp.type], @@ -4363,8 +4362,7 @@ int atomisp_css_dump_blob_infor(void) bd[i].name); break; default: - dev_dbg(atomisp_dev, - "Num%2d type %s, name is %s\n", + dev_dbg(isp->dev, "Num%2d type %s, name is %s\n", i + NUM_OF_SPS, fw_type_name[bd[i].header.type], bd[i].name); } diff --git a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.h b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.h index 8376aec18e3e..e0601534380f 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_compat_css20.h +++ b/drivers/staging/media/atomisp/pci/atomisp_compat_css20.h @@ -153,7 +153,7 @@ int atomisp_css_debug_dump_isp_binary(void); int atomisp_css_dump_sp_raw_copy_linecount(bool reduced); -int atomisp_css_dump_blob_infor(void); +int atomisp_css_dump_blob_infor(struct atomisp_device *isp); void atomisp_css_set_isp_config_id(struct atomisp_sub_device *asd, uint32_t isp_config_id); diff --git a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c index fe0e2bfde27f..f670faf978e6 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_drvfs.c +++ b/drivers/staging/media/atomisp/pci/atomisp_drvfs.c @@ -62,9 +62,9 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp, if (opt & OPTION_VALID) { if (opt & OPTION_BIN_LIST) { - ret = atomisp_css_dump_blob_infor(); + ret = atomisp_css_dump_blob_infor(isp); if (ret) { - dev_err(atomisp_dev, "%s dump blob infor err[ret:%d]\n", + dev_err(isp->dev, "%s dump blob infor err[ret:%d]\n", __func__, ret); goto opt_err; } @@ -76,7 +76,7 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp, atomisp_css_debug_dump_isp_binary(); } else { ret = -EPERM; - dev_err(atomisp_dev, "%s dump running bin err[ret:%d]\n", + dev_err(isp->dev, "%s dump running bin err[ret:%d]\n", __func__, ret); goto opt_err; } @@ -86,8 +86,7 @@ static inline int iunit_dump_dbgopt(struct atomisp_device *isp, hmm_show_mem_stat(__func__, __LINE__); } else { ret = -EINVAL; - dev_err(atomisp_dev, "%s dump nothing[ret=%d]\n", __func__, - ret); + dev_err(isp->dev, "%s dump nothing[ret=%d]\n", __func__, ret); } opt_err: @@ -185,8 +184,9 @@ static void iunit_drvfs_remove_files(struct device_driver *drv) driver_remove_file(drv, &iunit_drvfs_attrs[i]); } -int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp) +int atomisp_drvfs_init(struct atomisp_device *isp) { + struct device_driver *drv = isp->dev->driver; int ret; iunit_debug.isp = isp; @@ -194,7 +194,7 @@ int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp) ret = iunit_drvfs_create_files(iunit_debug.drv); if (ret) { - dev_err(atomisp_dev, "drvfs_create_files error: %d\n", ret); + dev_err(isp->dev, "drvfs_create_files error: %d\n", ret); iunit_drvfs_remove_files(iunit_debug.drv); } diff --git a/drivers/staging/media/atomisp/pci/atomisp_drvfs.h b/drivers/staging/media/atomisp/pci/atomisp_drvfs.h index 4911037231fb..8f4cc722b881 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_drvfs.h +++ b/drivers/staging/media/atomisp/pci/atomisp_drvfs.h @@ -19,7 +19,7 @@ #ifndef __ATOMISP_DRVFS_H__ #define __ATOMISP_DRVFS_H__ -int atomisp_drvfs_init(struct device_driver *drv, struct atomisp_device *isp); +int atomisp_drvfs_init(struct atomisp_device *isp); void atomisp_drvfs_exit(void); #endif /* __ATOMISP_DRVFS_H__ */ diff --git a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c index 1af9da8acf4c..0df46a1af5f0 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c +++ b/drivers/staging/media/atomisp/pci/atomisp_gmin_platform.c @@ -26,6 +26,9 @@ enum clock_rate { #define CLK_RATE_19_2MHZ 19200000 #define CLK_RATE_25_0MHZ 25000000 +/* Valid clock number range from 0 to 5 */ +#define MAX_CLK_COUNT 5 + /* X-Powers AXP288 register set */ #define ALDO1_SEL_REG 0x28 #define ALDO1_CTRL3_REG 0x13 @@ -61,9 +64,7 @@ enum clock_rate { struct gmin_subdev { struct v4l2_subdev *subdev; - int clock_num; enum clock_rate clock_src; - bool clock_on; struct clk *pmc_clk; struct gpio_desc *gpio0; struct gpio_desc *gpio1; @@ -75,11 +76,16 @@ struct gmin_subdev { unsigned int csi_lanes; enum atomisp_input_format csi_fmt; enum atomisp_bayer_order csi_bayer; + + bool clock_on; bool v1p8_on; bool v2p8_on; bool v1p2_on; bool v2p8_vcm_on; + int v1p8_gpio; + int v2p8_gpio; + u8 pwm_i2c_addr; /* For PMIC AXP */ @@ -90,9 +96,9 @@ struct gmin_subdev { static struct gmin_subdev gmin_subdevs[MAX_SUBDEVS]; /* ACPI HIDs for the PMICs that could be used by this driver */ -#define PMIC_ACPI_AXP "INT33F4:00" /* XPower AXP288 PMIC */ -#define PMIC_ACPI_TI "INT33F5:00" /* Dollar Cove TI PMIC */ -#define PMIC_ACPI_CRYSTALCOVE "INT33FD:00" /* Crystal Cove PMIC */ +#define PMIC_ACPI_AXP "INT33F4" /* XPower AXP288 PMIC */ +#define PMIC_ACPI_TI "INT33F5" /* Dollar Cove TI PMIC */ +#define PMIC_ACPI_CRYSTALCOVE "INT33FD" /* Crystal Cove PMIC */ #define PMIC_PLATFORM_TI "intel_soc_pmic_chtdc_ti" @@ -105,7 +111,7 @@ static enum { } pmic_id; static const char *pmic_name[] = { - [PMIC_UNSET] = "unset", + [PMIC_UNSET] = "ACPI device PM", [PMIC_REGULATOR] = "regulator driver", [PMIC_AXP] = "XPower AXP288 PMIC", [PMIC_TI] = "Dollar Cove TI PMIC", @@ -119,24 +125,6 @@ static const struct atomisp_platform_data pdata = { .subdevs = pdata_subdevs, }; -/* - * Something of a hack. The ECS E7 board drives camera 2.8v from an - * external regulator instead of the PMIC. There's a gmin_CamV2P8 - * config variable that specifies the GPIO to handle this particular - * case, but this needs a broader architecture for handling camera - * power. - */ -enum { V2P8_GPIO_UNSET = -2, V2P8_GPIO_NONE = -1 }; -static int v2p8_gpio = V2P8_GPIO_UNSET; - -/* - * Something of a hack. The CHT RVP board drives camera 1.8v from an - * external regulator instead of the PMIC just like ECS E7 board, see the - * comments above. - */ -enum { V1P8_GPIO_UNSET = -2, V1P8_GPIO_NONE = -1 }; -static int v1p8_gpio = V1P8_GPIO_UNSET; - static LIST_HEAD(vcm_devices); static DEFINE_MUTEX(vcm_lock); @@ -199,6 +187,8 @@ int atomisp_register_i2c_module(struct v4l2_subdev *subdev, * gmin_subdev struct is already initialized for us. */ gs = find_gmin_subdev(subdev); + if (!gs) + return -ENODEV; pdata.subdevs[i].type = type; pdata.subdevs[i].port = gs->csi_port; @@ -294,6 +284,7 @@ static struct gmin_cfg_var mrd7_vars[] = { {"INT33F8:00_CsiFmt", "13"}, {"INT33F8:00_CsiBayer", "0"}, {"INT33F8:00_CamClk", "0"}, + {"INT33F9:00_CamType", "1"}, {"INT33F9:00_CsiPort", "0"}, {"INT33F9:00_CsiLanes", "1"}, @@ -309,6 +300,7 @@ static struct gmin_cfg_var ecs7_vars[] = { {"INT33BE:00_CsiFmt", "13"}, {"INT33BE:00_CsiBayer", "2"}, {"INT33BE:00_CamClk", "0"}, + {"INT33F0:00_CsiPort", "0"}, {"INT33F0:00_CsiLanes", "1"}, {"INT33F0:00_CsiFmt", "13"}, @@ -322,6 +314,7 @@ static struct gmin_cfg_var i8880_vars[] = { {"XXOV2680:00_CsiPort", "1"}, {"XXOV2680:00_CsiLanes", "1"}, {"XXOV2680:00_CamClk", "0"}, + {"XXGC0310:00_CsiPort", "0"}, {"XXGC0310:00_CsiLanes", "1"}, {"XXGC0310:00_CamClk", "1"}, @@ -381,34 +374,27 @@ static const guid_t atomisp_dsm_guid = GUID_INIT(0xdc2f6c4f, 0x045b, 0x4f1d, #define GMIN_PMC_CLK_NAME 14 /* "pmc_plt_clk_[0..5]" */ static char gmin_pmc_clk_name[GMIN_PMC_CLK_NAME]; -static int gmin_i2c_match_one(struct device *dev, const void *data) -{ - const char *name = data; - struct i2c_client *client; - - if (dev->type != &i2c_client_type) - return 0; - - client = to_i2c_client(dev); - - return (!strcmp(name, client->name)); -} - static struct i2c_client *gmin_i2c_dev_exists(struct device *dev, char *name, struct i2c_client **client) { + struct acpi_device *adev; struct device *d; - while ((d = bus_find_device(&i2c_bus_type, NULL, name, - gmin_i2c_match_one))) { - *client = to_i2c_client(d); - dev_dbg(dev, "found '%s' at address 0x%02x, adapter %d\n", - (*client)->name, (*client)->addr, - (*client)->adapter->nr); - return *client; - } + adev = acpi_dev_get_first_match_dev(name, NULL, -1); + if (!adev) + return NULL; - return NULL; + d = bus_find_device_by_acpi_dev(&i2c_bus_type, adev); + acpi_dev_put(adev); + if (!d) + return NULL; + + *client = i2c_verify_client(d); + put_device(d); + + dev_dbg(dev, "found '%s' at address 0x%02x, adapter %d\n", + (*client)->name, (*client)->addr, (*client)->adapter->nr); + return *client; } static int gmin_i2c_write(struct device *dev, u16 i2c_addr, u8 reg, @@ -427,94 +413,222 @@ static int gmin_i2c_write(struct device *dev, u16 i2c_addr, u8 reg, "I2C write, addr: 0x%02x, reg: 0x%02x, value: 0x%02x, mask: 0x%02x\n", i2c_addr, reg, value, mask); - ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_addr, reg, - value, mask); - - if (ret == -EOPNOTSUPP) { + ret = intel_soc_pmic_exec_mipi_pmic_seq_element(i2c_addr, reg, value, mask); + if (ret == -EOPNOTSUPP) dev_err(dev, "ACPI didn't mapped the OpRegion needed to access I2C address 0x%02x.\n" - "Need to compile the Kernel using CONFIG_*_PMIC_OPREGION settings\n", + "Need to compile the kernel using CONFIG_*_PMIC_OPREGION settings\n", i2c_addr); - return ret; - } return ret; } -static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) +static int atomisp_get_acpi_power(struct device *dev) { - struct i2c_client *power = NULL, *client = v4l2_get_subdevdata(subdev); - struct acpi_device *adev; - acpi_handle handle; - struct device *dev; - int i, ret; + char name[5]; + struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; + struct acpi_buffer b_name = { sizeof(name), name }; + union acpi_object *package, *element; + acpi_handle handle = ACPI_HANDLE(dev); + acpi_handle rhandle; + acpi_status status; + int clock_num = -1; + int i; - if (!client) - return NULL; + status = acpi_evaluate_object(handle, "_PR0", NULL, &buffer); + if (!ACPI_SUCCESS(status)) + return -1; - dev = &client->dev; + package = buffer.pointer; - handle = ACPI_HANDLE(dev); + if (!buffer.length || !package + || package->type != ACPI_TYPE_PACKAGE + || !package->package.count) + goto fail; - // FIXME: may need to release resources allocated by acpi_bus_get_device() - if (!handle || acpi_bus_get_device(handle, &adev)) { - dev_err(dev, "Error could not get ACPI device\n"); - return NULL; - } + for (i = 0; i < package->package.count; i++) { + element = &package->package.elements[i]; - dev_info(&client->dev, "%s: ACPI detected it on bus ID=%s, HID=%s\n", - __func__, acpi_device_bid(adev), acpi_device_hid(adev)); + if (element->type != ACPI_TYPE_LOCAL_REFERENCE) + continue; - if (!pmic_id) { - if (gmin_i2c_dev_exists(dev, PMIC_ACPI_TI, &power)) - pmic_id = PMIC_TI; - else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_AXP, &power)) - pmic_id = PMIC_AXP; - else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_CRYSTALCOVE, &power)) - pmic_id = PMIC_CRYSTALCOVE; - else - pmic_id = PMIC_REGULATOR; + rhandle = element->reference.handle; + if (!rhandle) + goto fail; + + acpi_get_name(rhandle, ACPI_SINGLE_NAME, &b_name); + + dev_dbg(dev, "Found PM resource '%s'\n", name); + if (strlen(name) == 4 && !strncmp(name, "CLK", 3)) { + if (name[3] >= '0' && name[3] <= '4') + clock_num = name[3] - '0'; +#if 0 + /* + * We could abort here, but let's parse all resources, + * as this is helpful for debugging purposes + */ + if (clock_num >= 0) + break; +#endif + } } - for (i = 0; i < MAX_SUBDEVS && gmin_subdevs[i].subdev; i++) - ; - if (i >= MAX_SUBDEVS) - return NULL; +fail: + ACPI_FREE(buffer.pointer); + + return clock_num; +} + +static u8 gmin_get_pmic_id_and_addr(struct device *dev) +{ + struct i2c_client *power; + static u8 pmic_i2c_addr; + + if (pmic_id) + return pmic_i2c_addr; + + if (gmin_i2c_dev_exists(dev, PMIC_ACPI_TI, &power)) + pmic_id = PMIC_TI; + else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_AXP, &power)) + pmic_id = PMIC_AXP; + else if (gmin_i2c_dev_exists(dev, PMIC_ACPI_CRYSTALCOVE, &power)) + pmic_id = PMIC_CRYSTALCOVE; + else + pmic_id = PMIC_REGULATOR; + + pmic_i2c_addr = power ? power->addr : 0; + return pmic_i2c_addr; +} + +static int gmin_detect_pmic(struct v4l2_subdev *subdev) +{ + struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct device *dev = &client->dev; + u8 pmic_i2c_addr; + + pmic_i2c_addr = gmin_get_pmic_id_and_addr(dev); + dev_info(dev, "gmin: power management provided via %s (i2c addr 0x%02x)\n", + pmic_name[pmic_id], pmic_i2c_addr); + return pmic_i2c_addr; +} + +static int gmin_subdev_add(struct gmin_subdev *gs) +{ + struct i2c_client *client = v4l2_get_subdevdata(gs->subdev); + struct device *dev = &client->dev; + struct acpi_device *adev = ACPI_COMPANION(dev); + int ret, clock_num = -1; + + dev_info(dev, "%s: ACPI path is %pfw\n", __func__, dev_fwnode(dev)); + + /*WA:CHT requires XTAL clock as PLL is not stable.*/ + gs->clock_src = gmin_get_var_int(dev, false, "ClkSrc", + VLV2_CLK_PLL_19P2MHZ); + + gs->csi_port = gmin_get_var_int(dev, false, "CsiPort", 0); + gs->csi_lanes = gmin_get_var_int(dev, false, "CsiLanes", 1); + + gs->gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW); + if (IS_ERR(gs->gpio0)) + gs->gpio0 = NULL; + else + dev_info(dev, "will handle gpio0 via ACPI\n"); + + gs->gpio1 = gpiod_get_index(dev, NULL, 1, GPIOD_OUT_LOW); + if (IS_ERR(gs->gpio1)) + gs->gpio1 = NULL; + else + dev_info(dev, "will handle gpio1 via ACPI\n"); + + /* + * Those are used only when there is an external regulator apart + * from the PMIC that would be providing power supply, like on the + * two cases below: + * + * The ECS E7 board drives camera 2.8v from an external regulator + * instead of the PMIC. There's a gmin_CamV2P8 config variable + * that specifies the GPIO to handle this particular case, + * but this needs a broader architecture for handling camera power. + * + * The CHT RVP board drives camera 1.8v from an* external regulator + * instead of the PMIC just like ECS E7 board. + */ - if (power) { - gmin_subdevs[i].pwm_i2c_addr = power->addr; + gs->v1p8_gpio = gmin_get_var_int(dev, true, "V1P8GPIO", -1); + gs->v2p8_gpio = gmin_get_var_int(dev, true, "V2P8GPIO", -1); + + /* + * FIXME: + * + * The ACPI handling code checks for the _PR? tables in order to + * know what is required to switch the device from power state + * D0 (_PR0) up to D3COLD (_PR3). + * + * The adev->flags.power_manageable is set to true if the device + * has a _PR0 table, which can be checked by calling + * acpi_device_power_manageable(adev). + * + * However, this only says that the device can be set to power off + * mode. + * + * At least on the DSDT tables we've seen so far, there's no _PR3, + * nor _PS3 (which would have a somewhat similar effect). + * So, using ACPI for power management won't work, except if adding + * an ACPI override logic somewhere. + * + * So, at least for the existing devices we know, the check below + * will always be false. + */ + if (acpi_device_can_wakeup(adev) && + acpi_device_can_poweroff(adev)) { dev_info(dev, - "gmin: power management provided via %s (i2c addr 0x%02x)\n", - pmic_name[pmic_id], power->addr); - } else { - dev_info(dev, "gmin: power management provided via %s\n", - pmic_name[pmic_id]); + "gmin: power management provided via device PM\n"); + return 0; } - gmin_subdevs[i].subdev = subdev; - gmin_subdevs[i].clock_num = gmin_get_var_int(dev, false, "CamClk", 0); - /*WA:CHT requires XTAL clock as PLL is not stable.*/ - gmin_subdevs[i].clock_src = gmin_get_var_int(dev, false, "ClkSrc", - VLV2_CLK_PLL_19P2MHZ); - gmin_subdevs[i].csi_port = gmin_get_var_int(dev, false, "CsiPort", 0); - gmin_subdevs[i].csi_lanes = gmin_get_var_int(dev, false, "CsiLanes", 1); + /* + * The code below is here due to backward compatibility with devices + * whose ACPI BIOS may not contain everything that would be needed + * in order to set clocks and do power management. + */ + + /* + * According with : + * https://github.com/projectceladon/hardware-intel-kernelflinger/blob/master/doc/fastboot.md + * + * The "CamClk" EFI var is set via fastboot on some Android devices, + * and seems to contain the number of the clock used to feed the + * sensor. + * + * On systems with a proper ACPI table, this is given via the _PR0 + * power resource table. The logic below should first check if there + * is a power resource already, falling back to the EFI vars detection + * otherwise. + */ - /* get PMC clock with clock framework */ - snprintf(gmin_pmc_clk_name, - sizeof(gmin_pmc_clk_name), - "%s_%d", "pmc_plt_clk", gmin_subdevs[i].clock_num); + /* Try first to use ACPI to get the clock resource */ + if (acpi_device_power_manageable(adev)) + clock_num = atomisp_get_acpi_power(dev); - gmin_subdevs[i].pmc_clk = devm_clk_get(dev, gmin_pmc_clk_name); - if (IS_ERR(gmin_subdevs[i].pmc_clk)) { - ret = PTR_ERR(gmin_subdevs[i].pmc_clk); + /* Fall-back use EFI and/or DMI match */ + if (clock_num < 0) + clock_num = gmin_get_var_int(dev, false, "CamClk", 0); - dev_err(dev, - "Failed to get clk from %s : %d\n", - gmin_pmc_clk_name, - ret); + if (clock_num < 0 || clock_num > MAX_CLK_COUNT) { + dev_err(dev, "Invalid clock number\n"); + return -EINVAL; + } - return NULL; + snprintf(gmin_pmc_clk_name, sizeof(gmin_pmc_clk_name), + "%s_%d", "pmc_plt_clk", clock_num); + + gs->pmc_clk = devm_clk_get(dev, gmin_pmc_clk_name); + if (IS_ERR(gs->pmc_clk)) { + ret = PTR_ERR(gs->pmc_clk); + dev_err(dev, "Failed to get clk from %s: %d\n", gmin_pmc_clk_name, ret); + return ret; } + dev_info(dev, "Will use CLK%d (%s)\n", clock_num, gmin_pmc_clk_name); /* * The firmware might enable the clock at @@ -526,25 +640,17 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) * to disable a clock that has not been enabled, * we need to enable the clock first. */ - ret = clk_prepare_enable(gmin_subdevs[i].pmc_clk); + ret = clk_prepare_enable(gs->pmc_clk); if (!ret) - clk_disable_unprepare(gmin_subdevs[i].pmc_clk); - - gmin_subdevs[i].gpio0 = gpiod_get_index(dev, NULL, 0, GPIOD_OUT_LOW); - if (IS_ERR(gmin_subdevs[i].gpio0)) - gmin_subdevs[i].gpio0 = NULL; - - gmin_subdevs[i].gpio1 = gpiod_get_index(dev, NULL, 1, GPIOD_OUT_LOW); - if (IS_ERR(gmin_subdevs[i].gpio1)) - gmin_subdevs[i].gpio1 = NULL; + clk_disable_unprepare(gs->pmc_clk); switch (pmic_id) { case PMIC_REGULATOR: - gmin_subdevs[i].v1p8_reg = regulator_get(dev, "V1P8SX"); - gmin_subdevs[i].v2p8_reg = regulator_get(dev, "V2P8SX"); + gs->v1p8_reg = regulator_get(dev, "V1P8SX"); + gs->v2p8_reg = regulator_get(dev, "V2P8SX"); - gmin_subdevs[i].v1p2_reg = regulator_get(dev, "V1P2A"); - gmin_subdevs[i].v2p8_vcm_reg = regulator_get(dev, "VPROG4B"); + gs->v1p2_reg = regulator_get(dev, "V1P2A"); + gs->v2p8_vcm_reg = regulator_get(dev, "VPROG4B"); /* Note: ideally we would initialize v[12]p8_on to the * output of regulator_is_enabled(), but sadly that @@ -556,32 +662,31 @@ static struct gmin_subdev *gmin_subdev_add(struct v4l2_subdev *subdev) break; case PMIC_AXP: - gmin_subdevs[i].eldo1_1p8v = gmin_get_var_int(dev, false, - "eldo1_1p8v", - ELDO1_1P8V); - gmin_subdevs[i].eldo1_sel_reg = gmin_get_var_int(dev, false, - "eldo1_sel_reg", - ELDO1_SEL_REG); - gmin_subdevs[i].eldo1_ctrl_shift = gmin_get_var_int(dev, false, - "eldo1_ctrl_shift", - ELDO1_CTRL_SHIFT); - gmin_subdevs[i].eldo2_1p8v = gmin_get_var_int(dev, false, - "eldo2_1p8v", - ELDO2_1P8V); - gmin_subdevs[i].eldo2_sel_reg = gmin_get_var_int(dev, false, - "eldo2_sel_reg", - ELDO2_SEL_REG); - gmin_subdevs[i].eldo2_ctrl_shift = gmin_get_var_int(dev, false, - "eldo2_ctrl_shift", - ELDO2_CTRL_SHIFT); - gmin_subdevs[i].pwm_i2c_addr = power->addr; + gs->eldo1_1p8v = gmin_get_var_int(dev, false, + "eldo1_1p8v", + ELDO1_1P8V); + gs->eldo1_sel_reg = gmin_get_var_int(dev, false, + "eldo1_sel_reg", + ELDO1_SEL_REG); + gs->eldo1_ctrl_shift = gmin_get_var_int(dev, false, + "eldo1_ctrl_shift", + ELDO1_CTRL_SHIFT); + gs->eldo2_1p8v = gmin_get_var_int(dev, false, + "eldo2_1p8v", + ELDO2_1P8V); + gs->eldo2_sel_reg = gmin_get_var_int(dev, false, + "eldo2_sel_reg", + ELDO2_SEL_REG); + gs->eldo2_ctrl_shift = gmin_get_var_int(dev, false, + "eldo2_ctrl_shift", + ELDO2_CTRL_SHIFT); break; default: break; } - return &gmin_subdevs[i]; + return 0; } static struct gmin_subdev *find_gmin_subdev(struct v4l2_subdev *subdev) @@ -591,7 +696,17 @@ static struct gmin_subdev *find_gmin_subdev(struct v4l2_subdev *subdev) for (i = 0; i < MAX_SUBDEVS; i++) if (gmin_subdevs[i].subdev == subdev) return &gmin_subdevs[i]; - return gmin_subdev_add(subdev); + return NULL; +} + +static struct gmin_subdev *find_free_gmin_subdev_slot(void) +{ + unsigned int i; + + for (i = 0; i < MAX_SUBDEVS; i++) + if (gmin_subdevs[i].subdev == NULL) + return &gmin_subdevs[i]; + return NULL; } static int axp_regulator_set(struct device *dev, struct gmin_subdev *gs, @@ -700,32 +815,24 @@ static int gmin_v1p8_ctrl(struct v4l2_subdev *subdev, int on) { struct gmin_subdev *gs = find_gmin_subdev(subdev); int ret; - struct device *dev; - struct i2c_client *client = v4l2_get_subdevdata(subdev); int value; - dev = &client->dev; - - if (v1p8_gpio == V1P8_GPIO_UNSET) { - v1p8_gpio = gmin_get_var_int(dev, true, - "V1P8GPIO", V1P8_GPIO_NONE); - if (v1p8_gpio != V1P8_GPIO_NONE) { - pr_info("atomisp_gmin_platform: 1.8v power on GPIO %d\n", - v1p8_gpio); - ret = gpio_request(v1p8_gpio, "camera_v1p8_en"); - if (!ret) - ret = gpio_direction_output(v1p8_gpio, 0); - if (ret) - pr_err("V1P8 GPIO initialization failed\n"); - } + if (gs->v1p8_gpio >= 0) { + pr_info("atomisp_gmin_platform: 1.8v power on GPIO %d\n", + gs->v1p8_gpio); + ret = gpio_request(gs->v1p8_gpio, "camera_v1p8_en"); + if (!ret) + ret = gpio_direction_output(gs->v1p8_gpio, 0); + if (ret) + pr_err("V1P8 GPIO initialization failed\n"); } if (!gs || gs->v1p8_on == on) return 0; gs->v1p8_on = on; - if (v1p8_gpio >= 0) - gpio_set_value(v1p8_gpio, on); + if (gs->v1p8_gpio >= 0) + gpio_set_value(gs->v1p8_gpio, on); if (gs->v1p8_reg) { regulator_set_voltage(gs->v1p8_reg, 1800000, 1800000); @@ -762,32 +869,24 @@ static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on) { struct gmin_subdev *gs = find_gmin_subdev(subdev); int ret; - struct device *dev; - struct i2c_client *client = v4l2_get_subdevdata(subdev); int value; - dev = &client->dev; - - if (v2p8_gpio == V2P8_GPIO_UNSET) { - v2p8_gpio = gmin_get_var_int(dev, true, - "V2P8GPIO", V2P8_GPIO_NONE); - if (v2p8_gpio != V2P8_GPIO_NONE) { - pr_info("atomisp_gmin_platform: 2.8v power on GPIO %d\n", - v2p8_gpio); - ret = gpio_request(v2p8_gpio, "camera_v2p8"); - if (!ret) - ret = gpio_direction_output(v2p8_gpio, 0); - if (ret) - pr_err("V2P8 GPIO initialization failed\n"); - } + if (gs->v2p8_gpio >= 0) { + pr_info("atomisp_gmin_platform: 2.8v power on GPIO %d\n", + gs->v2p8_gpio); + ret = gpio_request(gs->v2p8_gpio, "camera_v2p8"); + if (!ret) + ret = gpio_direction_output(gs->v2p8_gpio, 0); + if (ret) + pr_err("V2P8 GPIO initialization failed\n"); } if (!gs || gs->v2p8_on == on) return 0; gs->v2p8_on = on; - if (v2p8_gpio >= 0) - gpio_set_value(v2p8_gpio, on); + if (gs->v2p8_gpio >= 0) + gpio_set_value(gs->v2p8_gpio, on); if (gs->v2p8_reg) { regulator_set_voltage(gs->v2p8_reg, 2900000, 2900000); @@ -819,6 +918,37 @@ static int gmin_v2p8_ctrl(struct v4l2_subdev *subdev, int on) return -EINVAL; } +static int gmin_acpi_pm_ctrl(struct v4l2_subdev *subdev, int on) +{ + int ret = 0; + struct gmin_subdev *gs = find_gmin_subdev(subdev); + struct i2c_client *client = v4l2_get_subdevdata(subdev); + struct acpi_device *adev = ACPI_COMPANION(&client->dev); + + /* Use the ACPI power management to control it */ + on = !!on; + if (gs->clock_on == on) + return 0; + + dev_dbg(subdev->dev, "Setting power state to %s\n", + on ? "on" : "off"); + + if (on) + ret = acpi_device_set_power(adev, + ACPI_STATE_D0); + else + ret = acpi_device_set_power(adev, + ACPI_STATE_D3_COLD); + + if (!ret) + gs->clock_on = on; + else + dev_err(subdev->dev, "Couldn't set power state to %s\n", + on ? "on" : "off"); + + return ret; +} + static int gmin_flisclk_ctrl(struct v4l2_subdev *subdev, int on) { int ret = 0; @@ -884,7 +1014,7 @@ static struct camera_vcm_control *gmin_get_vcm_ctrl(struct v4l2_subdev *subdev, return NULL; } -static struct camera_sensor_platform_data gmin_plat = { +static struct camera_sensor_platform_data pmic_gmin_plat = { .gpio0_ctrl = gmin_gpio0_ctrl, .gpio1_ctrl = gmin_gpio1_ctrl, .v1p8_ctrl = gmin_v1p8_ctrl, @@ -895,17 +1025,36 @@ static struct camera_sensor_platform_data gmin_plat = { .get_vcm_ctrl = gmin_get_vcm_ctrl, }; +static struct camera_sensor_platform_data acpi_gmin_plat = { + .gpio0_ctrl = gmin_gpio0_ctrl, + .gpio1_ctrl = gmin_gpio1_ctrl, + .v1p8_ctrl = gmin_acpi_pm_ctrl, + .v2p8_ctrl = gmin_acpi_pm_ctrl, + .v1p2_ctrl = gmin_acpi_pm_ctrl, + .flisclk_ctrl = gmin_acpi_pm_ctrl, + .csi_cfg = gmin_csi_cfg, + .get_vcm_ctrl = gmin_get_vcm_ctrl, +}; + struct camera_sensor_platform_data *gmin_camera_platform_data( struct v4l2_subdev *subdev, enum atomisp_input_format csi_format, enum atomisp_bayer_order csi_bayer) { - struct gmin_subdev *gs = find_gmin_subdev(subdev); + u8 pmic_i2c_addr = gmin_detect_pmic(subdev); + struct gmin_subdev *gs; + gs = find_free_gmin_subdev_slot(); + gs->subdev = subdev; gs->csi_fmt = csi_format; gs->csi_bayer = csi_bayer; + gs->pwm_i2c_addr = pmic_i2c_addr; - return &gmin_plat; + gmin_subdev_add(gs); + if (gs->pmc_clk) + return &pmic_gmin_plat; + else + return &acpi_gmin_plat; } EXPORT_SYMBOL_GPL(gmin_camera_platform_data); @@ -957,12 +1106,28 @@ static int gmin_get_config_dsm_var(struct device *dev, union acpi_object *obj, *cur = NULL; int i; + /* + * The data reported by "CamClk" seems to be either 0 or 1 at the + * _DSM table. + * + * At the ACPI tables we looked so far, this is not related to the + * actual clock source for the sensor, which is given by the + * _PR0 ACPI table. So, ignore it, as otherwise this will be + * set to a wrong value. + */ + if (!strcmp(var, "CamClk")) + return -EINVAL; + obj = acpi_evaluate_dsm(handle, &atomisp_dsm_guid, 0, 0, NULL); if (!obj) { dev_info_once(dev, "Didn't find ACPI _DSM table.\n"); return -EINVAL; } + /* Return on unexpected object type */ + if (obj->type != ACPI_TYPE_PACKAGE) + return -EINVAL; + #if 0 /* Just for debugging purposes */ for (i = 0; i < obj->package.count; i++) { union acpi_object *cur = &obj->package.elements[i]; @@ -1155,10 +1320,10 @@ EXPORT_SYMBOL_GPL(camera_sensor_csi); * trying. The driver itself does direct calls to the PUNIT to manage * ISP power. */ -static void isp_pm_cap_fixup(struct pci_dev *dev) +static void isp_pm_cap_fixup(struct pci_dev *pdev) { - dev_info(&dev->dev, "Disabling PCI power management on camera ISP\n"); - dev->pm_cap = 0; + dev_info(&pdev->dev, "Disabling PCI power management on camera ISP\n"); + pdev->pm_cap = 0; } DECLARE_PCI_FIXUP_FINAL(PCI_VENDOR_ID_INTEL, 0x0f38, isp_pm_cap_fixup); diff --git a/drivers/staging/media/atomisp/pci/atomisp_internal.h b/drivers/staging/media/atomisp/pci/atomisp_internal.h index ff3becd41110..c01db10bb735 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_internal.h +++ b/drivers/staging/media/atomisp/pci/atomisp_internal.h @@ -216,12 +216,12 @@ struct atomisp_sw_contex { * ci device struct */ struct atomisp_device { - struct pci_dev *pdev; struct device *dev; struct v4l2_device v4l2_dev; struct media_device media_dev; struct atomisp_platform_data *pdata; void *mmu_l1_base; + void __iomem *base; const struct firmware *firmware; struct pm_qos_request pm_qos; diff --git a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c index 9404a678fa6f..f8d616f08b51 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_ioctl.c +++ b/drivers/staging/media/atomisp/pci/atomisp_ioctl.c @@ -549,8 +549,7 @@ static int atomisp_querycap(struct file *file, void *fh, strscpy(cap->driver, DRIVER, sizeof(cap->driver)); strscpy(cap->card, CARD, sizeof(cap->card)); - snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", - pci_name(isp->pdev)); + snprintf(cap->bus_info, sizeof(cap->bus_info), "PCI:%s", dev_name(isp->dev)); return 0; } @@ -1635,6 +1634,7 @@ static int atomisp_streamon(struct file *file, void *fh, struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); struct atomisp_sub_device *asd = pipe->asd; struct atomisp_device *isp = video_get_drvdata(vdev); + struct pci_dev *pdev = to_pci_dev(isp->dev); enum ia_css_pipe_id css_pipe_id; unsigned int sensor_start_stream; unsigned int wdt_duration = ATOMISP_ISP_TIMEOUT_DURATION; @@ -1844,9 +1844,8 @@ start_sensor: /* Enable the CSI interface on ANN B0/K0 */ if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { - pci_write_config_word(isp->pdev, MRFLD_PCI_CSI_CONTROL, - isp->saved_regs.csi_control | - MRFLD_PCI_CSI_CONTROL_CSI_READY); + pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, + isp->saved_regs.csi_control | MRFLD_PCI_CSI_CONTROL_CSI_READY); } /* stream on the sensor */ @@ -1891,6 +1890,7 @@ int __atomisp_streamoff(struct file *file, void *fh, enum v4l2_buf_type type) { struct video_device *vdev = video_devdata(file); struct atomisp_device *isp = video_get_drvdata(vdev); + struct pci_dev *pdev = to_pci_dev(isp->dev); struct atomisp_video_pipe *pipe = atomisp_to_video_pipe(vdev); struct atomisp_sub_device *asd = pipe->asd; struct atomisp_video_pipe *capture_pipe = NULL; @@ -2076,9 +2076,8 @@ stopsensor: /* Disable the CSI interface on ANN B0/K0 */ if (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0)) { - pci_write_config_word(isp->pdev, MRFLD_PCI_CSI_CONTROL, - isp->saved_regs.csi_control & - ~MRFLD_PCI_CSI_CONTROL_CSI_READY); + pci_write_config_word(pdev, MRFLD_PCI_CSI_CONTROL, + isp->saved_regs.csi_control & ~MRFLD_PCI_CSI_CONTROL_CSI_READY); } if (atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, false)) @@ -2111,8 +2110,8 @@ stopsensor: } /* disable PUNIT/ISP acknowlede/handshake - SRSE=3 */ - pci_write_config_dword(isp->pdev, PCI_I_CONTROL, isp->saved_regs.i_control | - MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); + pci_write_config_dword(pdev, PCI_I_CONTROL, + isp->saved_regs.i_control | MRFLD_PCI_I_CONTROL_SRSE_RESET_MASK); dev_err(isp->dev, "atomisp_reset"); atomisp_reset(isp); for (i = 0; i < isp->num_of_streams; i++) { diff --git a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c index d36809a0182c..a000a1e316f7 100644 --- a/drivers/staging/media/atomisp/pci/atomisp_v4l2.c +++ b/drivers/staging/media/atomisp/pci/atomisp_v4l2.c @@ -127,8 +127,6 @@ MODULE_PARM_DESC(pad_h, "extra data for ISP processing"); struct device *atomisp_dev; -void __iomem *atomisp_io_base; - static const struct atomisp_freq_scaling_rule dfs_rules_merr[] = { { .width = ISP_FREQ_RULE_ANY, @@ -512,30 +510,27 @@ void atomisp_acc_unregister(struct atomisp_acc_pipe *video) static int atomisp_save_iunit_reg(struct atomisp_device *isp) { - struct pci_dev *dev = isp->pdev; + struct pci_dev *pdev = to_pci_dev(isp->dev); dev_dbg(isp->dev, "%s\n", __func__); - pci_read_config_word(dev, PCI_COMMAND, &isp->saved_regs.pcicmdsts); + pci_read_config_word(pdev, PCI_COMMAND, &isp->saved_regs.pcicmdsts); /* isp->saved_regs.ispmmadr is set from the atomisp_pci_probe() */ - pci_read_config_dword(dev, PCI_MSI_CAPID, &isp->saved_regs.msicap); - pci_read_config_dword(dev, PCI_MSI_ADDR, &isp->saved_regs.msi_addr); - pci_read_config_word(dev, PCI_MSI_DATA, &isp->saved_regs.msi_data); - pci_read_config_byte(dev, PCI_INTERRUPT_LINE, &isp->saved_regs.intr); - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, - &isp->saved_regs.interrupt_control); - - pci_read_config_dword(dev, MRFLD_PCI_PMCS, - &isp->saved_regs.pmcs); + pci_read_config_dword(pdev, PCI_MSI_CAPID, &isp->saved_regs.msicap); + pci_read_config_dword(pdev, PCI_MSI_ADDR, &isp->saved_regs.msi_addr); + pci_read_config_word(pdev, PCI_MSI_DATA, &isp->saved_regs.msi_data); + pci_read_config_byte(pdev, PCI_INTERRUPT_LINE, &isp->saved_regs.intr); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &isp->saved_regs.interrupt_control); + + pci_read_config_dword(pdev, MRFLD_PCI_PMCS, &isp->saved_regs.pmcs); /* Ensure read/write combining is enabled. */ - pci_read_config_dword(dev, PCI_I_CONTROL, - &isp->saved_regs.i_control); + pci_read_config_dword(pdev, PCI_I_CONTROL, &isp->saved_regs.i_control); isp->saved_regs.i_control |= MRFLD_PCI_I_CONTROL_ENABLE_READ_COMBINING | MRFLD_PCI_I_CONTROL_ENABLE_WRITE_COMBINING; - pci_read_config_dword(dev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL, + pci_read_config_dword(pdev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL, &isp->saved_regs.csi_access_viol); - pci_read_config_dword(dev, MRFLD_PCI_CSI_RCOMP_CONTROL, + pci_read_config_dword(pdev, MRFLD_PCI_CSI_RCOMP_CONTROL, &isp->saved_regs.csi_rcomp_config); /* * Hardware bugs require setting CSI_HS_OVR_CLK_GATE_ON_UPDATE. @@ -545,65 +540,58 @@ static int atomisp_save_iunit_reg(struct atomisp_device *isp) * is missed, and IUNIT can hang. * For both issues, setting this bit is a workaround. */ - isp->saved_regs.csi_rcomp_config |= - MRFLD_PCI_CSI_HS_OVR_CLK_GATE_ON_UPDATE; - pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, + isp->saved_regs.csi_rcomp_config |= MRFLD_PCI_CSI_HS_OVR_CLK_GATE_ON_UPDATE; + pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, &isp->saved_regs.csi_afe_dly); - pci_read_config_dword(dev, MRFLD_PCI_CSI_CONTROL, + pci_read_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, &isp->saved_regs.csi_control); if (isp->media_dev.hw_revision >= (ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT)) - isp->saved_regs.csi_control |= - MRFLD_PCI_CSI_CONTROL_PARPATHEN; + isp->saved_regs.csi_control |= MRFLD_PCI_CSI_CONTROL_PARPATHEN; /* * On CHT CSI_READY bit should be enabled before stream on */ if (IS_CHT && (isp->media_dev.hw_revision >= ((ATOMISP_HW_REVISION_ISP2401 << ATOMISP_HW_REVISION_SHIFT) | ATOMISP_HW_STEPPING_B0))) - isp->saved_regs.csi_control |= - MRFLD_PCI_CSI_CONTROL_CSI_READY; - pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL, + isp->saved_regs.csi_control |= MRFLD_PCI_CSI_CONTROL_CSI_READY; + pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL, &isp->saved_regs.csi_afe_rcomp_config); - pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_HS_CONTROL, + pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_HS_CONTROL, &isp->saved_regs.csi_afe_hs_control); - pci_read_config_dword(dev, MRFLD_PCI_CSI_DEADLINE_CONTROL, + pci_read_config_dword(pdev, MRFLD_PCI_CSI_DEADLINE_CONTROL, &isp->saved_regs.csi_deadline_control); return 0; } static int __maybe_unused atomisp_restore_iunit_reg(struct atomisp_device *isp) { - struct pci_dev *dev = isp->pdev; + struct pci_dev *pdev = to_pci_dev(isp->dev); dev_dbg(isp->dev, "%s\n", __func__); - pci_write_config_word(dev, PCI_COMMAND, isp->saved_regs.pcicmdsts); - pci_write_config_dword(dev, PCI_BASE_ADDRESS_0, - isp->saved_regs.ispmmadr); - pci_write_config_dword(dev, PCI_MSI_CAPID, isp->saved_regs.msicap); - pci_write_config_dword(dev, PCI_MSI_ADDR, isp->saved_regs.msi_addr); - pci_write_config_word(dev, PCI_MSI_DATA, isp->saved_regs.msi_data); - pci_write_config_byte(dev, PCI_INTERRUPT_LINE, isp->saved_regs.intr); - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, - isp->saved_regs.interrupt_control); - pci_write_config_dword(dev, PCI_I_CONTROL, - isp->saved_regs.i_control); - - pci_write_config_dword(dev, MRFLD_PCI_PMCS, - isp->saved_regs.pmcs); - pci_write_config_dword(dev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL, + pci_write_config_word(pdev, PCI_COMMAND, isp->saved_regs.pcicmdsts); + pci_write_config_dword(pdev, PCI_BASE_ADDRESS_0, isp->saved_regs.ispmmadr); + pci_write_config_dword(pdev, PCI_MSI_CAPID, isp->saved_regs.msicap); + pci_write_config_dword(pdev, PCI_MSI_ADDR, isp->saved_regs.msi_addr); + pci_write_config_word(pdev, PCI_MSI_DATA, isp->saved_regs.msi_data); + pci_write_config_byte(pdev, PCI_INTERRUPT_LINE, isp->saved_regs.intr); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, isp->saved_regs.interrupt_control); + pci_write_config_dword(pdev, PCI_I_CONTROL, isp->saved_regs.i_control); + + pci_write_config_dword(pdev, MRFLD_PCI_PMCS, isp->saved_regs.pmcs); + pci_write_config_dword(pdev, MRFLD_PCI_CSI_ACCESS_CTRL_VIOL, isp->saved_regs.csi_access_viol); - pci_write_config_dword(dev, MRFLD_PCI_CSI_RCOMP_CONTROL, + pci_write_config_dword(pdev, MRFLD_PCI_CSI_RCOMP_CONTROL, isp->saved_regs.csi_rcomp_config); - pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, + pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, isp->saved_regs.csi_afe_dly); - pci_write_config_dword(dev, MRFLD_PCI_CSI_CONTROL, + pci_write_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, isp->saved_regs.csi_control); - pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL, + pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_RCOMP_CONTROL, isp->saved_regs.csi_afe_rcomp_config); - pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_HS_CONTROL, + pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_HS_CONTROL, isp->saved_regs.csi_afe_hs_control); - pci_write_config_dword(dev, MRFLD_PCI_CSI_DEADLINE_CONTROL, + pci_write_config_dword(pdev, MRFLD_PCI_CSI_DEADLINE_CONTROL, isp->saved_regs.csi_deadline_control); /* @@ -619,7 +607,7 @@ static int __maybe_unused atomisp_restore_iunit_reg(struct atomisp_device *isp) static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp) { - struct pci_dev *dev = isp->pdev; + struct pci_dev *pdev = to_pci_dev(isp->dev); u32 irq; unsigned long flags; @@ -635,11 +623,11 @@ static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp) * So, here we need to check if there is any pending * IRQ, if so, waiting for it to be served */ - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq); irq = irq & 1 << INTR_IIR; - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq); - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq); if (!(irq & (1 << INTR_IIR))) goto done; @@ -652,11 +640,11 @@ static int atomisp_mrfld_pre_power_down(struct atomisp_device *isp) spin_unlock_irqrestore(&isp->lock, flags); return -EAGAIN; } else { - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq); irq = irq & 1 << INTR_IIR; - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq); - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq); if (!(irq & (1 << INTR_IIR))) { atomisp_css2_hw_store_32(MRFLD_INTR_ENABLE_REG, 0x0); goto done; @@ -675,11 +663,11 @@ done: * to IIR. It could block subsequent interrupt messages. * HW sighting:4568410. */ - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq); irq &= ~(1 << INTR_IER); - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq); - atomisp_msi_irq_uninit(isp, dev); + atomisp_msi_irq_uninit(isp); atomisp_freq_scaling(isp, ATOMISP_DFS_MODE_LOW, true); spin_unlock_irqrestore(&isp->lock, flags); @@ -755,7 +743,7 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) /* Wait until ISPSSPM0 bit[25:24] shows the right value */ iosf_mbi_read(BT_MBI_UNIT_PMC, MBI_REG_READ, MRFLD_ISPSSPM0, &tmp); - tmp = (tmp & MRFLD_ISPSSPM0_ISPSSC_MASK) >> MRFLD_ISPSSPM0_ISPSSS_OFFSET; + tmp = (tmp >> MRFLD_ISPSSPM0_ISPSSS_OFFSET) & MRFLD_ISPSSPM0_ISPSSC_MASK; if (tmp == val) { trace_ipu_cstate(enable); return 0; @@ -778,15 +766,13 @@ static int atomisp_mrfld_power(struct atomisp_device *isp, bool enable) /* Workaround for pmu_nc_set_power_state not ready in MRFLD */ int atomisp_mrfld_power_down(struct atomisp_device *isp) { -// FIXME: at least with ISP2401, enabling this code causes the driver to break - return 0 && atomisp_mrfld_power(isp, false); + return atomisp_mrfld_power(isp, false); } /* Workaround for pmu_nc_set_power_state not ready in MRFLD */ int atomisp_mrfld_power_up(struct atomisp_device *isp) { -// FIXME: at least with ISP2401, enabling this code causes the driver to break - return 0 && atomisp_mrfld_power(isp, true); + return atomisp_mrfld_power(isp, true); } int atomisp_runtime_suspend(struct device *dev) @@ -902,6 +888,7 @@ static int __maybe_unused atomisp_resume(struct device *dev) int atomisp_csi_lane_config(struct atomisp_device *isp) { + struct pci_dev *pdev = to_pci_dev(isp->dev); static const struct { u8 code; u8 lanes[MRFLD_PORT_NUM]; @@ -1003,7 +990,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) return -EINVAL; } - pci_read_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, &csi_control); + pci_read_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, &csi_control); csi_control &= ~port_config_mask; csi_control |= (portconfigs[i].code << MRFLD_PORT_CONFIGCODE_SHIFT) | (portconfigs[i].lanes[0] ? 0 : (1 << MRFLD_PORT1_ENABLE_SHIFT)) @@ -1013,7 +1000,7 @@ int atomisp_csi_lane_config(struct atomisp_device *isp) | (((1 << portconfigs[i].lanes[1]) - 1) << MRFLD_PORT2_LANES_SHIFT) | (((1 << portconfigs[i].lanes[2]) - 1) << port3_lanes_shift); - pci_write_config_dword(isp->pdev, MRFLD_PCI_CSI_CONTROL, csi_control); + pci_write_config_dword(pdev, MRFLD_PCI_CSI_CONTROL, csi_control); dev_dbg(isp->dev, "%s: the portconfig is %d-%d-%d, CSI_CONTROL is 0x%08X\n", @@ -1440,8 +1427,7 @@ atomisp_load_firmware(struct atomisp_device *isp) * Check for flags the driver was compiled with against the PCI * device. Always returns true on other than ISP 2400. */ -static bool is_valid_device(struct pci_dev *dev, - const struct pci_device_id *id) +static bool is_valid_device(struct pci_dev *pdev, const struct pci_device_id *id) { unsigned int a0_max_id = 0; const char *name; @@ -1465,14 +1451,14 @@ static bool is_valid_device(struct pci_dev *dev, name = "Cherrytrail"; break; default: - dev_err(&dev->dev, "%s: unknown device ID %x04:%x04\n", + dev_err(&pdev->dev, "%s: unknown device ID %x04:%x04\n", product, id->vendor, id->device); return false; } - if (dev->revision <= ATOMISP_PCI_REV_BYT_A0_MAX) { - dev_err(&dev->dev, "%s revision %d is not unsupported\n", - name, dev->revision); + if (pdev->revision <= ATOMISP_PCI_REV_BYT_A0_MAX) { + dev_err(&pdev->dev, "%s revision %d is not unsupported\n", + name, pdev->revision); return false; } @@ -1483,22 +1469,20 @@ static bool is_valid_device(struct pci_dev *dev, #if defined(ISP2400) if (IS_ISP2401) { - dev_err(&dev->dev, "Support for %s (ISP2401) was disabled at compile time\n", + dev_err(&pdev->dev, "Support for %s (ISP2401) was disabled at compile time\n", name); return false; } #else if (!IS_ISP2401) { - dev_err(&dev->dev, "Support for %s (ISP2400) was disabled at compile time\n", + dev_err(&pdev->dev, "Support for %s (ISP2400) was disabled at compile time\n", name); return false; } #endif - dev_info(&dev->dev, "Detected %s version %d (ISP240%c) on %s\n", - name, dev->revision, - IS_ISP2401 ? '1' : '0', - product); + dev_info(&pdev->dev, "Detected %s version %d (ISP240%c) on %s\n", + name, pdev->revision, IS_ISP2401 ? '1' : '0', product); return true; } @@ -1538,66 +1522,60 @@ alloc_fail: #define ATOM_ISP_PCI_BAR 0 -static int atomisp_pci_probe(struct pci_dev *dev, - const struct pci_device_id *id) +static int atomisp_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) { const struct atomisp_platform_data *pdata; struct atomisp_device *isp; unsigned int start; - void __iomem *base; int err, val; u32 irq; - if (!is_valid_device(dev, id)) + if (!is_valid_device(pdev, id)) return -ENODEV; /* Pointer to struct device. */ - atomisp_dev = &dev->dev; + atomisp_dev = &pdev->dev; pdata = atomisp_get_platform_data(); if (!pdata) - dev_warn(&dev->dev, "no platform data available\n"); + dev_warn(&pdev->dev, "no platform data available\n"); - err = pcim_enable_device(dev); + err = pcim_enable_device(pdev); if (err) { - dev_err(&dev->dev, "Failed to enable CI ISP device (%d)\n", - err); + dev_err(&pdev->dev, "Failed to enable CI ISP device (%d)\n", err); return err; } - start = pci_resource_start(dev, ATOM_ISP_PCI_BAR); - dev_dbg(&dev->dev, "start: 0x%x\n", start); + start = pci_resource_start(pdev, ATOM_ISP_PCI_BAR); + dev_dbg(&pdev->dev, "start: 0x%x\n", start); - err = pcim_iomap_regions(dev, 1 << ATOM_ISP_PCI_BAR, pci_name(dev)); + err = pcim_iomap_regions(pdev, 1 << ATOM_ISP_PCI_BAR, pci_name(pdev)); if (err) { - dev_err(&dev->dev, "Failed to I/O memory remapping (%d)\n", - err); + dev_err(&pdev->dev, "Failed to I/O memory remapping (%d)\n", err); goto ioremap_fail; } - base = pcim_iomap_table(dev)[ATOM_ISP_PCI_BAR]; - dev_dbg(&dev->dev, "base: %p\n", base); - - atomisp_io_base = base; - - dev_dbg(&dev->dev, "atomisp_io_base: %p\n", atomisp_io_base); - - isp = devm_kzalloc(&dev->dev, sizeof(struct atomisp_device), GFP_KERNEL); + isp = devm_kzalloc(&pdev->dev, sizeof(*isp), GFP_KERNEL); if (!isp) { err = -ENOMEM; goto atomisp_dev_alloc_fail; } - isp->pdev = dev; - isp->dev = &dev->dev; + + isp->dev = &pdev->dev; + isp->base = pcim_iomap_table(pdev)[ATOM_ISP_PCI_BAR]; isp->sw_contex.power_state = ATOM_ISP_POWER_UP; isp->saved_regs.ispmmadr = start; + dev_dbg(&pdev->dev, "atomisp mmio base: %p\n", isp->base); + rt_mutex_init(&isp->mutex); mutex_init(&isp->streamoff_mutex); spin_lock_init(&isp->lock); /* This is not a true PCI device on SoC, so the delay is not needed. */ - isp->pdev->d3_delay = 0; + pdev->d3_delay = 0; + + pci_set_drvdata(pdev, isp); switch (id->device & ATOMISP_PCI_DEVICE_SOC_MASK) { case ATOMISP_PCI_DEVICE_SOC_MRFLD: @@ -1648,15 +1626,14 @@ static int atomisp_pci_probe(struct pci_dev *dev, * have specs yet for exactly how it varies. Default to * BYT-CR but let provisioning set it via EFI variable */ - isp->hpll_freq = gmin_get_var_int(&dev->dev, false, "HpllFreq", - HPLL_FREQ_2000MHZ); + isp->hpll_freq = gmin_get_var_int(&pdev->dev, false, "HpllFreq", HPLL_FREQ_2000MHZ); /* * for BYT/CHT we are put isp into D3cold to avoid pci registers access * in power off. Set d3cold_delay to 0 since default 100ms is not * necessary. */ - isp->pdev->d3cold_delay = 0; + pdev->d3cold_delay = 0; break; case ATOMISP_PCI_DEVICE_SOC_ANN: isp->media_dev.hw_revision = ( @@ -1666,7 +1643,7 @@ static int atomisp_pci_probe(struct pci_dev *dev, ATOMISP_HW_REVISION_ISP2401_LEGACY #endif << ATOMISP_HW_REVISION_SHIFT); - isp->media_dev.hw_revision |= isp->pdev->revision < 2 ? + isp->media_dev.hw_revision |= pdev->revision < 2 ? ATOMISP_HW_STEPPING_A0 : ATOMISP_HW_STEPPING_B0; isp->dfs = &dfs_config_merr; isp->hpll_freq = HPLL_FREQ_1600MHZ; @@ -1679,13 +1656,13 @@ static int atomisp_pci_probe(struct pci_dev *dev, ATOMISP_HW_REVISION_ISP2401_LEGACY #endif << ATOMISP_HW_REVISION_SHIFT); - isp->media_dev.hw_revision |= isp->pdev->revision < 2 ? + isp->media_dev.hw_revision |= pdev->revision < 2 ? ATOMISP_HW_STEPPING_A0 : ATOMISP_HW_STEPPING_B0; isp->dfs = &dfs_config_cht; - isp->pdev->d3cold_delay = 0; + pdev->d3cold_delay = 0; - iosf_mbi_read(CCK_PORT, MBI_REG_READ, CCK_FUSE_REG_0, &val); + iosf_mbi_read(BT_MBI_UNIT_CCK, MBI_REG_READ, CCK_FUSE_REG_0, &val); switch (val & CCK_FUSE_HPLL_FREQ_MASK) { case 0x00: isp->hpll_freq = HPLL_FREQ_800MHZ; @@ -1698,18 +1675,16 @@ static int atomisp_pci_probe(struct pci_dev *dev, break; default: isp->hpll_freq = HPLL_FREQ_1600MHZ; - dev_warn(isp->dev, - "read HPLL from cck failed. Default to 1600 MHz.\n"); + dev_warn(&pdev->dev, "read HPLL from cck failed. Default to 1600 MHz.\n"); } break; default: - dev_err(&dev->dev, "un-supported IUNIT device\n"); + dev_err(&pdev->dev, "un-supported IUNIT device\n"); err = -ENODEV; goto atomisp_dev_alloc_fail; } - dev_info(&dev->dev, "ISP HPLL frequency base = %d MHz\n", - isp->hpll_freq); + dev_info(&pdev->dev, "ISP HPLL frequency base = %d MHz\n", isp->hpll_freq); isp->max_isr_latency = ATOMISP_MAX_ISR_LATENCY; @@ -1718,30 +1693,28 @@ static int atomisp_pci_probe(struct pci_dev *dev, isp->firmware = atomisp_load_firmware(isp); if (!isp->firmware) { err = -ENOENT; - dev_dbg(&dev->dev, "Firmware load failed\n"); + dev_dbg(&pdev->dev, "Firmware load failed\n"); goto load_fw_fail; } - err = sh_css_check_firmware_version(isp->dev, - isp->firmware->data); + err = sh_css_check_firmware_version(isp->dev, isp->firmware->data); if (err) { - dev_dbg(&dev->dev, "Firmware version check failed\n"); + dev_dbg(&pdev->dev, "Firmware version check failed\n"); goto fw_validation_fail; } } else { - dev_info(&dev->dev, "Firmware load will be deferred\n"); + dev_info(&pdev->dev, "Firmware load will be deferred\n"); } - pci_set_master(dev); - pci_set_drvdata(dev, isp); + pci_set_master(pdev); - err = pci_enable_msi(dev); + err = pci_enable_msi(pdev); if (err) { - dev_err(&dev->dev, "Failed to enable msi (%d)\n", err); + dev_err(&pdev->dev, "Failed to enable msi (%d)\n", err); goto enable_msi_fail; } - atomisp_msi_irq_init(isp, dev); + atomisp_msi_irq_init(isp); cpu_latency_qos_add_request(&isp->pm_qos, PM_QOS_DEFAULT_VALUE); @@ -1762,8 +1735,7 @@ static int atomisp_pci_probe(struct pci_dev *dev, * Workaround for imbalance data eye issue which is observed * on TNG B0. */ - pci_read_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, - &csi_afe_trim); + pci_read_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, &csi_afe_trim); csi_afe_trim &= ~((MRFLD_PCI_CSI_HSRXCLKTRIM_MASK << MRFLD_PCI_CSI1_HSRXCLKTRIM_SHIFT) | (MRFLD_PCI_CSI_HSRXCLKTRIM_MASK << @@ -1776,20 +1748,18 @@ static int atomisp_pci_probe(struct pci_dev *dev, MRFLD_PCI_CSI2_HSRXCLKTRIM_SHIFT) | (MRFLD_PCI_CSI3_HSRXCLKTRIM << MRFLD_PCI_CSI3_HSRXCLKTRIM_SHIFT); - pci_write_config_dword(dev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, - csi_afe_trim); + pci_write_config_dword(pdev, MRFLD_PCI_CSI_AFE_TRIM_CONTROL, csi_afe_trim); } err = atomisp_initialize_modules(isp); if (err < 0) { - dev_err(&dev->dev, "atomisp_initialize_modules (%d)\n", err); + dev_err(&pdev->dev, "atomisp_initialize_modules (%d)\n", err); goto initialize_modules_fail; } err = atomisp_register_entities(isp); if (err < 0) { - dev_err(&dev->dev, "atomisp_register_entities failed (%d)\n", - err); + dev_err(&pdev->dev, "atomisp_register_entities failed (%d)\n", err); goto register_entities_fail; } err = atomisp_create_pads_links(isp); @@ -1802,24 +1772,24 @@ static int atomisp_pci_probe(struct pci_dev *dev, /* save the iunit context only once after all the values are init'ed. */ atomisp_save_iunit_reg(isp); - pm_runtime_put_noidle(&dev->dev); - pm_runtime_allow(&dev->dev); + pm_runtime_put_noidle(&pdev->dev); + pm_runtime_allow(&pdev->dev); hmm_init_mem_stat(repool_pgnr, dypool_enable, dypool_pgnr); err = hmm_pool_register(repool_pgnr, HMM_POOL_TYPE_RESERVED); if (err) { - dev_err(&dev->dev, "Failed to register reserved memory pool.\n"); + dev_err(&pdev->dev, "Failed to register reserved memory pool.\n"); goto hmm_pool_fail; } /* Init ISP memory management */ hmm_init(); - err = devm_request_threaded_irq(&dev->dev, dev->irq, + err = devm_request_threaded_irq(&pdev->dev, pdev->irq, atomisp_isr, atomisp_isr_thread, IRQF_SHARED, "isp_irq", isp); if (err) { - dev_err(&dev->dev, "Failed to request irq (%d)\n", err); + dev_err(&pdev->dev, "Failed to request irq (%d)\n", err); goto request_irq_fail; } @@ -1827,23 +1797,23 @@ static int atomisp_pci_probe(struct pci_dev *dev, if (!defer_fw_load) { err = atomisp_css_load_firmware(isp); if (err) { - dev_err(&dev->dev, "Failed to init css.\n"); + dev_err(&pdev->dev, "Failed to init css.\n"); goto css_init_fail; } } else { - dev_dbg(&dev->dev, "Skip css init.\n"); + dev_dbg(&pdev->dev, "Skip css init.\n"); } /* Clear FW image from memory */ release_firmware(isp->firmware); isp->firmware = NULL; isp->css_env.isp_css_fw.data = NULL; - atomisp_drvfs_init(&dev->driver->driver, isp); + atomisp_drvfs_init(isp); return 0; css_init_fail: - devm_free_irq(&dev->dev, dev->irq, isp); + devm_free_irq(&pdev->dev, pdev->irq, isp); request_irq_fail: hmm_cleanup(); hmm_pool_unregister(HMM_POOL_TYPE_RESERVED); @@ -1856,8 +1826,8 @@ register_entities_fail: atomisp_uninitialize_modules(isp); initialize_modules_fail: cpu_latency_qos_remove_request(&isp->pm_qos); - atomisp_msi_irq_uninit(isp, dev); - pci_disable_msi(dev); + atomisp_msi_irq_uninit(isp); + pci_disable_msi(pdev); enable_msi_fail: fw_validation_fail: release_firmware(isp->firmware); @@ -1869,35 +1839,34 @@ load_fw_fail: * The following lines have been copied from atomisp suspend path */ - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq); irq = irq & 1 << INTR_IIR; - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq); - pci_read_config_dword(dev, PCI_INTERRUPT_CTRL, &irq); + pci_read_config_dword(pdev, PCI_INTERRUPT_CTRL, &irq); irq &= ~(1 << INTR_IER); - pci_write_config_dword(dev, PCI_INTERRUPT_CTRL, irq); + pci_write_config_dword(pdev, PCI_INTERRUPT_CTRL, irq); - atomisp_msi_irq_uninit(isp, dev); + atomisp_msi_irq_uninit(isp); atomisp_ospm_dphy_down(isp); /* Address later when we worry about the ...field chips */ if (IS_ENABLED(CONFIG_PM) && atomisp_mrfld_power_down(isp)) - dev_err(&dev->dev, "Failed to switch off ISP\n"); + dev_err(&pdev->dev, "Failed to switch off ISP\n"); atomisp_dev_alloc_fail: - pcim_iounmap_regions(dev, 1 << ATOM_ISP_PCI_BAR); + pcim_iounmap_regions(pdev, 1 << ATOM_ISP_PCI_BAR); ioremap_fail: return err; } -static void atomisp_pci_remove(struct pci_dev *dev) +static void atomisp_pci_remove(struct pci_dev *pdev) { - struct atomisp_device *isp = (struct atomisp_device *) - pci_get_drvdata(dev); + struct atomisp_device *isp = pci_get_drvdata(pdev); - dev_info(&dev->dev, "Removing atomisp driver\n"); + dev_info(&pdev->dev, "Removing atomisp driver\n"); atomisp_drvfs_exit(); @@ -1906,11 +1875,11 @@ static void atomisp_pci_remove(struct pci_dev *dev) ia_css_unload_firmware(); hmm_cleanup(); - pm_runtime_forbid(&dev->dev); - pm_runtime_get_noresume(&dev->dev); + pm_runtime_forbid(&pdev->dev); + pm_runtime_get_noresume(&pdev->dev); cpu_latency_qos_remove_request(&isp->pm_qos); - atomisp_msi_irq_uninit(isp, dev); + atomisp_msi_irq_uninit(isp); atomisp_unregister_entities(isp); destroy_workqueue(isp->wdt_work_queue); diff --git a/drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c b/drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c index cf02737cf8d4..a9c881631f4a 100644 --- a/drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c +++ b/drivers/staging/media/atomisp/pci/base/refcount/src/refcount.c @@ -48,7 +48,7 @@ static struct ia_css_refcount_entry *refcount_find_entry(ia_css_ptr ptr, return NULL; if (!myrefcount.items) { ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, - "refcount_find_entry(): Ref count not initialized!\n"); + "%s(): Ref count not initialized!\n", __func__); return NULL; } @@ -73,12 +73,12 @@ int ia_css_refcount_init(uint32_t size) if (size == 0) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_init(): Size of 0 for Ref count init!\n"); + "%s(): Size of 0 for Ref count init!\n", __func__); return -EINVAL; } if (myrefcount.items) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_init(): Ref count is already initialized\n"); + "%s(): Ref count is already initialized\n", __func__); return -EINVAL; } myrefcount.items = @@ -99,7 +99,7 @@ void ia_css_refcount_uninit(void) u32 i; ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_uninit() entry\n"); + "%s() entry\n", __func__); for (i = 0; i < myrefcount.size; i++) { /* driver verifier tool has issues with &arr[i] and prefers arr + i; as these are actually equivalent @@ -120,7 +120,7 @@ void ia_css_refcount_uninit(void) myrefcount.items = NULL; myrefcount.size = 0; ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_uninit() leave\n"); + "%s() leave\n", __func__); } ia_css_ptr ia_css_refcount_increment(s32 id, ia_css_ptr ptr) @@ -133,7 +133,7 @@ ia_css_ptr ia_css_refcount_increment(s32 id, ia_css_ptr ptr) entry = refcount_find_entry(ptr, false); ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_increment(%x) 0x%x\n", id, ptr); + "%s(%x) 0x%x\n", __func__, id, ptr); if (!entry) { entry = refcount_find_entry(ptr, true); @@ -145,7 +145,7 @@ ia_css_ptr ia_css_refcount_increment(s32 id, ia_css_ptr ptr) if (entry->id != id) { ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, - "ia_css_refcount_increment(): Ref count IDS do not match!\n"); + "%s(): Ref count IDS do not match!\n", __func__); return mmgr_NULL; } @@ -165,7 +165,7 @@ bool ia_css_refcount_decrement(s32 id, ia_css_ptr ptr) struct ia_css_refcount_entry *entry; ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_decrement(%x) 0x%x\n", id, ptr); + "%s(%x) 0x%x\n", __func__, id, ptr); if (ptr == mmgr_NULL) return false; @@ -175,7 +175,7 @@ bool ia_css_refcount_decrement(s32 id, ia_css_ptr ptr) if (entry) { if (entry->id != id) { ia_css_debug_dtrace(IA_CSS_DEBUG_ERROR, - "ia_css_refcount_decrement(): Ref count IDS do not match!\n"); + "%s(): Ref count IDS do not match!\n", __func__); return false; } if (entry->count > 0) { @@ -225,8 +225,8 @@ void ia_css_refcount_clear(s32 id, clear_func clear_func_ptr) u32 count = 0; assert(clear_func_ptr); - ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "ia_css_refcount_clear(%x)\n", - id); + ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, "%s(%x)\n", + __func__, id); for (i = 0; i < myrefcount.size; i++) { /* driver verifier tool has issues with &arr[i] @@ -236,14 +236,14 @@ void ia_css_refcount_clear(s32 id, clear_func clear_func_ptr) entry = myrefcount.items + i; if ((entry->data != mmgr_NULL) && (entry->id == id)) { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_clear: %x: 0x%x\n", + "%s: %x: 0x%x\n", __func__, id, entry->data); if (clear_func_ptr) { /* clear using provided function */ clear_func_ptr(entry->data); } else { ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_clear: using hmm_free: no clear_func\n"); + "%s: using hmm_free: no clear_func\n", __func__); hmm_free(entry->data); } @@ -260,7 +260,7 @@ void ia_css_refcount_clear(s32 id, clear_func clear_func_ptr) } } ia_css_debug_dtrace(IA_CSS_DEBUG_TRACE, - "ia_css_refcount_clear(%x): cleared %d\n", id, + "%s(%x): cleared %d\n", __func__, id, count); } diff --git a/drivers/staging/media/atomisp/pci/hive_types.h b/drivers/staging/media/atomisp/pci/hive_types.h index addda9b81d7b..4b8a679fb672 100644 --- a/drivers/staging/media/atomisp/pci/hive_types.h +++ b/drivers/staging/media/atomisp/pci/hive_types.h @@ -52,32 +52,14 @@ typedef unsigned short hive_uint16; typedef unsigned int hive_uint32; typedef unsigned long long hive_uint64; -/* by default assume 32 bit master port (both data and address) */ -#ifndef HRT_DATA_WIDTH -#define HRT_DATA_WIDTH 32 -#endif -#ifndef HRT_ADDRESS_WIDTH -#define HRT_ADDRESS_WIDTH 32 -#endif - +#define HRT_DATA_WIDTH 32 +#define HRT_ADDRESS_WIDTH 64 #define HRT_DATA_BYTES (HRT_DATA_WIDTH / 8) #define HRT_ADDRESS_BYTES (HRT_ADDRESS_WIDTH / 8) +#define SIZEOF_HRT_REG (HRT_DATA_WIDTH >> 3) -#if HRT_DATA_WIDTH == 64 -typedef hive_uint64 hrt_data; -#elif HRT_DATA_WIDTH == 32 typedef hive_uint32 hrt_data; -#else -#error data width not supported -#endif - -#if HRT_ADDRESS_WIDTH == 64 typedef hive_uint64 hrt_address; -#elif HRT_ADDRESS_WIDTH == 32 -typedef hive_uint32 hrt_address; -#else -#error adddres width not supported -#endif /* use 64 bit addresses in simulation, where possible */ typedef hive_uint64 hive_sim_address; diff --git a/drivers/staging/media/atomisp/pci/hmm/hmm.c b/drivers/staging/media/atomisp/pci/hmm/hmm.c index 42fef1779862..2bd39b4939f1 100644 --- a/drivers/staging/media/atomisp/pci/hmm/hmm.c +++ b/drivers/staging/media/atomisp/pci/hmm/hmm.c @@ -735,11 +735,11 @@ ia_css_ptr hmm_host_vaddr_to_hrt_vaddr(const void *ptr) void hmm_show_mem_stat(const char *func, const int line) { - trace_printk("tol_cnt=%d usr_size=%d res_size=%d res_cnt=%d sys_size=%d dyc_thr=%d dyc_size=%d.\n", - hmm_mem_stat.tol_cnt, - hmm_mem_stat.usr_size, hmm_mem_stat.res_size, - hmm_mem_stat.res_cnt, hmm_mem_stat.sys_size, - hmm_mem_stat.dyc_thr, hmm_mem_stat.dyc_size); + pr_info("tol_cnt=%d usr_size=%d res_size=%d res_cnt=%d sys_size=%d dyc_thr=%d dyc_size=%d.\n", + hmm_mem_stat.tol_cnt, + hmm_mem_stat.usr_size, hmm_mem_stat.res_size, + hmm_mem_stat.res_cnt, hmm_mem_stat.sys_size, + hmm_mem_stat.dyc_thr, hmm_mem_stat.dyc_size); } void hmm_init_mem_stat(int res_pgnr, int dyc_en, int dyc_pgnr) diff --git a/drivers/staging/media/atomisp/pci/isp2400_system_global.h b/drivers/staging/media/atomisp/pci/isp2400_system_global.h index d87ddf1d2fe9..74fff465e8e8 100644 --- a/drivers/staging/media/atomisp/pci/isp2400_system_global.h +++ b/drivers/staging/media/atomisp/pci/isp2400_system_global.h @@ -13,306 +13,4 @@ * more details. */ -#ifndef __SYSTEM_GLOBAL_H_INCLUDED__ -#define __SYSTEM_GLOBAL_H_INCLUDED__ - -#include <hive_isp_css_defs.h> -#include <type_support.h> - -/* - * The longest allowed (uninteruptible) bus transfer, does not - * take stalling into account - */ -#define HIVE_ISP_MAX_BURST_LENGTH 1024 - -/* - * Maximum allowed burst length in words for the ISP DMA - */ -#define ISP_DMA_MAX_BURST_LENGTH 128 - -/* - * Create a list of HAS and IS properties that defines the system - * - * The configuration assumes the following - * - The system is hetereogeneous; Multiple cells and devices classes - * - The cell and device instances are homogeneous, each device type - * belongs to the same class - * - Device instances supporting a subset of the class capabilities are - * allowed - * - * We could manage different device classes through the enumerated - * lists (C) or the use of classes (C++), but that is presently not - * fully supported - * - * N.B. the 3 input formatters are of 2 different classess - */ - #define USE_INPUT_SYSTEM_VERSION_2 - -#define HAS_MMU_VERSION_2 -#define HAS_DMA_VERSION_2 -#define HAS_GDC_VERSION_2 -#define HAS_VAMEM_VERSION_2 -#define HAS_HMEM_VERSION_1 -#define HAS_BAMEM_VERSION_2 -#define HAS_IRQ_VERSION_2 -#define HAS_IRQ_MAP_VERSION_2 -#define HAS_INPUT_FORMATTER_VERSION_2 -/* 2401: HAS_INPUT_SYSTEM_VERSION_2401 */ -#define HAS_INPUT_SYSTEM_VERSION_2 -#define HAS_BUFFERED_SENSOR -#define HAS_FIFO_MONITORS_VERSION_2 -/* #define HAS_GP_REGS_VERSION_2 */ -#define HAS_GP_DEVICE_VERSION_2 -#define HAS_GPIO_VERSION_1 -#define HAS_TIMED_CTRL_VERSION_1 -#define HAS_RX_VERSION_2 - -#define DMA_DDR_TO_VAMEM_WORKAROUND -#define DMA_DDR_TO_HMEM_WORKAROUND - -/* - * Semi global. "HRT" is accessible from SP, but the HRT types do not fully apply - */ -#define HRT_VADDRESS_WIDTH 32 -//#define HRT_ADDRESS_WIDTH 64 /* Surprise, this is a local property*/ -#define HRT_DATA_WIDTH 32 - -#define SIZEOF_HRT_REG (HRT_DATA_WIDTH >> 3) -#define HIVE_ISP_CTRL_DATA_BYTES (HIVE_ISP_CTRL_DATA_WIDTH / 8) - -/* The main bus connecting all devices */ -#define HRT_BUS_WIDTH HIVE_ISP_CTRL_DATA_WIDTH -#define HRT_BUS_BYTES HIVE_ISP_CTRL_DATA_BYTES - -/* per-frame parameter handling support */ -#define SH_CSS_ENABLE_PER_FRAME_PARAMS - -typedef u32 hrt_bus_align_t; - -/* - * Enumerate the devices, device access through the API is by ID, through the DLI by address - * The enumerator terminators are used to size the wiring arrays and as an exception value. - */ -typedef enum { - DDR0_ID = 0, - N_DDR_ID -} ddr_ID_t; - -typedef enum { - ISP0_ID = 0, - N_ISP_ID -} isp_ID_t; - -typedef enum { - SP0_ID = 0, - N_SP_ID -} sp_ID_t; - -typedef enum { - MMU0_ID = 0, - MMU1_ID, - N_MMU_ID -} mmu_ID_t; - -typedef enum { - DMA0_ID = 0, - N_DMA_ID -} dma_ID_t; - -typedef enum { - GDC0_ID = 0, - GDC1_ID, - N_GDC_ID -} gdc_ID_t; - -#define N_GDC_ID_CPP 2 // this extra define is needed because we want to use it also in the preprocessor, and that doesn't work with enums. - -typedef enum { - VAMEM0_ID = 0, - VAMEM1_ID, - VAMEM2_ID, - N_VAMEM_ID -} vamem_ID_t; - -typedef enum { - BAMEM0_ID = 0, - N_BAMEM_ID -} bamem_ID_t; - -typedef enum { - HMEM0_ID = 0, - N_HMEM_ID -} hmem_ID_t; - -/* -typedef enum { - IRQ0_ID = 0, - N_IRQ_ID -} irq_ID_t; -*/ - -typedef enum { - IRQ0_ID = 0, // GP IRQ block - IRQ1_ID, // Input formatter - IRQ2_ID, // input system - IRQ3_ID, // input selector - N_IRQ_ID -} irq_ID_t; - -typedef enum { - FIFO_MONITOR0_ID = 0, - N_FIFO_MONITOR_ID -} fifo_monitor_ID_t; - -/* - * Deprecated: Since all gp_reg instances are different - * and put in the address maps of other devices we cannot - * enumerate them as that assumes the instrances are the - * same. - * - * We define a single GP_DEVICE containing all gp_regs - * w.r.t. a single base address - * -typedef enum { - GP_REGS0_ID = 0, - N_GP_REGS_ID -} gp_regs_ID_t; - */ -typedef enum { - GP_DEVICE0_ID = 0, - N_GP_DEVICE_ID -} gp_device_ID_t; - -typedef enum { - GP_TIMER0_ID = 0, - GP_TIMER1_ID, - GP_TIMER2_ID, - GP_TIMER3_ID, - GP_TIMER4_ID, - GP_TIMER5_ID, - GP_TIMER6_ID, - GP_TIMER7_ID, - N_GP_TIMER_ID -} gp_timer_ID_t; - -typedef enum { - GPIO0_ID = 0, - N_GPIO_ID -} gpio_ID_t; - -typedef enum { - TIMED_CTRL0_ID = 0, - N_TIMED_CTRL_ID -} timed_ctrl_ID_t; - -typedef enum { - INPUT_FORMATTER0_ID = 0, - INPUT_FORMATTER1_ID, - INPUT_FORMATTER2_ID, - INPUT_FORMATTER3_ID, - N_INPUT_FORMATTER_ID -} input_formatter_ID_t; - -/* The IF RST is outside the IF */ -#define INPUT_FORMATTER0_SRST_OFFSET 0x0824 -#define INPUT_FORMATTER1_SRST_OFFSET 0x0624 -#define INPUT_FORMATTER2_SRST_OFFSET 0x0424 -#define INPUT_FORMATTER3_SRST_OFFSET 0x0224 - -#define INPUT_FORMATTER0_SRST_MASK 0x0001 -#define INPUT_FORMATTER1_SRST_MASK 0x0002 -#define INPUT_FORMATTER2_SRST_MASK 0x0004 -#define INPUT_FORMATTER3_SRST_MASK 0x0008 - -typedef enum { - INPUT_SYSTEM0_ID = 0, - N_INPUT_SYSTEM_ID -} input_system_ID_t; - -typedef enum { - RX0_ID = 0, - N_RX_ID -} rx_ID_t; - -enum mipi_port_id { - MIPI_PORT0_ID = 0, - MIPI_PORT1_ID, - MIPI_PORT2_ID, - N_MIPI_PORT_ID -}; - -#define N_RX_CHANNEL_ID 4 - -/* Generic port enumeration with an internal port type ID */ -typedef enum { - CSI_PORT0_ID = 0, - CSI_PORT1_ID, - CSI_PORT2_ID, - TPG_PORT0_ID, - PRBS_PORT0_ID, - FIFO_PORT0_ID, - MEMORY_PORT0_ID, - N_INPUT_PORT_ID -} input_port_ID_t; - -typedef enum { - CAPTURE_UNIT0_ID = 0, - CAPTURE_UNIT1_ID, - CAPTURE_UNIT2_ID, - ACQUISITION_UNIT0_ID, - DMA_UNIT0_ID, - CTRL_UNIT0_ID, - GPREGS_UNIT0_ID, - FIFO_UNIT0_ID, - IRQ_UNIT0_ID, - N_SUB_SYSTEM_ID -} sub_system_ID_t; - -#define N_CAPTURE_UNIT_ID 3 -#define N_ACQUISITION_UNIT_ID 1 -#define N_CTRL_UNIT_ID 1 - -enum ia_css_isp_memories { - IA_CSS_ISP_PMEM0 = 0, - IA_CSS_ISP_DMEM0, - IA_CSS_ISP_VMEM0, - IA_CSS_ISP_VAMEM0, - IA_CSS_ISP_VAMEM1, - IA_CSS_ISP_VAMEM2, - IA_CSS_ISP_HMEM0, - IA_CSS_SP_DMEM0, - IA_CSS_DDR, - N_IA_CSS_MEMORIES -}; - -#define IA_CSS_NUM_MEMORIES 9 -/* For driver compatibility */ -#define N_IA_CSS_ISP_MEMORIES IA_CSS_NUM_MEMORIES -#define IA_CSS_NUM_ISP_MEMORIES IA_CSS_NUM_MEMORIES - -#if 0 -typedef enum { - dev_chn, /* device channels, external resource */ - ext_mem, /* external memories */ - int_mem, /* internal memories */ - int_chn /* internal channels, user defined */ -} resource_type_t; - -/* if this enum is extended with other memory resources, pls also extend the function resource_to_memptr() */ -typedef enum { - vied_nci_dev_chn_dma_ext0, - int_mem_vmem0, - int_mem_dmem0 -} resource_id_t; - -/* enum listing the different memories within a program group. - This enum is used in the mem_ptr_t type */ -typedef enum { - buf_mem_invalid = 0, - buf_mem_vmem_prog0, - buf_mem_dmem_prog0 -} buf_mem_t; - -#endif -#endif /* __SYSTEM_GLOBAL_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/isp2400_system_local.h b/drivers/staging/media/atomisp/pci/isp2400_system_local.h deleted file mode 100644 index 675b8e5bdcc1..000000000000 --- a/drivers/staging/media/atomisp/pci/isp2400_system_local.h +++ /dev/null @@ -1,321 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2010-2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef __SYSTEM_LOCAL_H_INCLUDED__ -#define __SYSTEM_LOCAL_H_INCLUDED__ - -#ifdef HRT_ISP_CSS_CUSTOM_HOST -#ifndef HRT_USE_VIR_ADDRS -#define HRT_USE_VIR_ADDRS -#endif -#endif - -#include "system_global.h" - -/* HRT assumes 32 by default (see Linux/include/hive_types.h), overrule it in case it is different */ -#undef HRT_ADDRESS_WIDTH -#define HRT_ADDRESS_WIDTH 64 /* Surprise, this is a local property */ - -/* This interface is deprecated */ -#include "hive_types.h" - -/* - * Cell specific address maps - */ -#if HRT_ADDRESS_WIDTH == 64 - -#define GP_FIFO_BASE ((hrt_address)0x0000000000090104) /* This is NOT a base address */ - -/* DDR */ -static const hrt_address DDR_BASE[N_DDR_ID] = { - (hrt_address)0x0000000120000000ULL -}; - -/* ISP */ -static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = { - (hrt_address)0x0000000000020000ULL -}; - -static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = { - (hrt_address)0x0000000000200000ULL -}; - -static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = { - (hrt_address)0x0000000000100000ULL -}; - -static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = { - (hrt_address)0x00000000001C0000ULL, - (hrt_address)0x00000000001D0000ULL, - (hrt_address)0x00000000001E0000ULL -}; - -static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = { - (hrt_address)0x00000000001F0000ULL -}; - -/* SP */ -static const hrt_address SP_CTRL_BASE[N_SP_ID] = { - (hrt_address)0x0000000000010000ULL -}; - -static const hrt_address SP_DMEM_BASE[N_SP_ID] = { - (hrt_address)0x0000000000300000ULL -}; - -static const hrt_address SP_PMEM_BASE[N_SP_ID] = { - (hrt_address)0x00000000000B0000ULL -}; - -/* MMU */ -/* - * MMU0_ID: The data MMU - * MMU1_ID: The icache MMU - */ -static const hrt_address MMU_BASE[N_MMU_ID] = { - (hrt_address)0x0000000000070000ULL, - (hrt_address)0x00000000000A0000ULL -}; - -/* DMA */ -static const hrt_address DMA_BASE[N_DMA_ID] = { - (hrt_address)0x0000000000040000ULL -}; - -/* IRQ */ -static const hrt_address IRQ_BASE[N_IRQ_ID] = { - (hrt_address)0x0000000000000500ULL, - (hrt_address)0x0000000000030A00ULL, - (hrt_address)0x000000000008C000ULL, - (hrt_address)0x0000000000090200ULL -}; - -/* - (hrt_address)0x0000000000000500ULL}; - */ - -/* GDC */ -static const hrt_address GDC_BASE[N_GDC_ID] = { - (hrt_address)0x0000000000050000ULL, - (hrt_address)0x0000000000060000ULL -}; - -/* FIFO_MONITOR (not a subset of GP_DEVICE) */ -static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = { - (hrt_address)0x0000000000000000ULL -}; - -/* -static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = { - (hrt_address)0x0000000000000000ULL}; - -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - (hrt_address)0x0000000000090000ULL}; -*/ - -/* GP_DEVICE (single base for all separate GP_REG instances) */ -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - (hrt_address)0x0000000000000000ULL -}; - -/*GP TIMER , all timer registers are inter-twined, - * so, having multiple base addresses for - * different timers does not help*/ -static const hrt_address GP_TIMER_BASE = - (hrt_address)0x0000000000000600ULL; -/* GPIO */ -static const hrt_address GPIO_BASE[N_GPIO_ID] = { - (hrt_address)0x0000000000000400ULL -}; - -/* TIMED_CTRL */ -static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = { - (hrt_address)0x0000000000000100ULL -}; - -/* INPUT_FORMATTER */ -static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = { - (hrt_address)0x0000000000030000ULL, - (hrt_address)0x0000000000030200ULL, - (hrt_address)0x0000000000030400ULL, - (hrt_address)0x0000000000030600ULL -}; /* memcpy() */ - -/* INPUT_SYSTEM */ -static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = { - (hrt_address)0x0000000000080000ULL -}; - -/* (hrt_address)0x0000000000081000ULL, */ /* capture A */ -/* (hrt_address)0x0000000000082000ULL, */ /* capture B */ -/* (hrt_address)0x0000000000083000ULL, */ /* capture C */ -/* (hrt_address)0x0000000000084000ULL, */ /* Acquisition */ -/* (hrt_address)0x0000000000085000ULL, */ /* DMA */ -/* (hrt_address)0x0000000000089000ULL, */ /* ctrl */ -/* (hrt_address)0x000000000008A000ULL, */ /* GP regs */ -/* (hrt_address)0x000000000008B000ULL, */ /* FIFO */ -/* (hrt_address)0x000000000008C000ULL, */ /* IRQ */ - -/* RX, the MIPI lane control regs start at offset 0 */ -static const hrt_address RX_BASE[N_RX_ID] = { - (hrt_address)0x0000000000080100ULL -}; - -#elif HRT_ADDRESS_WIDTH == 32 - -#define GP_FIFO_BASE ((hrt_address)0x00090104) /* This is NOT a base address */ - -/* DDR : Attention, this value not defined in 32-bit */ -static const hrt_address DDR_BASE[N_DDR_ID] = { - (hrt_address)0x00000000UL -}; - -/* ISP */ -static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = { - (hrt_address)0x00020000UL -}; - -static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = { - (hrt_address)0x00200000UL -}; - -static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = { - (hrt_address)0x100000UL -}; - -static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = { - (hrt_address)0xffffffffUL, - (hrt_address)0xffffffffUL, - (hrt_address)0xffffffffUL -}; - -static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = { - (hrt_address)0xffffffffUL -}; - -/* SP */ -static const hrt_address SP_CTRL_BASE[N_SP_ID] = { - (hrt_address)0x00010000UL -}; - -static const hrt_address SP_DMEM_BASE[N_SP_ID] = { - (hrt_address)0x00300000UL -}; - -static const hrt_address SP_PMEM_BASE[N_SP_ID] = { - (hrt_address)0x000B0000UL -}; - -/* MMU */ -/* - * MMU0_ID: The data MMU - * MMU1_ID: The icache MMU - */ -static const hrt_address MMU_BASE[N_MMU_ID] = { - (hrt_address)0x00070000UL, - (hrt_address)0x000A0000UL -}; - -/* DMA */ -static const hrt_address DMA_BASE[N_DMA_ID] = { - (hrt_address)0x00040000UL -}; - -/* IRQ */ -static const hrt_address IRQ_BASE[N_IRQ_ID] = { - (hrt_address)0x00000500UL, - (hrt_address)0x00030A00UL, - (hrt_address)0x0008C000UL, - (hrt_address)0x00090200UL -}; - -/* - (hrt_address)0x00000500UL}; - */ - -/* GDC */ -static const hrt_address GDC_BASE[N_GDC_ID] = { - (hrt_address)0x00050000UL, - (hrt_address)0x00060000UL -}; - -/* FIFO_MONITOR (not a subset of GP_DEVICE) */ -static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = { - (hrt_address)0x00000000UL -}; - -/* -static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = { - (hrt_address)0x00000000UL}; - -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - (hrt_address)0x00090000UL}; -*/ - -/* GP_DEVICE (single base for all separate GP_REG instances) */ -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - (hrt_address)0x00000000UL -}; - -/*GP TIMER , all timer registers are inter-twined, - * so, having multiple base addresses for - * different timers does not help*/ -static const hrt_address GP_TIMER_BASE = - (hrt_address)0x00000600UL; - -/* GPIO */ -static const hrt_address GPIO_BASE[N_GPIO_ID] = { - (hrt_address)0x00000400UL -}; - -/* TIMED_CTRL */ -static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = { - (hrt_address)0x00000100UL -}; - -/* INPUT_FORMATTER */ -static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = { - (hrt_address)0x00030000UL, - (hrt_address)0x00030200UL, - (hrt_address)0x00030400UL -}; - -/* (hrt_address)0x00030600UL, */ /* memcpy() */ - -/* INPUT_SYSTEM */ -static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = { - (hrt_address)0x00080000UL -}; - -/* (hrt_address)0x00081000UL, */ /* capture A */ -/* (hrt_address)0x00082000UL, */ /* capture B */ -/* (hrt_address)0x00083000UL, */ /* capture C */ -/* (hrt_address)0x00084000UL, */ /* Acquisition */ -/* (hrt_address)0x00085000UL, */ /* DMA */ -/* (hrt_address)0x00089000UL, */ /* ctrl */ -/* (hrt_address)0x0008A000UL, */ /* GP regs */ -/* (hrt_address)0x0008B000UL, */ /* FIFO */ -/* (hrt_address)0x0008C000UL, */ /* IRQ */ - -/* RX, the MIPI lane control regs start at offset 0 */ -static const hrt_address RX_BASE[N_RX_ID] = { - (hrt_address)0x00080100UL -}; - -#else -#error "system_local.h: HRT_ADDRESS_WIDTH must be one of {32,64}" -#endif - -#endif /* __SYSTEM_LOCAL_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/isp2401_system_global.h b/drivers/staging/media/atomisp/pci/isp2401_system_global.h index 8bb2a956f983..27cd2535bab8 100644 --- a/drivers/staging/media/atomisp/pci/isp2401_system_global.h +++ b/drivers/staging/media/atomisp/pci/isp2401_system_global.h @@ -13,415 +13,7 @@ * more details. */ -#ifndef __SYSTEM_GLOBAL_H_INCLUDED__ -#define __SYSTEM_GLOBAL_H_INCLUDED__ - -#include <hive_isp_css_defs.h> -#include <type_support.h> - -/* - * The longest allowed (uninteruptible) bus transfer, does not - * take stalling into account - */ -#define HIVE_ISP_MAX_BURST_LENGTH 1024 - -/* - * Maximum allowed burst length in words for the ISP DMA - * This value is set to 2 to prevent the ISP DMA from blocking - * the bus for too long; as the input system can only buffer - * 2 lines on Moorefield and Cherrytrail, the input system buffers - * may overflow if blocked for too long (BZ 2726). - */ -#define ISP_DMA_MAX_BURST_LENGTH 2 - -/* - * Create a list of HAS and IS properties that defines the system - * - * The configuration assumes the following - * - The system is hetereogeneous; Multiple cells and devices classes - * - The cell and device instances are homogeneous, each device type - * belongs to the same class - * - Device instances supporting a subset of the class capabilities are - * allowed - * - * We could manage different device classes through the enumerated - * lists (C) or the use of classes (C++), but that is presently not - * fully supported - * - * N.B. the 3 input formatters are of 2 different classess - */ - +#define HAS_NO_INPUT_FORMATTER #define USE_INPUT_SYSTEM_VERSION_2401 - -#define HAS_MMU_VERSION_2 -#define HAS_DMA_VERSION_2 -#define HAS_GDC_VERSION_2 -#define HAS_VAMEM_VERSION_2 -#define HAS_HMEM_VERSION_1 -#define HAS_BAMEM_VERSION_2 -#define HAS_IRQ_VERSION_2 -#define HAS_IRQ_MAP_VERSION_2 -#define HAS_INPUT_FORMATTER_VERSION_2 -/* 2401: HAS_INPUT_SYSTEM_VERSION_3 */ -/* 2400: HAS_INPUT_SYSTEM_VERSION_2 */ -#define HAS_INPUT_SYSTEM_VERSION_2 #define HAS_INPUT_SYSTEM_VERSION_2401 -#define HAS_BUFFERED_SENSOR -#define HAS_FIFO_MONITORS_VERSION_2 -/* #define HAS_GP_REGS_VERSION_2 */ -#define HAS_GP_DEVICE_VERSION_2 -#define HAS_GPIO_VERSION_1 -#define HAS_TIMED_CTRL_VERSION_1 -#define HAS_RX_VERSION_2 -#define HAS_NO_INPUT_FORMATTER -/*#define HAS_NO_PACKED_RAW_PIXELS*/ -/*#define HAS_NO_DVS_6AXIS_CONFIG_UPDATE*/ - -#define DMA_DDR_TO_VAMEM_WORKAROUND -#define DMA_DDR_TO_HMEM_WORKAROUND - -/* - * Semi global. "HRT" is accessible from SP, but - * the HRT types do not fully apply - */ -#define HRT_VADDRESS_WIDTH 32 -/* Surprise, this is a local property*/ -/*#define HRT_ADDRESS_WIDTH 64 */ -#define HRT_DATA_WIDTH 32 - -#define SIZEOF_HRT_REG (HRT_DATA_WIDTH >> 3) -#define HIVE_ISP_CTRL_DATA_BYTES (HIVE_ISP_CTRL_DATA_WIDTH / 8) - -/* The main bus connecting all devices */ -#define HRT_BUS_WIDTH HIVE_ISP_CTRL_DATA_WIDTH -#define HRT_BUS_BYTES HIVE_ISP_CTRL_DATA_BYTES - #define CSI2P_DISABLE_ISYS2401_ONLINE_MODE - -/* per-frame parameter handling support */ -#define SH_CSS_ENABLE_PER_FRAME_PARAMS - -typedef u32 hrt_bus_align_t; - -/* - * Enumerate the devices, device access through the API is by ID, - * through the DLI by address. The enumerator terminators are used - * to size the wiring arrays and as an exception value. - */ -typedef enum { - DDR0_ID = 0, - N_DDR_ID -} ddr_ID_t; - -typedef enum { - ISP0_ID = 0, - N_ISP_ID -} isp_ID_t; - -typedef enum { - SP0_ID = 0, - N_SP_ID -} sp_ID_t; - -typedef enum { - MMU0_ID = 0, - MMU1_ID, - N_MMU_ID -} mmu_ID_t; - -typedef enum { - DMA0_ID = 0, - N_DMA_ID -} dma_ID_t; - -typedef enum { - GDC0_ID = 0, - GDC1_ID, - N_GDC_ID -} gdc_ID_t; - -/* this extra define is needed because we want to use it also - in the preprocessor, and that doesn't work with enums. - */ -#define N_GDC_ID_CPP 2 - -typedef enum { - VAMEM0_ID = 0, - VAMEM1_ID, - VAMEM2_ID, - N_VAMEM_ID -} vamem_ID_t; - -typedef enum { - BAMEM0_ID = 0, - N_BAMEM_ID -} bamem_ID_t; - -typedef enum { - HMEM0_ID = 0, - N_HMEM_ID -} hmem_ID_t; - -typedef enum { - ISYS_IRQ0_ID = 0, /* port a */ - ISYS_IRQ1_ID, /* port b */ - ISYS_IRQ2_ID, /* port c */ - N_ISYS_IRQ_ID -} isys_irq_ID_t; - -typedef enum { - IRQ0_ID = 0, /* GP IRQ block */ - IRQ1_ID, /* Input formatter */ - IRQ2_ID, /* input system */ - IRQ3_ID, /* input selector */ - N_IRQ_ID -} irq_ID_t; - -typedef enum { - FIFO_MONITOR0_ID = 0, - N_FIFO_MONITOR_ID -} fifo_monitor_ID_t; - -/* - * Deprecated: Since all gp_reg instances are different - * and put in the address maps of other devices we cannot - * enumerate them as that assumes the instrances are the - * same. - * - * We define a single GP_DEVICE containing all gp_regs - * w.r.t. a single base address - * -typedef enum { - GP_REGS0_ID = 0, - N_GP_REGS_ID -} gp_regs_ID_t; - */ -typedef enum { - GP_DEVICE0_ID = 0, - N_GP_DEVICE_ID -} gp_device_ID_t; - -typedef enum { - GP_TIMER0_ID = 0, - GP_TIMER1_ID, - GP_TIMER2_ID, - GP_TIMER3_ID, - GP_TIMER4_ID, - GP_TIMER5_ID, - GP_TIMER6_ID, - GP_TIMER7_ID, - N_GP_TIMER_ID -} gp_timer_ID_t; - -typedef enum { - GPIO0_ID = 0, - N_GPIO_ID -} gpio_ID_t; - -typedef enum { - TIMED_CTRL0_ID = 0, - N_TIMED_CTRL_ID -} timed_ctrl_ID_t; - -typedef enum { - INPUT_FORMATTER0_ID = 0, - INPUT_FORMATTER1_ID, - INPUT_FORMATTER2_ID, - INPUT_FORMATTER3_ID, - N_INPUT_FORMATTER_ID -} input_formatter_ID_t; - -/* The IF RST is outside the IF */ -#define INPUT_FORMATTER0_SRST_OFFSET 0x0824 -#define INPUT_FORMATTER1_SRST_OFFSET 0x0624 -#define INPUT_FORMATTER2_SRST_OFFSET 0x0424 -#define INPUT_FORMATTER3_SRST_OFFSET 0x0224 - -#define INPUT_FORMATTER0_SRST_MASK 0x0001 -#define INPUT_FORMATTER1_SRST_MASK 0x0002 -#define INPUT_FORMATTER2_SRST_MASK 0x0004 -#define INPUT_FORMATTER3_SRST_MASK 0x0008 - -typedef enum { - INPUT_SYSTEM0_ID = 0, - N_INPUT_SYSTEM_ID -} input_system_ID_t; - -typedef enum { - RX0_ID = 0, - N_RX_ID -} rx_ID_t; - -enum mipi_port_id { - MIPI_PORT0_ID = 0, - MIPI_PORT1_ID, - MIPI_PORT2_ID, - N_MIPI_PORT_ID -}; - -#define N_RX_CHANNEL_ID 4 - -/* Generic port enumeration with an internal port type ID */ -typedef enum { - CSI_PORT0_ID = 0, - CSI_PORT1_ID, - CSI_PORT2_ID, - TPG_PORT0_ID, - PRBS_PORT0_ID, - FIFO_PORT0_ID, - MEMORY_PORT0_ID, - N_INPUT_PORT_ID -} input_port_ID_t; - -typedef enum { - CAPTURE_UNIT0_ID = 0, - CAPTURE_UNIT1_ID, - CAPTURE_UNIT2_ID, - ACQUISITION_UNIT0_ID, - DMA_UNIT0_ID, - CTRL_UNIT0_ID, - GPREGS_UNIT0_ID, - FIFO_UNIT0_ID, - IRQ_UNIT0_ID, - N_SUB_SYSTEM_ID -} sub_system_ID_t; - -#define N_CAPTURE_UNIT_ID 3 -#define N_ACQUISITION_UNIT_ID 1 -#define N_CTRL_UNIT_ID 1 - -/* - * Input-buffer Controller. - */ -typedef enum { - IBUF_CTRL0_ID = 0, /* map to ISYS2401_IBUF_CNTRL_A */ - IBUF_CTRL1_ID, /* map to ISYS2401_IBUF_CNTRL_B */ - IBUF_CTRL2_ID, /* map ISYS2401_IBUF_CNTRL_C */ - N_IBUF_CTRL_ID -} ibuf_ctrl_ID_t; -/* end of Input-buffer Controller */ - -/* - * Stream2MMIO. - */ -typedef enum { - STREAM2MMIO0_ID = 0, /* map to ISYS2401_S2M_A */ - STREAM2MMIO1_ID, /* map to ISYS2401_S2M_B */ - STREAM2MMIO2_ID, /* map to ISYS2401_S2M_C */ - N_STREAM2MMIO_ID -} stream2mmio_ID_t; - -typedef enum { - /* - * Stream2MMIO 0 has 8 SIDs that are indexed by - * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID7_ID]. - * - * Stream2MMIO 1 has 4 SIDs that are indexed by - * [STREAM2MMIO_SID0_ID...TREAM2MMIO_SID3_ID]. - * - * Stream2MMIO 2 has 4 SIDs that are indexed by - * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID3_ID]. - */ - STREAM2MMIO_SID0_ID = 0, - STREAM2MMIO_SID1_ID, - STREAM2MMIO_SID2_ID, - STREAM2MMIO_SID3_ID, - STREAM2MMIO_SID4_ID, - STREAM2MMIO_SID5_ID, - STREAM2MMIO_SID6_ID, - STREAM2MMIO_SID7_ID, - N_STREAM2MMIO_SID_ID -} stream2mmio_sid_ID_t; -/* end of Stream2MMIO */ - -/** - * Input System 2401: CSI-MIPI recevier. - */ -typedef enum { - CSI_RX_BACKEND0_ID = 0, /* map to ISYS2401_MIPI_BE_A */ - CSI_RX_BACKEND1_ID, /* map to ISYS2401_MIPI_BE_B */ - CSI_RX_BACKEND2_ID, /* map to ISYS2401_MIPI_BE_C */ - N_CSI_RX_BACKEND_ID -} csi_rx_backend_ID_t; - -typedef enum { - CSI_RX_FRONTEND0_ID = 0, /* map to ISYS2401_CSI_RX_A */ - CSI_RX_FRONTEND1_ID, /* map to ISYS2401_CSI_RX_B */ - CSI_RX_FRONTEND2_ID, /* map to ISYS2401_CSI_RX_C */ -#define N_CSI_RX_FRONTEND_ID (CSI_RX_FRONTEND2_ID + 1) -} csi_rx_frontend_ID_t; - -typedef enum { - CSI_RX_DLANE0_ID = 0, /* map to DLANE0 in CSI RX */ - CSI_RX_DLANE1_ID, /* map to DLANE1 in CSI RX */ - CSI_RX_DLANE2_ID, /* map to DLANE2 in CSI RX */ - CSI_RX_DLANE3_ID, /* map to DLANE3 in CSI RX */ - N_CSI_RX_DLANE_ID -} csi_rx_fe_dlane_ID_t; -/* end of CSI-MIPI receiver */ - -typedef enum { - ISYS2401_DMA0_ID = 0, - N_ISYS2401_DMA_ID -} isys2401_dma_ID_t; - -/** - * Pixel-generator. ("system_global.h") - */ -typedef enum { - PIXELGEN0_ID = 0, - PIXELGEN1_ID, - PIXELGEN2_ID, - N_PIXELGEN_ID -} pixelgen_ID_t; -/* end of pixel-generator. ("system_global.h") */ - -typedef enum { - INPUT_SYSTEM_CSI_PORT0_ID = 0, - INPUT_SYSTEM_CSI_PORT1_ID, - INPUT_SYSTEM_CSI_PORT2_ID, - - INPUT_SYSTEM_PIXELGEN_PORT0_ID, - INPUT_SYSTEM_PIXELGEN_PORT1_ID, - INPUT_SYSTEM_PIXELGEN_PORT2_ID, - - N_INPUT_SYSTEM_INPUT_PORT_ID -} input_system_input_port_ID_t; - -#define N_INPUT_SYSTEM_CSI_PORT 3 - -typedef enum { - ISYS2401_DMA_CHANNEL_0 = 0, - ISYS2401_DMA_CHANNEL_1, - ISYS2401_DMA_CHANNEL_2, - ISYS2401_DMA_CHANNEL_3, - ISYS2401_DMA_CHANNEL_4, - ISYS2401_DMA_CHANNEL_5, - ISYS2401_DMA_CHANNEL_6, - ISYS2401_DMA_CHANNEL_7, - ISYS2401_DMA_CHANNEL_8, - ISYS2401_DMA_CHANNEL_9, - ISYS2401_DMA_CHANNEL_10, - ISYS2401_DMA_CHANNEL_11, - N_ISYS2401_DMA_CHANNEL -} isys2401_dma_channel; - -enum ia_css_isp_memories { - IA_CSS_ISP_PMEM0 = 0, - IA_CSS_ISP_DMEM0, - IA_CSS_ISP_VMEM0, - IA_CSS_ISP_VAMEM0, - IA_CSS_ISP_VAMEM1, - IA_CSS_ISP_VAMEM2, - IA_CSS_ISP_HMEM0, - IA_CSS_SP_DMEM0, - IA_CSS_DDR, - N_IA_CSS_MEMORIES -}; - -#define IA_CSS_NUM_MEMORIES 9 -/* For driver compatibility */ -#define N_IA_CSS_ISP_MEMORIES IA_CSS_NUM_MEMORIES -#define IA_CSS_NUM_ISP_MEMORIES IA_CSS_NUM_MEMORIES - -#endif /* __SYSTEM_GLOBAL_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/isp2401_system_local.h b/drivers/staging/media/atomisp/pci/isp2401_system_local.h deleted file mode 100644 index b09f8faadb13..000000000000 --- a/drivers/staging/media/atomisp/pci/isp2401_system_local.h +++ /dev/null @@ -1,402 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0 */ -/* - * Support for Intel Camera Imaging ISP subsystem. - * Copyright (c) 2015, Intel Corporation. - * - * This program is free software; you can redistribute it and/or modify it - * under the terms and conditions of the GNU General Public License, - * version 2, as published by the Free Software Foundation. - * - * This program is distributed in the hope it will be useful, but WITHOUT - * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or - * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for - * more details. - */ - -#ifndef __SYSTEM_LOCAL_H_INCLUDED__ -#define __SYSTEM_LOCAL_H_INCLUDED__ - -#ifdef HRT_ISP_CSS_CUSTOM_HOST -#ifndef HRT_USE_VIR_ADDRS -#define HRT_USE_VIR_ADDRS -#endif -#endif - -#include "system_global.h" - -#define HRT_ADDRESS_WIDTH 64 /* Surprise, this is a local property */ - -/* This interface is deprecated */ -#include "hive_types.h" - -/* - * Cell specific address maps - */ -#if HRT_ADDRESS_WIDTH == 64 - -#define GP_FIFO_BASE ((hrt_address)0x0000000000090104) /* This is NOT a base address */ - -/* DDR */ -static const hrt_address DDR_BASE[N_DDR_ID] = { - 0x0000000120000000ULL -}; - -/* ISP */ -static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = { - 0x0000000000020000ULL -}; - -static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = { - 0x0000000000200000ULL -}; - -static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = { - 0x0000000000100000ULL -}; - -static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = { - 0x00000000001C0000ULL, - 0x00000000001D0000ULL, - 0x00000000001E0000ULL -}; - -static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = { - 0x00000000001F0000ULL -}; - -/* SP */ -static const hrt_address SP_CTRL_BASE[N_SP_ID] = { - 0x0000000000010000ULL -}; - -static const hrt_address SP_DMEM_BASE[N_SP_ID] = { - 0x0000000000300000ULL -}; - -/* MMU */ -/* - * MMU0_ID: The data MMU - * MMU1_ID: The icache MMU - */ -static const hrt_address MMU_BASE[N_MMU_ID] = { - 0x0000000000070000ULL, - 0x00000000000A0000ULL -}; - -/* DMA */ -static const hrt_address DMA_BASE[N_DMA_ID] = { - 0x0000000000040000ULL -}; - -static const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID] = { - 0x00000000000CA000ULL -}; - -/* IRQ */ -static const hrt_address IRQ_BASE[N_IRQ_ID] = { - 0x0000000000000500ULL, - 0x0000000000030A00ULL, - 0x000000000008C000ULL, - 0x0000000000090200ULL -}; - -/* - 0x0000000000000500ULL}; - */ - -/* GDC */ -static const hrt_address GDC_BASE[N_GDC_ID] = { - 0x0000000000050000ULL, - 0x0000000000060000ULL -}; - -/* FIFO_MONITOR (not a subset of GP_DEVICE) */ -static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = { - 0x0000000000000000ULL -}; - -/* -static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = { - 0x0000000000000000ULL}; - -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - 0x0000000000090000ULL}; -*/ - -/* GP_DEVICE (single base for all separate GP_REG instances) */ -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - 0x0000000000000000ULL -}; - -/*GP TIMER , all timer registers are inter-twined, - * so, having multiple base addresses for - * different timers does not help*/ -static const hrt_address GP_TIMER_BASE = - (hrt_address)0x0000000000000600ULL; - -/* GPIO */ -static const hrt_address GPIO_BASE[N_GPIO_ID] = { - 0x0000000000000400ULL -}; - -/* TIMED_CTRL */ -static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = { - 0x0000000000000100ULL -}; - -/* INPUT_FORMATTER */ -static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = { - 0x0000000000030000ULL, - 0x0000000000030200ULL, - 0x0000000000030400ULL, - 0x0000000000030600ULL -}; /* memcpy() */ - -/* INPUT_SYSTEM */ -static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = { - 0x0000000000080000ULL -}; - -/* 0x0000000000081000ULL, */ /* capture A */ -/* 0x0000000000082000ULL, */ /* capture B */ -/* 0x0000000000083000ULL, */ /* capture C */ -/* 0x0000000000084000ULL, */ /* Acquisition */ -/* 0x0000000000085000ULL, */ /* DMA */ -/* 0x0000000000089000ULL, */ /* ctrl */ -/* 0x000000000008A000ULL, */ /* GP regs */ -/* 0x000000000008B000ULL, */ /* FIFO */ -/* 0x000000000008C000ULL, */ /* IRQ */ - -/* RX, the MIPI lane control regs start at offset 0 */ -static const hrt_address RX_BASE[N_RX_ID] = { - 0x0000000000080100ULL -}; - -/* IBUF_CTRL, part of the Input System 2401 */ -static const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID] = { - 0x00000000000C1800ULL, /* ibuf controller A */ - 0x00000000000C3800ULL, /* ibuf controller B */ - 0x00000000000C5800ULL /* ibuf controller C */ -}; - -/* ISYS IRQ Controllers, part of the Input System 2401 */ -static const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID] = { - 0x00000000000C1400ULL, /* port a */ - 0x00000000000C3400ULL, /* port b */ - 0x00000000000C5400ULL /* port c */ -}; - -/* CSI FE, part of the Input System 2401 */ -static const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID] = { - 0x00000000000C0400ULL, /* csi fe controller A */ - 0x00000000000C2400ULL, /* csi fe controller B */ - 0x00000000000C4400ULL /* csi fe controller C */ -}; - -/* CSI BE, part of the Input System 2401 */ -static const hrt_address CSI_RX_BE_CTRL_BASE[N_CSI_RX_BACKEND_ID] = { - 0x00000000000C0800ULL, /* csi be controller A */ - 0x00000000000C2800ULL, /* csi be controller B */ - 0x00000000000C4800ULL /* csi be controller C */ -}; - -/* PIXEL Generator, part of the Input System 2401 */ -static const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID] = { - 0x00000000000C1000ULL, /* pixel gen controller A */ - 0x00000000000C3000ULL, /* pixel gen controller B */ - 0x00000000000C5000ULL /* pixel gen controller C */ -}; - -/* Stream2MMIO, part of the Input System 2401 */ -static const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID] = { - 0x00000000000C0C00ULL, /* stream2mmio controller A */ - 0x00000000000C2C00ULL, /* stream2mmio controller B */ - 0x00000000000C4C00ULL /* stream2mmio controller C */ -}; -#elif HRT_ADDRESS_WIDTH == 32 - -#define GP_FIFO_BASE ((hrt_address)0x00090104) /* This is NOT a base address */ - -/* DDR : Attention, this value not defined in 32-bit */ -static const hrt_address DDR_BASE[N_DDR_ID] = { - 0x00000000UL -}; - -/* ISP */ -static const hrt_address ISP_CTRL_BASE[N_ISP_ID] = { - 0x00020000UL -}; - -static const hrt_address ISP_DMEM_BASE[N_ISP_ID] = { - 0xffffffffUL -}; - -static const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = { - 0xffffffffUL -}; - -static const hrt_address ISP_VAMEM_BASE[N_VAMEM_ID] = { - 0xffffffffUL, - 0xffffffffUL, - 0xffffffffUL -}; - -static const hrt_address ISP_HMEM_BASE[N_HMEM_ID] = { - 0xffffffffUL -}; - -/* SP */ -static const hrt_address SP_CTRL_BASE[N_SP_ID] = { - 0x00010000UL -}; - -static const hrt_address SP_DMEM_BASE[N_SP_ID] = { - 0x00300000UL -}; - -/* MMU */ -/* - * MMU0_ID: The data MMU - * MMU1_ID: The icache MMU - */ -static const hrt_address MMU_BASE[N_MMU_ID] = { - 0x00070000UL, - 0x000A0000UL -}; - -/* DMA */ -static const hrt_address DMA_BASE[N_DMA_ID] = { - 0x00040000UL -}; - -static const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID] = { - 0x000CA000UL -}; - -/* IRQ */ -static const hrt_address IRQ_BASE[N_IRQ_ID] = { - 0x00000500UL, - 0x00030A00UL, - 0x0008C000UL, - 0x00090200UL -}; - -/* - 0x00000500UL}; - */ - -/* GDC */ -static const hrt_address GDC_BASE[N_GDC_ID] = { - 0x00050000UL, - 0x00060000UL -}; - -/* FIFO_MONITOR (not a subset of GP_DEVICE) */ -static const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = { - 0x00000000UL -}; - -/* -static const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = { - 0x00000000UL}; - -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - 0x00090000UL}; -*/ - -/* GP_DEVICE (single base for all separate GP_REG instances) */ -static const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { - 0x00000000UL -}; - -/*GP TIMER , all timer registers are inter-twined, - * so, having multiple base addresses for - * different timers does not help*/ -static const hrt_address GP_TIMER_BASE = - (hrt_address)0x00000600UL; -/* GPIO */ -static const hrt_address GPIO_BASE[N_GPIO_ID] = { - 0x00000400UL -}; - -/* TIMED_CTRL */ -static const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = { - 0x00000100UL -}; - -/* INPUT_FORMATTER */ -static const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = { - 0x00030000UL, - 0x00030200UL, - 0x00030400UL -}; - -/* 0x00030600UL, */ /* memcpy() */ - -/* INPUT_SYSTEM */ -static const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = { - 0x00080000UL -}; - -/* 0x00081000UL, */ /* capture A */ -/* 0x00082000UL, */ /* capture B */ -/* 0x00083000UL, */ /* capture C */ -/* 0x00084000UL, */ /* Acquisition */ -/* 0x00085000UL, */ /* DMA */ -/* 0x00089000UL, */ /* ctrl */ -/* 0x0008A000UL, */ /* GP regs */ -/* 0x0008B000UL, */ /* FIFO */ -/* 0x0008C000UL, */ /* IRQ */ - -/* RX, the MIPI lane control regs start at offset 0 */ -static const hrt_address RX_BASE[N_RX_ID] = { - 0x00080100UL -}; - -/* IBUF_CTRL, part of the Input System 2401 */ -static const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID] = { - 0x000C1800UL, /* ibuf controller A */ - 0x000C3800UL, /* ibuf controller B */ - 0x000C5800UL /* ibuf controller C */ -}; - -/* ISYS IRQ Controllers, part of the Input System 2401 */ -static const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID] = { - 0x000C1400ULL, /* port a */ - 0x000C3400ULL, /* port b */ - 0x000C5400ULL /* port c */ -}; - -/* CSI FE, part of the Input System 2401 */ -static const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID] = { - 0x000C0400UL, /* csi fe controller A */ - 0x000C2400UL, /* csi fe controller B */ - 0x000C4400UL /* csi fe controller C */ -}; - -/* CSI BE, part of the Input System 2401 */ -static const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_BACKEND_ID] = { - 0x000C0800UL, /* csi be controller A */ - 0x000C2800UL, /* csi be controller B */ - 0x000C4800UL /* csi be controller C */ -}; - -/* PIXEL Generator, part of the Input System 2401 */ -static const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID] = { - 0x000C1000UL, /* pixel gen controller A */ - 0x000C3000UL, /* pixel gen controller B */ - 0x000C5000UL /* pixel gen controller C */ -}; - -/* Stream2MMIO, part of the Input System 2401 */ -static const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID] = { - 0x000C0C00UL, /* stream2mmio controller A */ - 0x000C2C00UL, /* stream2mmio controller B */ - 0x000C4C00UL /* stream2mmio controller C */ -}; - -#else -#error "system_local.h: HRT_ADDRESS_WIDTH must be one of {32,64}" -#endif - -#endif /* __SYSTEM_LOCAL_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/sh_css.c b/drivers/staging/media/atomisp/pci/sh_css.c index 6676537f0e97..54434c2dbaf9 100644 --- a/drivers/staging/media/atomisp/pci/sh_css.c +++ b/drivers/staging/media/atomisp/pci/sh_css.c @@ -1841,8 +1841,13 @@ ia_css_init(struct device *dev, const struct ia_css_env *env, #endif #if !defined(HAS_NO_INPUT_SYSTEM) - dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, - ISP_DMA_MAX_BURST_LENGTH); + + if (!IS_ISP2401) + dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, + ISP2400_DMA_MAX_BURST_LENGTH); + else + dma_set_max_burst_size(DMA0_ID, HIVE_DMA_BUS_DDR_CONN, + ISP2401_DMA_MAX_BURST_LENGTH); if (ia_css_isys_init() != INPUT_SYSTEM_ERR_NO_ERROR) err = -EINVAL; diff --git a/drivers/staging/media/atomisp/pci/system_global.h b/drivers/staging/media/atomisp/pci/system_global.h index 16d0a2e9a4dc..90210f6943d2 100644 --- a/drivers/staging/media/atomisp/pci/system_global.h +++ b/drivers/staging/media/atomisp/pci/system_global.h @@ -4,8 +4,403 @@ * (c) 2020 Mauro Carvalho Chehab <mchehab+huawei@kernel.org> */ +#ifndef __SYSTEM_GLOBAL_H_INCLUDED__ +#define __SYSTEM_GLOBAL_H_INCLUDED__ + +/* + * Create a list of HAS and IS properties that defines the system + * Those are common for both ISP2400 and ISP2401 + * + * The configuration assumes the following + * - The system is hetereogeneous; Multiple cells and devices classes + * - The cell and device instances are homogeneous, each device type + * belongs to the same class + * - Device instances supporting a subset of the class capabilities are + * allowed + * + * We could manage different device classes through the enumerated + * lists (C) or the use of classes (C++), but that is presently not + * fully supported + * + * N.B. the 3 input formatters are of 2 different classess + */ + +#define HAS_MMU_VERSION_2 +#define HAS_DMA_VERSION_2 +#define HAS_GDC_VERSION_2 +#define HAS_VAMEM_VERSION_2 +#define HAS_HMEM_VERSION_1 +#define HAS_BAMEM_VERSION_2 +#define HAS_IRQ_VERSION_2 +#define HAS_IRQ_MAP_VERSION_2 +#define HAS_INPUT_FORMATTER_VERSION_2 +#define HAS_INPUT_SYSTEM_VERSION_2 +#define HAS_BUFFERED_SENSOR +#define HAS_FIFO_MONITORS_VERSION_2 +#define HAS_GP_DEVICE_VERSION_2 +#define HAS_GPIO_VERSION_1 +#define HAS_TIMED_CTRL_VERSION_1 +#define HAS_RX_VERSION_2 + +/* per-frame parameter handling support */ +#define SH_CSS_ENABLE_PER_FRAME_PARAMS + +#define DMA_DDR_TO_VAMEM_WORKAROUND +#define DMA_DDR_TO_HMEM_WORKAROUND + +/* + * The longest allowed (uninteruptible) bus transfer, does not + * take stalling into account + */ +#define HIVE_ISP_MAX_BURST_LENGTH 1024 + +/* + * Maximum allowed burst length in words for the ISP DMA + * This value is set to 2 to prevent the ISP DMA from blocking + * the bus for too long; as the input system can only buffer + * 2 lines on Moorefield and Cherrytrail, the input system buffers + * may overflow if blocked for too long (BZ 2726). + */ +#define ISP2400_DMA_MAX_BURST_LENGTH 128 +#define ISP2401_DMA_MAX_BURST_LENGTH 2 + #ifdef ISP2401 # include "isp2401_system_global.h" #else # include "isp2400_system_global.h" #endif + +#include <hive_isp_css_defs.h> +#include <type_support.h> + +/* This interface is deprecated */ +#include "hive_types.h" + +/* + * Semi global. "HRT" is accessible from SP, but the HRT types do not fully apply + */ +#define HRT_VADDRESS_WIDTH 32 + +#define SIZEOF_HRT_REG (HRT_DATA_WIDTH >> 3) +#define HIVE_ISP_CTRL_DATA_BYTES (HIVE_ISP_CTRL_DATA_WIDTH / 8) + +/* The main bus connecting all devices */ +#define HRT_BUS_WIDTH HIVE_ISP_CTRL_DATA_WIDTH +#define HRT_BUS_BYTES HIVE_ISP_CTRL_DATA_BYTES + +typedef u32 hrt_bus_align_t; + +/* + * Enumerate the devices, device access through the API is by ID, + * through the DLI by address. The enumerator terminators are used + * to size the wiring arrays and as an exception value. + */ +typedef enum { + DDR0_ID = 0, + N_DDR_ID +} ddr_ID_t; + +typedef enum { + ISP0_ID = 0, + N_ISP_ID +} isp_ID_t; + +typedef enum { + SP0_ID = 0, + N_SP_ID +} sp_ID_t; + +typedef enum { + MMU0_ID = 0, + MMU1_ID, + N_MMU_ID +} mmu_ID_t; + +typedef enum { + DMA0_ID = 0, + N_DMA_ID +} dma_ID_t; + +typedef enum { + GDC0_ID = 0, + GDC1_ID, + N_GDC_ID +} gdc_ID_t; + +/* this extra define is needed because we want to use it also + in the preprocessor, and that doesn't work with enums. + */ +#define N_GDC_ID_CPP 2 + +typedef enum { + VAMEM0_ID = 0, + VAMEM1_ID, + VAMEM2_ID, + N_VAMEM_ID +} vamem_ID_t; + +typedef enum { + BAMEM0_ID = 0, + N_BAMEM_ID +} bamem_ID_t; + +typedef enum { + HMEM0_ID = 0, + N_HMEM_ID +} hmem_ID_t; + +typedef enum { + IRQ0_ID = 0, /* GP IRQ block */ + IRQ1_ID, /* Input formatter */ + IRQ2_ID, /* input system */ + IRQ3_ID, /* input selector */ + N_IRQ_ID +} irq_ID_t; + +typedef enum { + FIFO_MONITOR0_ID = 0, + N_FIFO_MONITOR_ID +} fifo_monitor_ID_t; + +typedef enum { + GP_DEVICE0_ID = 0, + N_GP_DEVICE_ID +} gp_device_ID_t; + +typedef enum { + GP_TIMER0_ID = 0, + GP_TIMER1_ID, + GP_TIMER2_ID, + GP_TIMER3_ID, + GP_TIMER4_ID, + GP_TIMER5_ID, + GP_TIMER6_ID, + GP_TIMER7_ID, + N_GP_TIMER_ID +} gp_timer_ID_t; + +typedef enum { + GPIO0_ID = 0, + N_GPIO_ID +} gpio_ID_t; + +typedef enum { + TIMED_CTRL0_ID = 0, + N_TIMED_CTRL_ID +} timed_ctrl_ID_t; + +typedef enum { + INPUT_FORMATTER0_ID = 0, + INPUT_FORMATTER1_ID, + INPUT_FORMATTER2_ID, + INPUT_FORMATTER3_ID, + N_INPUT_FORMATTER_ID +} input_formatter_ID_t; + +/* The IF RST is outside the IF */ +#define INPUT_FORMATTER0_SRST_OFFSET 0x0824 +#define INPUT_FORMATTER1_SRST_OFFSET 0x0624 +#define INPUT_FORMATTER2_SRST_OFFSET 0x0424 +#define INPUT_FORMATTER3_SRST_OFFSET 0x0224 + +#define INPUT_FORMATTER0_SRST_MASK 0x0001 +#define INPUT_FORMATTER1_SRST_MASK 0x0002 +#define INPUT_FORMATTER2_SRST_MASK 0x0004 +#define INPUT_FORMATTER3_SRST_MASK 0x0008 + +typedef enum { + INPUT_SYSTEM0_ID = 0, + N_INPUT_SYSTEM_ID +} input_system_ID_t; + +typedef enum { + RX0_ID = 0, + N_RX_ID +} rx_ID_t; + +enum mipi_port_id { + MIPI_PORT0_ID = 0, + MIPI_PORT1_ID, + MIPI_PORT2_ID, + N_MIPI_PORT_ID +}; + +#define N_RX_CHANNEL_ID 4 + +/* Generic port enumeration with an internal port type ID */ +typedef enum { + CSI_PORT0_ID = 0, + CSI_PORT1_ID, + CSI_PORT2_ID, + TPG_PORT0_ID, + PRBS_PORT0_ID, + FIFO_PORT0_ID, + MEMORY_PORT0_ID, + N_INPUT_PORT_ID +} input_port_ID_t; + +typedef enum { + CAPTURE_UNIT0_ID = 0, + CAPTURE_UNIT1_ID, + CAPTURE_UNIT2_ID, + ACQUISITION_UNIT0_ID, + DMA_UNIT0_ID, + CTRL_UNIT0_ID, + GPREGS_UNIT0_ID, + FIFO_UNIT0_ID, + IRQ_UNIT0_ID, + N_SUB_SYSTEM_ID +} sub_system_ID_t; + +#define N_CAPTURE_UNIT_ID 3 +#define N_ACQUISITION_UNIT_ID 1 +#define N_CTRL_UNIT_ID 1 + + +enum ia_css_isp_memories { + IA_CSS_ISP_PMEM0 = 0, + IA_CSS_ISP_DMEM0, + IA_CSS_ISP_VMEM0, + IA_CSS_ISP_VAMEM0, + IA_CSS_ISP_VAMEM1, + IA_CSS_ISP_VAMEM2, + IA_CSS_ISP_HMEM0, + IA_CSS_SP_DMEM0, + IA_CSS_DDR, + N_IA_CSS_MEMORIES +}; + +#define IA_CSS_NUM_MEMORIES 9 +/* For driver compatibility */ +#define N_IA_CSS_ISP_MEMORIES IA_CSS_NUM_MEMORIES +#define IA_CSS_NUM_ISP_MEMORIES IA_CSS_NUM_MEMORIES + +/* + * ISP2401 specific enums + */ + +typedef enum { + ISYS_IRQ0_ID = 0, /* port a */ + ISYS_IRQ1_ID, /* port b */ + ISYS_IRQ2_ID, /* port c */ + N_ISYS_IRQ_ID +} isys_irq_ID_t; + + +/* + * Input-buffer Controller. + */ +typedef enum { + IBUF_CTRL0_ID = 0, /* map to ISYS2401_IBUF_CNTRL_A */ + IBUF_CTRL1_ID, /* map to ISYS2401_IBUF_CNTRL_B */ + IBUF_CTRL2_ID, /* map ISYS2401_IBUF_CNTRL_C */ + N_IBUF_CTRL_ID +} ibuf_ctrl_ID_t; +/* end of Input-buffer Controller */ + +/* + * Stream2MMIO. + */ +typedef enum { + STREAM2MMIO0_ID = 0, /* map to ISYS2401_S2M_A */ + STREAM2MMIO1_ID, /* map to ISYS2401_S2M_B */ + STREAM2MMIO2_ID, /* map to ISYS2401_S2M_C */ + N_STREAM2MMIO_ID +} stream2mmio_ID_t; + +typedef enum { + /* + * Stream2MMIO 0 has 8 SIDs that are indexed by + * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID7_ID]. + * + * Stream2MMIO 1 has 4 SIDs that are indexed by + * [STREAM2MMIO_SID0_ID...TREAM2MMIO_SID3_ID]. + * + * Stream2MMIO 2 has 4 SIDs that are indexed by + * [STREAM2MMIO_SID0_ID...STREAM2MMIO_SID3_ID]. + */ + STREAM2MMIO_SID0_ID = 0, + STREAM2MMIO_SID1_ID, + STREAM2MMIO_SID2_ID, + STREAM2MMIO_SID3_ID, + STREAM2MMIO_SID4_ID, + STREAM2MMIO_SID5_ID, + STREAM2MMIO_SID6_ID, + STREAM2MMIO_SID7_ID, + N_STREAM2MMIO_SID_ID +} stream2mmio_sid_ID_t; +/* end of Stream2MMIO */ + +/** + * Input System 2401: CSI-MIPI recevier. + */ +typedef enum { + CSI_RX_BACKEND0_ID = 0, /* map to ISYS2401_MIPI_BE_A */ + CSI_RX_BACKEND1_ID, /* map to ISYS2401_MIPI_BE_B */ + CSI_RX_BACKEND2_ID, /* map to ISYS2401_MIPI_BE_C */ + N_CSI_RX_BACKEND_ID +} csi_rx_backend_ID_t; + +typedef enum { + CSI_RX_FRONTEND0_ID = 0, /* map to ISYS2401_CSI_RX_A */ + CSI_RX_FRONTEND1_ID, /* map to ISYS2401_CSI_RX_B */ + CSI_RX_FRONTEND2_ID, /* map to ISYS2401_CSI_RX_C */ +#define N_CSI_RX_FRONTEND_ID (CSI_RX_FRONTEND2_ID + 1) +} csi_rx_frontend_ID_t; + +typedef enum { + CSI_RX_DLANE0_ID = 0, /* map to DLANE0 in CSI RX */ + CSI_RX_DLANE1_ID, /* map to DLANE1 in CSI RX */ + CSI_RX_DLANE2_ID, /* map to DLANE2 in CSI RX */ + CSI_RX_DLANE3_ID, /* map to DLANE3 in CSI RX */ + N_CSI_RX_DLANE_ID +} csi_rx_fe_dlane_ID_t; +/* end of CSI-MIPI receiver */ + +typedef enum { + ISYS2401_DMA0_ID = 0, + N_ISYS2401_DMA_ID +} isys2401_dma_ID_t; + +/** + * Pixel-generator. ("system_global.h") + */ +typedef enum { + PIXELGEN0_ID = 0, + PIXELGEN1_ID, + PIXELGEN2_ID, + N_PIXELGEN_ID +} pixelgen_ID_t; +/* end of pixel-generator. ("system_global.h") */ + +typedef enum { + INPUT_SYSTEM_CSI_PORT0_ID = 0, + INPUT_SYSTEM_CSI_PORT1_ID, + INPUT_SYSTEM_CSI_PORT2_ID, + + INPUT_SYSTEM_PIXELGEN_PORT0_ID, + INPUT_SYSTEM_PIXELGEN_PORT1_ID, + INPUT_SYSTEM_PIXELGEN_PORT2_ID, + + N_INPUT_SYSTEM_INPUT_PORT_ID +} input_system_input_port_ID_t; + +#define N_INPUT_SYSTEM_CSI_PORT 3 + +typedef enum { + ISYS2401_DMA_CHANNEL_0 = 0, + ISYS2401_DMA_CHANNEL_1, + ISYS2401_DMA_CHANNEL_2, + ISYS2401_DMA_CHANNEL_3, + ISYS2401_DMA_CHANNEL_4, + ISYS2401_DMA_CHANNEL_5, + ISYS2401_DMA_CHANNEL_6, + ISYS2401_DMA_CHANNEL_7, + ISYS2401_DMA_CHANNEL_8, + ISYS2401_DMA_CHANNEL_9, + ISYS2401_DMA_CHANNEL_10, + ISYS2401_DMA_CHANNEL_11, + N_ISYS2401_DMA_CHANNEL +} isys2401_dma_channel; + +#endif /* __SYSTEM_GLOBAL_H_INCLUDED__ */ diff --git a/drivers/staging/media/atomisp/pci/system_local.c b/drivers/staging/media/atomisp/pci/system_local.c new file mode 100644 index 000000000000..4ca8569d7feb --- /dev/null +++ b/drivers/staging/media/atomisp/pci/system_local.c @@ -0,0 +1,179 @@ +// SPDX-License-Identifier: GPL-2.0 +/* + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. + */ + +#include "system_local.h" + +/* ISP */ +const hrt_address ISP_CTRL_BASE[N_ISP_ID] = { + 0x0000000000020000ULL +}; + +const hrt_address ISP_DMEM_BASE[N_ISP_ID] = { + 0x0000000000200000ULL +}; + +const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID] = { + 0x0000000000100000ULL +}; + +/* SP */ +const hrt_address SP_CTRL_BASE[N_SP_ID] = { + 0x0000000000010000ULL +}; + +const hrt_address SP_DMEM_BASE[N_SP_ID] = { + 0x0000000000300000ULL +}; + +/* MMU */ +/* + * MMU0_ID: The data MMU + * MMU1_ID: The icache MMU + */ +const hrt_address MMU_BASE[N_MMU_ID] = { + 0x0000000000070000ULL, + 0x00000000000A0000ULL +}; + +/* DMA */ +const hrt_address DMA_BASE[N_DMA_ID] = { + 0x0000000000040000ULL +}; + +const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID] = { + 0x00000000000CA000ULL +}; + +/* IRQ */ +const hrt_address IRQ_BASE[N_IRQ_ID] = { + 0x0000000000000500ULL, + 0x0000000000030A00ULL, + 0x000000000008C000ULL, + 0x0000000000090200ULL +}; + +/* + 0x0000000000000500ULL}; + */ + +/* GDC */ +const hrt_address GDC_BASE[N_GDC_ID] = { + 0x0000000000050000ULL, + 0x0000000000060000ULL +}; + +/* FIFO_MONITOR (not a subset of GP_DEVICE) */ +const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID] = { + 0x0000000000000000ULL +}; + +/* +const hrt_address GP_REGS_BASE[N_GP_REGS_ID] = { + 0x0000000000000000ULL}; + +const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { + 0x0000000000090000ULL}; +*/ + +/* GP_DEVICE (single base for all separate GP_REG instances) */ +const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID] = { + 0x0000000000000000ULL +}; + +/*GP TIMER , all timer registers are inter-twined, + * so, having multiple base addresses for + * different timers does not help*/ +const hrt_address GP_TIMER_BASE = + (hrt_address)0x0000000000000600ULL; + +/* GPIO */ +const hrt_address GPIO_BASE[N_GPIO_ID] = { + 0x0000000000000400ULL +}; + +/* TIMED_CTRL */ +const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID] = { + 0x0000000000000100ULL +}; + +/* INPUT_FORMATTER */ +const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID] = { + 0x0000000000030000ULL, + 0x0000000000030200ULL, + 0x0000000000030400ULL, + 0x0000000000030600ULL +}; /* memcpy() */ + +/* INPUT_SYSTEM */ +const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID] = { + 0x0000000000080000ULL +}; + +/* 0x0000000000081000ULL, */ /* capture A */ +/* 0x0000000000082000ULL, */ /* capture B */ +/* 0x0000000000083000ULL, */ /* capture C */ +/* 0x0000000000084000ULL, */ /* Acquisition */ +/* 0x0000000000085000ULL, */ /* DMA */ +/* 0x0000000000089000ULL, */ /* ctrl */ +/* 0x000000000008A000ULL, */ /* GP regs */ +/* 0x000000000008B000ULL, */ /* FIFO */ +/* 0x000000000008C000ULL, */ /* IRQ */ + +/* RX, the MIPI lane control regs start at offset 0 */ +const hrt_address RX_BASE[N_RX_ID] = { + 0x0000000000080100ULL +}; + +/* IBUF_CTRL, part of the Input System 2401 */ +const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID] = { + 0x00000000000C1800ULL, /* ibuf controller A */ + 0x00000000000C3800ULL, /* ibuf controller B */ + 0x00000000000C5800ULL /* ibuf controller C */ +}; + +/* ISYS IRQ Controllers, part of the Input System 2401 */ +const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID] = { + 0x00000000000C1400ULL, /* port a */ + 0x00000000000C3400ULL, /* port b */ + 0x00000000000C5400ULL /* port c */ +}; + +/* CSI FE, part of the Input System 2401 */ +const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID] = { + 0x00000000000C0400ULL, /* csi fe controller A */ + 0x00000000000C2400ULL, /* csi fe controller B */ + 0x00000000000C4400ULL /* csi fe controller C */ +}; + +/* CSI BE, part of the Input System 2401 */ +const hrt_address CSI_RX_BE_CTRL_BASE[N_CSI_RX_BACKEND_ID] = { + 0x00000000000C0800ULL, /* csi be controller A */ + 0x00000000000C2800ULL, /* csi be controller B */ + 0x00000000000C4800ULL /* csi be controller C */ +}; + +/* PIXEL Generator, part of the Input System 2401 */ +const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID] = { + 0x00000000000C1000ULL, /* pixel gen controller A */ + 0x00000000000C3000ULL, /* pixel gen controller B */ + 0x00000000000C5000ULL /* pixel gen controller C */ +}; + +/* Stream2MMIO, part of the Input System 2401 */ +const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID] = { + 0x00000000000C0C00ULL, /* stream2mmio controller A */ + 0x00000000000C2C00ULL, /* stream2mmio controller B */ + 0x00000000000C4C00ULL /* stream2mmio controller C */ +}; diff --git a/drivers/staging/media/atomisp/pci/system_local.h b/drivers/staging/media/atomisp/pci/system_local.h index dfcc4c2b8f16..a47258c2e8a8 100644 --- a/drivers/staging/media/atomisp/pci/system_local.h +++ b/drivers/staging/media/atomisp/pci/system_local.h @@ -1,11 +1,103 @@ /* SPDX-License-Identifier: GPL-2.0 */ -// SPDX-License-Identifier: GPL-2.0-or-later /* - * (c) 2020 Mauro Carvalho Chehab <mchehab+huawei@kernel.org> + * Support for Intel Camera Imaging ISP subsystem. + * Copyright (c) 2015, Intel Corporation. + * + * This program is free software; you can redistribute it and/or modify it + * under the terms and conditions of the GNU General Public License, + * version 2, as published by the Free Software Foundation. + * + * This program is distributed in the hope it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for + * more details. */ -#ifdef ISP2401 -# include "isp2401_system_local.h" -#else -# include "isp2400_system_local.h" +#ifndef __SYSTEM_LOCAL_H_INCLUDED__ +#define __SYSTEM_LOCAL_H_INCLUDED__ + +#ifdef HRT_ISP_CSS_CUSTOM_HOST +#ifndef HRT_USE_VIR_ADDRS +#define HRT_USE_VIR_ADDRS +#endif #endif + +#include "system_global.h" + +/* This interface is deprecated */ +#include "hive_types.h" + +/* + * Cell specific address maps + */ + +#define GP_FIFO_BASE ((hrt_address)0x0000000000090104) /* This is NOT a base address */ + +/* ISP */ +extern const hrt_address ISP_CTRL_BASE[N_ISP_ID]; +extern const hrt_address ISP_DMEM_BASE[N_ISP_ID]; +extern const hrt_address ISP_BAMEM_BASE[N_BAMEM_ID]; + +/* SP */ +extern const hrt_address SP_CTRL_BASE[N_SP_ID]; +extern const hrt_address SP_DMEM_BASE[N_SP_ID]; + +/* MMU */ + +extern const hrt_address MMU_BASE[N_MMU_ID]; + +/* DMA */ +extern const hrt_address DMA_BASE[N_DMA_ID]; +extern const hrt_address ISYS2401_DMA_BASE[N_ISYS2401_DMA_ID]; + +/* IRQ */ +extern const hrt_address IRQ_BASE[N_IRQ_ID]; + +/* GDC */ +extern const hrt_address GDC_BASE[N_GDC_ID]; + +/* FIFO_MONITOR (not a subset of GP_DEVICE) */ +extern const hrt_address FIFO_MONITOR_BASE[N_FIFO_MONITOR_ID]; + +/* GP_DEVICE (single base for all separate GP_REG instances) */ +extern const hrt_address GP_DEVICE_BASE[N_GP_DEVICE_ID]; + +/*GP TIMER , all timer registers are inter-twined, + * so, having multiple base addresses for + * different timers does not help*/ +extern const hrt_address GP_TIMER_BASE; + +/* GPIO */ +extern const hrt_address GPIO_BASE[N_GPIO_ID]; + +/* TIMED_CTRL */ +extern const hrt_address TIMED_CTRL_BASE[N_TIMED_CTRL_ID]; + +/* INPUT_FORMATTER */ +extern const hrt_address INPUT_FORMATTER_BASE[N_INPUT_FORMATTER_ID]; + +/* INPUT_SYSTEM */ +extern const hrt_address INPUT_SYSTEM_BASE[N_INPUT_SYSTEM_ID]; + +/* RX, the MIPI lane control regs start at offset 0 */ +extern const hrt_address RX_BASE[N_RX_ID]; + +/* IBUF_CTRL, part of the Input System 2401 */ +extern const hrt_address IBUF_CTRL_BASE[N_IBUF_CTRL_ID]; + +/* ISYS IRQ Controllers, part of the Input System 2401 */ +extern const hrt_address ISYS_IRQ_BASE[N_ISYS_IRQ_ID]; + +/* CSI FE, part of the Input System 2401 */ +extern const hrt_address CSI_RX_FE_CTRL_BASE[N_CSI_RX_FRONTEND_ID]; + +/* CSI BE, part of the Input System 2401 */ +extern const hrt_address CSI_RX_BE_CTRL_BASE[N_CSI_RX_BACKEND_ID]; + +/* PIXEL Generator, part of the Input System 2401 */ +extern const hrt_address PIXELGEN_CTRL_BASE[N_PIXELGEN_ID]; + +/* Stream2MMIO, part of the Input System 2401 */ +extern const hrt_address STREAM2MMIO_CTRL_BASE[N_STREAM2MMIO_ID]; + +#endif /* __SYSTEM_LOCAL_H_INCLUDED__ */ diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index f634c81998bb..de881a6cff35 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -521,14 +521,19 @@ static void vfio_pci_release(void *device_data) vfio_pci_vf_token_user_add(vdev, -1); vfio_spapr_pci_eeh_release(vdev->pdev); vfio_pci_disable(vdev); + mutex_lock(&vdev->igate); if (vdev->err_trigger) { eventfd_ctx_put(vdev->err_trigger); vdev->err_trigger = NULL; } + mutex_unlock(&vdev->igate); + + mutex_lock(&vdev->igate); if (vdev->req_trigger) { eventfd_ctx_put(vdev->req_trigger); vdev->req_trigger = NULL; } + mutex_unlock(&vdev->igate); } mutex_unlock(&vdev->reflck->lock); diff --git a/drivers/virtio/virtio_mmio.c b/drivers/virtio/virtio_mmio.c index 9d16aaffca9d..627ac0487494 100644 --- a/drivers/virtio/virtio_mmio.c +++ b/drivers/virtio/virtio_mmio.c @@ -641,11 +641,11 @@ static int vm_cmdline_set(const char *device, &vm_cmdline_id, &consumed); /* - * sscanf() must processes at least 2 chunks; also there + * sscanf() must process at least 2 chunks; also there * must be no extra characters after the last chunk, so * str[consumed] must be '\0' */ - if (processed < 2 || str[consumed]) + if (processed < 2 || str[consumed] || irq == 0) return -EINVAL; resources[0].flags = IORESOURCE_MEM; diff --git a/fs/btrfs/backref.c b/fs/btrfs/backref.c index d888e71e66b6..ea10f7bc99ab 100644 --- a/fs/btrfs/backref.c +++ b/fs/btrfs/backref.c @@ -1461,6 +1461,7 @@ static int btrfs_find_all_roots_safe(struct btrfs_trans_handle *trans, if (ret < 0 && ret != -ENOENT) { ulist_free(tmp); ulist_free(*roots); + *roots = NULL; return ret; } node = ulist_next(tmp, &uiter); diff --git a/fs/btrfs/extent_io.c b/fs/btrfs/extent_io.c index 608f93438b29..60278e52c37a 100644 --- a/fs/btrfs/extent_io.c +++ b/fs/btrfs/extent_io.c @@ -1999,7 +1999,8 @@ static int __process_pages_contig(struct address_space *mapping, if (!PageDirty(pages[i]) || pages[i]->mapping != mapping) { unlock_page(pages[i]); - put_page(pages[i]); + for (; i < ret; i++) + put_page(pages[i]); err = -EAGAIN; goto out; } diff --git a/fs/btrfs/inode.c b/fs/btrfs/inode.c index 43c803c16b48..6862cd7e21a9 100644 --- a/fs/btrfs/inode.c +++ b/fs/btrfs/inode.c @@ -8123,20 +8123,17 @@ again: /* * Qgroup reserved space handler * Page here will be either - * 1) Already written to disk - * In this case, its reserved space is released from data rsv map - * and will be freed by delayed_ref handler finally. - * So even we call qgroup_free_data(), it won't decrease reserved - * space. - * 2) Not written to disk - * This means the reserved space should be freed here. However, - * if a truncate invalidates the page (by clearing PageDirty) - * and the page is accounted for while allocating extent - * in btrfs_check_data_free_space() we let delayed_ref to - * free the entire extent. + * 1) Already written to disk or ordered extent already submitted + * Then its QGROUP_RESERVED bit in io_tree is already cleaned. + * Qgroup will be handled by its qgroup_record then. + * btrfs_qgroup_free_data() call will do nothing here. + * + * 2) Not written to disk yet + * Then btrfs_qgroup_free_data() call will clear the QGROUP_RESERVED + * bit of its io_tree, and free the qgroup reserved data space. + * Since the IO will never happen for this page. */ - if (PageDirty(page)) - btrfs_qgroup_free_data(inode, NULL, page_start, PAGE_SIZE); + btrfs_qgroup_free_data(inode, NULL, page_start, PAGE_SIZE); if (!inode_evicting) { clear_extent_bit(tree, page_start, page_end, EXTENT_LOCKED | EXTENT_DELALLOC | EXTENT_DELALLOC_NEW | diff --git a/fs/btrfs/volumes.c b/fs/btrfs/volumes.c index 0d6e785bcb98..f403fb1e6d37 100644 --- a/fs/btrfs/volumes.c +++ b/fs/btrfs/volumes.c @@ -7052,6 +7052,14 @@ int btrfs_read_chunk_tree(struct btrfs_fs_info *fs_info) mutex_lock(&fs_info->chunk_mutex); /* + * It is possible for mount and umount to race in such a way that + * we execute this code path, but open_fs_devices failed to clear + * total_rw_bytes. We certainly want it cleared before reading the + * device items, so clear it here. + */ + fs_info->fs_devices->total_rw_bytes = 0; + + /* * Read all device items, and then all the chunk items. All * device items are found before any chunk item (their object id * is smaller than the lowest possible object id for a chunk diff --git a/fs/exfat/dir.c b/fs/exfat/dir.c index 91ece649285d..119abf0d8dd6 100644 --- a/fs/exfat/dir.c +++ b/fs/exfat/dir.c @@ -1112,7 +1112,7 @@ found: ret = exfat_get_next_cluster(sb, &clu.dir); } - if (ret || clu.dir != EXFAT_EOF_CLUSTER) { + if (ret || clu.dir == EXFAT_EOF_CLUSTER) { /* just initialized hint_stat */ hint_stat->clu = p_dir->dir; hint_stat->eidx = 0; diff --git a/fs/exfat/exfat_fs.h b/fs/exfat/exfat_fs.h index 7579cd3bbadb..75c7bdbeba6d 100644 --- a/fs/exfat/exfat_fs.h +++ b/fs/exfat/exfat_fs.h @@ -371,7 +371,7 @@ static inline bool exfat_is_last_sector_in_cluster(struct exfat_sb_info *sbi, static inline sector_t exfat_cluster_to_sector(struct exfat_sb_info *sbi, unsigned int clus) { - return ((clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) + + return ((sector_t)(clus - EXFAT_RESERVED_CLUSTERS) << sbi->sect_per_clus_bits) + sbi->data_start_sector; } diff --git a/fs/exfat/file.c b/fs/exfat/file.c index 3b7fea465fd4..a6a063830edc 100644 --- a/fs/exfat/file.c +++ b/fs/exfat/file.c @@ -176,7 +176,7 @@ int __exfat_truncate(struct inode *inode, loff_t new_size) ep2->dentry.stream.size = 0; } else { ep2->dentry.stream.valid_size = cpu_to_le64(new_size); - ep2->dentry.stream.size = ep->dentry.stream.valid_size; + ep2->dentry.stream.size = ep2->dentry.stream.valid_size; } if (new_size == 0) { diff --git a/fs/exfat/nls.c b/fs/exfat/nls.c index 57b5a7a4d1f7..a3c927501e67 100644 --- a/fs/exfat/nls.c +++ b/fs/exfat/nls.c @@ -495,7 +495,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb, struct exfat_uni_name *p_uniname, int *p_lossy) { int i, unilen, lossy = NLS_NAME_NO_LOSSY; - unsigned short upname[MAX_NAME_LENGTH + 1]; + __le16 upname[MAX_NAME_LENGTH + 1]; unsigned short *uniname = p_uniname->name; WARN_ON(!len); @@ -519,7 +519,7 @@ static int exfat_utf8_to_utf16(struct super_block *sb, exfat_wstrchr(bad_uni_chars, *uniname)) lossy |= NLS_NAME_LOSSY; - upname[i] = exfat_toupper(sb, *uniname); + upname[i] = cpu_to_le16(exfat_toupper(sb, *uniname)); uniname++; } @@ -597,7 +597,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb, struct exfat_uni_name *p_uniname, int *p_lossy) { int i = 0, unilen = 0, lossy = NLS_NAME_NO_LOSSY; - unsigned short upname[MAX_NAME_LENGTH + 1]; + __le16 upname[MAX_NAME_LENGTH + 1]; unsigned short *uniname = p_uniname->name; struct nls_table *nls = EXFAT_SB(sb)->nls_io; @@ -611,7 +611,7 @@ static int exfat_nls_to_ucs2(struct super_block *sb, exfat_wstrchr(bad_uni_chars, *uniname)) lossy |= NLS_NAME_LOSSY; - upname[unilen] = exfat_toupper(sb, *uniname); + upname[unilen] = cpu_to_le16(exfat_toupper(sb, *uniname)); uniname++; unilen++; } diff --git a/fs/io_uring.c b/fs/io_uring.c index 74bc4a04befa..32b0064f806e 100644 --- a/fs/io_uring.c +++ b/fs/io_uring.c @@ -605,6 +605,7 @@ enum { struct async_poll { struct io_poll_iocb poll; + struct io_poll_iocb *double_poll; struct io_wq_work work; }; @@ -4159,9 +4160,9 @@ static bool io_poll_rewait(struct io_kiocb *req, struct io_poll_iocb *poll) return false; } -static void io_poll_remove_double(struct io_kiocb *req) +static void io_poll_remove_double(struct io_kiocb *req, void *data) { - struct io_poll_iocb *poll = (struct io_poll_iocb *) req->io; + struct io_poll_iocb *poll = data; lockdep_assert_held(&req->ctx->completion_lock); @@ -4181,7 +4182,7 @@ static void io_poll_complete(struct io_kiocb *req, __poll_t mask, int error) { struct io_ring_ctx *ctx = req->ctx; - io_poll_remove_double(req); + io_poll_remove_double(req, req->io); req->poll.done = true; io_cqring_fill_event(req, error ? error : mangle_poll(mask)); io_commit_cqring(ctx); @@ -4224,21 +4225,21 @@ static int io_poll_double_wake(struct wait_queue_entry *wait, unsigned mode, int sync, void *key) { struct io_kiocb *req = wait->private; - struct io_poll_iocb *poll = (struct io_poll_iocb *) req->io; + struct io_poll_iocb *poll = req->apoll->double_poll; __poll_t mask = key_to_poll(key); /* for instances that support it check for an event match first: */ if (mask && !(mask & poll->events)) return 0; - if (req->poll.head) { + if (poll && poll->head) { bool done; - spin_lock(&req->poll.head->lock); - done = list_empty(&req->poll.wait.entry); + spin_lock(&poll->head->lock); + done = list_empty(&poll->wait.entry); if (!done) - list_del_init(&req->poll.wait.entry); - spin_unlock(&req->poll.head->lock); + list_del_init(&poll->wait.entry); + spin_unlock(&poll->head->lock); if (!done) __io_async_wake(req, poll, mask, io_poll_task_func); } @@ -4258,7 +4259,8 @@ static void io_init_poll_iocb(struct io_poll_iocb *poll, __poll_t events, } static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt, - struct wait_queue_head *head) + struct wait_queue_head *head, + struct io_poll_iocb **poll_ptr) { struct io_kiocb *req = pt->req; @@ -4269,7 +4271,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt, */ if (unlikely(poll->head)) { /* already have a 2nd entry, fail a third attempt */ - if (req->io) { + if (*poll_ptr) { pt->error = -EINVAL; return; } @@ -4281,7 +4283,7 @@ static void __io_queue_proc(struct io_poll_iocb *poll, struct io_poll_table *pt, io_init_poll_iocb(poll, req->poll.events, io_poll_double_wake); refcount_inc(&req->refs); poll->wait.private = req; - req->io = (void *) poll; + *poll_ptr = poll; } pt->error = 0; @@ -4293,8 +4295,9 @@ static void io_async_queue_proc(struct file *file, struct wait_queue_head *head, struct poll_table_struct *p) { struct io_poll_table *pt = container_of(p, struct io_poll_table, pt); + struct async_poll *apoll = pt->req->apoll; - __io_queue_proc(&pt->req->apoll->poll, pt, head); + __io_queue_proc(&apoll->poll, pt, head, &apoll->double_poll); } static void io_sq_thread_drop_mm(struct io_ring_ctx *ctx) @@ -4344,11 +4347,13 @@ static void io_async_task_func(struct callback_head *cb) } } + io_poll_remove_double(req, apoll->double_poll); spin_unlock_irq(&ctx->completion_lock); /* restore ->work in case we need to retry again */ if (req->flags & REQ_F_WORK_INITIALIZED) memcpy(&req->work, &apoll->work, sizeof(req->work)); + kfree(apoll->double_poll); kfree(apoll); if (!canceled) { @@ -4436,7 +4441,6 @@ static bool io_arm_poll_handler(struct io_kiocb *req) struct async_poll *apoll; struct io_poll_table ipt; __poll_t mask, ret; - bool had_io; if (!req->file || !file_can_poll(req->file)) return false; @@ -4448,11 +4452,11 @@ static bool io_arm_poll_handler(struct io_kiocb *req) apoll = kmalloc(sizeof(*apoll), GFP_ATOMIC); if (unlikely(!apoll)) return false; + apoll->double_poll = NULL; req->flags |= REQ_F_POLLED; if (req->flags & REQ_F_WORK_INITIALIZED) memcpy(&apoll->work, &req->work, sizeof(req->work)); - had_io = req->io != NULL; io_get_req_task(req); req->apoll = apoll; @@ -4470,13 +4474,11 @@ static bool io_arm_poll_handler(struct io_kiocb *req) ret = __io_arm_poll_handler(req, &apoll->poll, &ipt, mask, io_async_wake); if (ret) { - ipt.error = 0; - /* only remove double add if we did it here */ - if (!had_io) - io_poll_remove_double(req); + io_poll_remove_double(req, apoll->double_poll); spin_unlock_irq(&ctx->completion_lock); if (req->flags & REQ_F_WORK_INITIALIZED) memcpy(&req->work, &apoll->work, sizeof(req->work)); + kfree(apoll->double_poll); kfree(apoll); return false; } @@ -4507,11 +4509,13 @@ static bool io_poll_remove_one(struct io_kiocb *req) bool do_complete; if (req->opcode == IORING_OP_POLL_ADD) { - io_poll_remove_double(req); + io_poll_remove_double(req, req->io); do_complete = __io_poll_remove_one(req, &req->poll); } else { struct async_poll *apoll = req->apoll; + io_poll_remove_double(req, apoll->double_poll); + /* non-poll requests have submit ref still */ do_complete = __io_poll_remove_one(req, &apoll->poll); if (do_complete) { @@ -4524,6 +4528,7 @@ static bool io_poll_remove_one(struct io_kiocb *req) if (req->flags & REQ_F_WORK_INITIALIZED) memcpy(&req->work, &apoll->work, sizeof(req->work)); + kfree(apoll->double_poll); kfree(apoll); } } @@ -4624,7 +4629,7 @@ static void io_poll_queue_proc(struct file *file, struct wait_queue_head *head, { struct io_poll_table *pt = container_of(p, struct io_poll_table, pt); - __io_queue_proc(&pt->req->poll, pt, head); + __io_queue_proc(&pt->req->poll, pt, head, (struct io_poll_iocb **) &pt->req->io); } static int io_poll_add_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) @@ -4732,7 +4737,9 @@ static int io_timeout_remove_prep(struct io_kiocb *req, { if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) return -EINVAL; - if (sqe->flags || sqe->ioprio || sqe->buf_index || sqe->len) + if (unlikely(req->flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT))) + return -EINVAL; + if (sqe->ioprio || sqe->buf_index || sqe->len) return -EINVAL; req->timeout.addr = READ_ONCE(sqe->addr); @@ -4910,8 +4917,9 @@ static int io_async_cancel_prep(struct io_kiocb *req, { if (unlikely(req->ctx->flags & IORING_SETUP_IOPOLL)) return -EINVAL; - if (sqe->flags || sqe->ioprio || sqe->off || sqe->len || - sqe->cancel_flags) + if (unlikely(req->flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT))) + return -EINVAL; + if (sqe->ioprio || sqe->off || sqe->len || sqe->cancel_flags) return -EINVAL; req->cancel.addr = READ_ONCE(sqe->addr); @@ -4929,7 +4937,9 @@ static int io_async_cancel(struct io_kiocb *req) static int io_files_update_prep(struct io_kiocb *req, const struct io_uring_sqe *sqe) { - if (sqe->flags || sqe->ioprio || sqe->rw_flags) + if (unlikely(req->flags & (REQ_F_FIXED_FILE | REQ_F_BUFFER_SELECT))) + return -EINVAL; + if (sqe->ioprio || sqe->rw_flags) return -EINVAL; req->files_update.offset = READ_ONCE(sqe->off); @@ -5720,6 +5730,7 @@ fail_req: * Never try inline submit of IOSQE_ASYNC is set, go straight * to async execution. */ + io_req_init_async(req); req->work.flags |= IO_WQ_WORK_CONCURRENT; io_queue_async_work(req); } else { diff --git a/fs/nfsd/nfs4state.c b/fs/nfsd/nfs4state.c index cce2510b2cca..c9056316a0b3 100644 --- a/fs/nfsd/nfs4state.c +++ b/fs/nfsd/nfs4state.c @@ -507,6 +507,17 @@ find_any_file(struct nfs4_file *f) return ret; } +static struct nfsd_file *find_deleg_file(struct nfs4_file *f) +{ + struct nfsd_file *ret = NULL; + + spin_lock(&f->fi_lock); + if (f->fi_deleg_file) + ret = nfsd_file_get(f->fi_deleg_file); + spin_unlock(&f->fi_lock); + return ret; +} + static atomic_long_t num_delegations; unsigned long max_delegations; @@ -2444,6 +2455,8 @@ static int nfs4_show_open(struct seq_file *s, struct nfs4_stid *st) oo = ols->st_stateowner; nf = st->sc_file; file = find_any_file(nf); + if (!file) + return 0; seq_printf(s, "- "); nfs4_show_stateid(s, &st->sc_stateid); @@ -2481,6 +2494,8 @@ static int nfs4_show_lock(struct seq_file *s, struct nfs4_stid *st) oo = ols->st_stateowner; nf = st->sc_file; file = find_any_file(nf); + if (!file) + return 0; seq_printf(s, "- "); nfs4_show_stateid(s, &st->sc_stateid); @@ -2513,7 +2528,9 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) ds = delegstateid(st); nf = st->sc_file; - file = nf->fi_deleg_file; + file = find_deleg_file(nf); + if (!file) + return 0; seq_printf(s, "- "); nfs4_show_stateid(s, &st->sc_stateid); @@ -2529,6 +2546,7 @@ static int nfs4_show_deleg(struct seq_file *s, struct nfs4_stid *st) seq_printf(s, ", "); nfs4_show_fname(s, file); seq_printf(s, " }\n"); + nfsd_file_put(file); return 0; } diff --git a/fs/squashfs/block.c b/fs/squashfs/block.c index 64f61330564a..76bb1c846845 100644 --- a/fs/squashfs/block.c +++ b/fs/squashfs/block.c @@ -175,7 +175,7 @@ int squashfs_read_data(struct super_block *sb, u64 index, int length, /* Extract the length of the metadata block */ data = page_address(bvec->bv_page) + bvec->bv_offset; length = data[offset]; - if (offset <= bvec->bv_len - 1) { + if (offset < bvec->bv_len - 1) { length |= data[offset + 1] << 8; } else { if (WARN_ON_ONCE(!bio_next_segment(bio, &iter_all))) { diff --git a/fs/zonefs/super.c b/fs/zonefs/super.c index 07bc42d62673..abfb17f88f9a 100644 --- a/fs/zonefs/super.c +++ b/fs/zonefs/super.c @@ -607,14 +607,14 @@ static ssize_t zonefs_file_dio_append(struct kiocb *iocb, struct iov_iter *from) int nr_pages; ssize_t ret; - nr_pages = iov_iter_npages(from, BIO_MAX_PAGES); - if (!nr_pages) - return 0; - max = queue_max_zone_append_sectors(bdev_get_queue(bdev)); max = ALIGN_DOWN(max << SECTOR_SHIFT, inode->i_sb->s_blocksize); iov_iter_truncate(from, max); + nr_pages = iov_iter_npages(from, BIO_MAX_PAGES); + if (!nr_pages) + return 0; + bio = bio_alloc_bioset(GFP_NOFS, nr_pages, &fs_bio_set); if (!bio) return -ENOMEM; @@ -1119,7 +1119,7 @@ static int zonefs_create_zgroup(struct zonefs_zone_data *zd, char *file_name; struct dentry *dir; unsigned int n = 0; - int ret = -ENOMEM; + int ret; /* If the group is empty, there is nothing to do */ if (!zd->nr_zones[type]) @@ -1135,8 +1135,10 @@ static int zonefs_create_zgroup(struct zonefs_zone_data *zd, zgroup_name = "seq"; dir = zonefs_create_inode(sb->s_root, zgroup_name, NULL, type); - if (!dir) + if (!dir) { + ret = -ENOMEM; goto free; + } /* * The first zone contains the super block: skip it. @@ -1174,8 +1176,10 @@ static int zonefs_create_zgroup(struct zonefs_zone_data *zd, * Use the file number within its group as file name. */ snprintf(file_name, ZONEFS_NAME_MAX - 1, "%u", n); - if (!zonefs_create_inode(dir, file_name, zone, type)) + if (!zonefs_create_inode(dir, file_name, zone, type)) { + ret = -ENOMEM; goto free; + } n++; } diff --git a/include/linux/device-mapper.h b/include/linux/device-mapper.h index 8750f2dc5613..73dec4b5d5be 100644 --- a/include/linux/device-mapper.h +++ b/include/linux/device-mapper.h @@ -426,6 +426,7 @@ const char *dm_device_name(struct mapped_device *md); int dm_copy_name_and_uuid(struct mapped_device *md, char *name, char *uuid); struct gendisk *dm_disk(struct mapped_device *md); int dm_suspended(struct dm_target *ti); +int dm_post_suspending(struct dm_target *ti); int dm_noflush_suspending(struct dm_target *ti); void dm_accept_partial_bio(struct bio *bio, unsigned n_sectors); union map_info *dm_get_rq_mapinfo(struct request *rq); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index b8b8963f8bb9..ee328cf80bd9 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -56,7 +56,7 @@ struct property_entry; * on a bus (or read from them). Apart from two basic transfer functions to * transmit one message at a time, a more complex version can be used to * transmit an arbitrary number of messages without interruption. - * @count must be be less than 64k since msg.len is u16. + * @count must be less than 64k since msg.len is u16. */ int i2c_transfer_buffer_flags(const struct i2c_client *client, char *buf, int count, u16 flags); diff --git a/include/linux/io-mapping.h b/include/linux/io-mapping.h index 0beaa3eba155..c75e4d3d8833 100644 --- a/include/linux/io-mapping.h +++ b/include/linux/io-mapping.h @@ -107,9 +107,12 @@ io_mapping_init_wc(struct io_mapping *iomap, resource_size_t base, unsigned long size) { + iomap->iomem = ioremap_wc(base, size); + if (!iomap->iomem) + return NULL; + iomap->base = base; iomap->size = size; - iomap->iomem = ioremap_wc(base, size); #if defined(pgprot_noncached_wc) /* archs can't agree on a name ... */ iomap->prot = pgprot_noncached_wc(PAGE_KERNEL); #elif defined(pgprot_writecombine) diff --git a/include/linux/rhashtable.h b/include/linux/rhashtable.h index 70ebef866cc8..d3432ee65de7 100644 --- a/include/linux/rhashtable.h +++ b/include/linux/rhashtable.h @@ -33,7 +33,7 @@ * of two or more hash tables when the rhashtable is being resized. * The end of the chain is marked with a special nulls marks which has * the least significant bit set but otherwise stores the address of - * the hash bucket. This allows us to be be sure we've found the end + * the hash bucket. This allows us to be sure we've found the end * of the right list. * The value stored in the hash bucket has BIT(0) used as a lock bit. * This bit must be atomically set before any changes are made to diff --git a/include/linux/tcp.h b/include/linux/tcp.h index 9aac824c523c..a1bbaa1c1a3a 100644 --- a/include/linux/tcp.h +++ b/include/linux/tcp.h @@ -220,7 +220,9 @@ struct tcp_sock { } rack; u16 advmss; /* Advertised MSS */ u8 compressed_ack; - u8 dup_ack_counter; + u8 dup_ack_counter:2, + tlp_retrans:1, /* TLP is a retransmission */ + unused:5; u32 chrono_start; /* Start time in jiffies of a TCP chrono */ u32 chrono_stat[3]; /* Time in jiffies for chrono_stat stats */ u8 chrono_type:2, /* current chronograph type */ @@ -243,7 +245,7 @@ struct tcp_sock { save_syn:1, /* Save headers of SYN packet */ is_cwnd_limited:1,/* forward progress limited by snd_cwnd? */ syn_smc:1; /* SYN includes SMC */ - u32 tlp_high_seq; /* snd_nxt at the time of TLP retransmit. */ + u32 tlp_high_seq; /* snd_nxt at the time of TLP */ u32 tcp_tx_delay; /* delay (in usec) added to TX packets */ u64 tcp_wstamp_ns; /* departure time for next sent data packet */ diff --git a/include/linux/xattr.h b/include/linux/xattr.h index 47eaa34f8761..c5afaf8ca7a2 100644 --- a/include/linux/xattr.h +++ b/include/linux/xattr.h @@ -15,6 +15,7 @@ #include <linux/slab.h> #include <linux/types.h> #include <linux/spinlock.h> +#include <linux/mm.h> #include <uapi/linux/xattr.h> struct inode; @@ -94,7 +95,7 @@ static inline void simple_xattrs_free(struct simple_xattrs *xattrs) list_for_each_entry_safe(xattr, node, &xattrs->head, list) { kfree(xattr->name); - kfree(xattr); + kvfree(xattr); } } diff --git a/include/net/flow_offload.h b/include/net/flow_offload.h index 6315324b9dc2..3eaf25f68b79 100644 --- a/include/net/flow_offload.h +++ b/include/net/flow_offload.h @@ -5,7 +5,6 @@ #include <linux/list.h> #include <linux/netlink.h> #include <net/flow_dissector.h> -#include <linux/rhashtable.h> struct flow_match { struct flow_dissector *dissector; diff --git a/include/sound/rt5670.h b/include/sound/rt5670.h index f9024c7a1600..02e1d7778354 100644 --- a/include/sound/rt5670.h +++ b/include/sound/rt5670.h @@ -12,6 +12,7 @@ struct rt5670_platform_data { int jd_mode; bool in2_diff; bool dev_gpio; + bool gpio1_is_ext_spk_en; bool dmic_en; unsigned int dmic1_data_pin; diff --git a/include/sound/soc-dai.h b/include/sound/soc-dai.h index 212257e84fac..71e178c89793 100644 --- a/include/sound/soc-dai.h +++ b/include/sound/soc-dai.h @@ -161,6 +161,7 @@ void snd_soc_dai_resume(struct snd_soc_dai *dai); int snd_soc_dai_compress_new(struct snd_soc_dai *dai, struct snd_soc_pcm_runtime *rtd, int num); bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int stream); +void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link); void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action); static inline void snd_soc_dai_activate(struct snd_soc_dai *dai, diff --git a/include/sound/soc.h b/include/sound/soc.h index 2756f9bcac3e..3ce7f0f5aa92 100644 --- a/include/sound/soc.h +++ b/include/sound/soc.h @@ -444,6 +444,8 @@ int devm_snd_soc_register_component(struct device *dev, const struct snd_soc_component_driver *component_driver, struct snd_soc_dai_driver *dai_drv, int num_dai); void snd_soc_unregister_component(struct device *dev); +void snd_soc_unregister_component_by_driver(struct device *dev, + const struct snd_soc_component_driver *component_driver); struct snd_soc_component *snd_soc_lookup_component_nolocked(struct device *dev, const char *driver_name); struct snd_soc_component *snd_soc_lookup_component(struct device *dev, diff --git a/mm/hugetlb.c b/mm/hugetlb.c index fab4485b9e52..590111ea6975 100644 --- a/mm/hugetlb.c +++ b/mm/hugetlb.c @@ -45,7 +45,10 @@ int hugetlb_max_hstate __read_mostly; unsigned int default_hstate_idx; struct hstate hstates[HUGE_MAX_HSTATE]; +#ifdef CONFIG_CMA static struct cma *hugetlb_cma[MAX_NUMNODES]; +#endif +static unsigned long hugetlb_cma_size __initdata; /* * Minimum page order among possible hugepage sizes, set to a proper value @@ -1235,9 +1238,10 @@ static void free_gigantic_page(struct page *page, unsigned int order) * If the page isn't allocated using the cma allocator, * cma_release() returns false. */ - if (IS_ENABLED(CONFIG_CMA) && - cma_release(hugetlb_cma[page_to_nid(page)], page, 1 << order)) +#ifdef CONFIG_CMA + if (cma_release(hugetlb_cma[page_to_nid(page)], page, 1 << order)) return; +#endif free_contig_range(page_to_pfn(page), 1 << order); } @@ -1248,7 +1252,8 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask, { unsigned long nr_pages = 1UL << huge_page_order(h); - if (IS_ENABLED(CONFIG_CMA)) { +#ifdef CONFIG_CMA + { struct page *page; int node; @@ -1262,6 +1267,7 @@ static struct page *alloc_gigantic_page(struct hstate *h, gfp_t gfp_mask, return page; } } +#endif return alloc_contig_pages(nr_pages, gfp_mask, nid, nodemask); } @@ -2571,7 +2577,7 @@ static void __init hugetlb_hstate_alloc_pages(struct hstate *h) for (i = 0; i < h->max_huge_pages; ++i) { if (hstate_is_gigantic(h)) { - if (IS_ENABLED(CONFIG_CMA) && hugetlb_cma[0]) { + if (hugetlb_cma_size) { pr_warn_once("HugeTLB: hugetlb_cma is enabled, skip boot time allocation\n"); break; } @@ -5654,7 +5660,6 @@ void move_hugetlb_state(struct page *oldpage, struct page *newpage, int reason) } #ifdef CONFIG_CMA -static unsigned long hugetlb_cma_size __initdata; static bool cma_reserve_called __initdata; static int __init cmdline_parse_hugetlb_cma(char *p) diff --git a/mm/khugepaged.c b/mm/khugepaged.c index b043c40a21d4..700f5160f3e4 100644 --- a/mm/khugepaged.c +++ b/mm/khugepaged.c @@ -958,6 +958,9 @@ static int hugepage_vma_revalidate(struct mm_struct *mm, unsigned long address, return SCAN_ADDRESS_RANGE; if (!hugepage_vma_check(vma, vma->vm_flags)) return SCAN_VMA_CHECK; + /* Anon VMA expected */ + if (!vma->anon_vma || vma->vm_ops) + return SCAN_VMA_CHECK; return 0; } diff --git a/mm/memcontrol.c b/mm/memcontrol.c index 19622328e4b5..13f559af1ab6 100644 --- a/mm/memcontrol.c +++ b/mm/memcontrol.c @@ -5669,7 +5669,6 @@ static void __mem_cgroup_clear_mc(void) if (!mem_cgroup_is_root(mc.to)) page_counter_uncharge(&mc.to->memory, mc.moved_swap); - mem_cgroup_id_get_many(mc.to, mc.moved_swap); css_put_many(&mc.to->css, mc.moved_swap); mc.moved_swap = 0; @@ -5860,7 +5859,8 @@ put: /* get_mctgt_type() gets the page */ ent = target.ent; if (!mem_cgroup_move_swap_account(ent, mc.from, mc.to)) { mc.precharge--; - /* we fixup refcnts and charges later. */ + mem_cgroup_id_get_many(mc.to, 1); + /* we fixup other refcnts and charges later. */ mc.moved_swap++; } break; @@ -7186,6 +7186,13 @@ static struct cftype memsw_files[] = { { }, /* terminate */ }; +/* + * If mem_cgroup_swap_init() is implemented as a subsys_initcall() + * instead of a core_initcall(), this could mean cgroup_memory_noswap still + * remains set to false even when memcg is disabled via "cgroup_disable=memory" + * boot parameter. This may result in premature OOPS inside + * mem_cgroup_get_nr_swap_pages() function in corner cases. + */ static int __init mem_cgroup_swap_init(void) { /* No memory control -> no swap control */ @@ -7200,6 +7207,6 @@ static int __init mem_cgroup_swap_init(void) return 0; } -subsys_initcall(mem_cgroup_swap_init); +core_initcall(mem_cgroup_swap_init); #endif /* CONFIG_MEMCG_SWAP */ diff --git a/mm/memory.c b/mm/memory.c index 87ec87cdc1ff..3ecad55103ad 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -1601,7 +1601,7 @@ int vm_insert_pages(struct vm_area_struct *vma, unsigned long addr, return insert_pages(vma, addr, pages, num, vma->vm_page_prot); #else unsigned long idx = 0, pgcount = *num; - int err; + int err = -EINVAL; for (; idx < pgcount; ++idx) { err = vm_insert_page(vma, addr + (PAGE_SIZE * idx), pages[idx]); diff --git a/mm/mmap.c b/mm/mmap.c index 59a4682ebf3f..8c7ca737a19b 100644 --- a/mm/mmap.c +++ b/mm/mmap.c @@ -2620,7 +2620,7 @@ static void unmap_region(struct mm_struct *mm, * Create a list of vma's touched by the unmap, removing them from the mm's * vma list as we go.. */ -static void +static bool detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, struct vm_area_struct *prev, unsigned long end) { @@ -2645,6 +2645,17 @@ detach_vmas_to_be_unmapped(struct mm_struct *mm, struct vm_area_struct *vma, /* Kill the cache */ vmacache_invalidate(mm); + + /* + * Do not downgrade mmap_lock if we are next to VM_GROWSDOWN or + * VM_GROWSUP VMA. Such VMAs can change their size under + * down_read(mmap_lock) and collide with the VMA we are about to unmap. + */ + if (vma && (vma->vm_flags & VM_GROWSDOWN)) + return false; + if (prev && (prev->vm_flags & VM_GROWSUP)) + return false; + return true; } /* @@ -2825,7 +2836,8 @@ int __do_munmap(struct mm_struct *mm, unsigned long start, size_t len, } /* Detach vmas from rbtree */ - detach_vmas_to_be_unmapped(mm, vma, prev, end); + if (!detach_vmas_to_be_unmapped(mm, vma, prev, end)) + downgrade = false; if (downgrade) mmap_write_downgrade(mm); diff --git a/mm/shmem.c b/mm/shmem.c index a0dbe62f8042..b2abca3f7f33 100644 --- a/mm/shmem.c +++ b/mm/shmem.c @@ -3178,7 +3178,7 @@ static int shmem_initxattrs(struct inode *inode, new_xattr->name = kmalloc(XATTR_SECURITY_PREFIX_LEN + len, GFP_KERNEL); if (!new_xattr->name) { - kfree(new_xattr); + kvfree(new_xattr); return -ENOMEM; } diff --git a/mm/slab_common.c b/mm/slab_common.c index 37d48a56431d..fe8b68482670 100644 --- a/mm/slab_common.c +++ b/mm/slab_common.c @@ -326,6 +326,14 @@ int slab_unmergeable(struct kmem_cache *s) if (s->refcount < 0) return 1; +#ifdef CONFIG_MEMCG_KMEM + /* + * Skip the dying kmem_cache. + */ + if (s->memcg_params.dying) + return 1; +#endif + return 0; } @@ -886,12 +894,15 @@ static int shutdown_memcg_caches(struct kmem_cache *s) return 0; } -static void flush_memcg_workqueue(struct kmem_cache *s) +static void memcg_set_kmem_cache_dying(struct kmem_cache *s) { spin_lock_irq(&memcg_kmem_wq_lock); s->memcg_params.dying = true; spin_unlock_irq(&memcg_kmem_wq_lock); +} +static void flush_memcg_workqueue(struct kmem_cache *s) +{ /* * SLAB and SLUB deactivate the kmem_caches through call_rcu. Make * sure all registered rcu callbacks have been invoked. @@ -923,10 +934,6 @@ static inline int shutdown_memcg_caches(struct kmem_cache *s) { return 0; } - -static inline void flush_memcg_workqueue(struct kmem_cache *s) -{ -} #endif /* CONFIG_MEMCG_KMEM */ void slab_kmem_cache_release(struct kmem_cache *s) @@ -944,8 +951,6 @@ void kmem_cache_destroy(struct kmem_cache *s) if (unlikely(!s)) return; - flush_memcg_workqueue(s); - get_online_cpus(); get_online_mems(); @@ -955,6 +960,22 @@ void kmem_cache_destroy(struct kmem_cache *s) if (s->refcount) goto out_unlock; +#ifdef CONFIG_MEMCG_KMEM + memcg_set_kmem_cache_dying(s); + + mutex_unlock(&slab_mutex); + + put_online_mems(); + put_online_cpus(); + + flush_memcg_workqueue(s); + + get_online_cpus(); + get_online_mems(); + + mutex_lock(&slab_mutex); +#endif + err = shutdown_memcg_caches(s); if (!err) err = shutdown_cache(s); diff --git a/net/ax25/af_ax25.c b/net/ax25/af_ax25.c index fd91cd34f25e..dec3f35467c9 100644 --- a/net/ax25/af_ax25.c +++ b/net/ax25/af_ax25.c @@ -1187,7 +1187,10 @@ static int __must_check ax25_connect(struct socket *sock, if (addr_len > sizeof(struct sockaddr_ax25) && fsa->fsa_ax25.sax25_ndigis != 0) { /* Valid number of digipeaters ? */ - if (fsa->fsa_ax25.sax25_ndigis < 1 || fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS) { + if (fsa->fsa_ax25.sax25_ndigis < 1 || + fsa->fsa_ax25.sax25_ndigis > AX25_MAX_DIGIS || + addr_len < sizeof(struct sockaddr_ax25) + + sizeof(ax25_address) * fsa->fsa_ax25.sax25_ndigis) { err = -EINVAL; goto out_release; } @@ -1507,7 +1510,10 @@ static int ax25_sendmsg(struct socket *sock, struct msghdr *msg, size_t len) struct full_sockaddr_ax25 *fsa = (struct full_sockaddr_ax25 *)usax; /* Valid number of digipeaters ? */ - if (usax->sax25_ndigis < 1 || usax->sax25_ndigis > AX25_MAX_DIGIS) { + if (usax->sax25_ndigis < 1 || + usax->sax25_ndigis > AX25_MAX_DIGIS || + addr_len < sizeof(struct sockaddr_ax25) + + sizeof(ax25_address) * usax->sax25_ndigis) { err = -EINVAL; goto out; } diff --git a/net/core/dev.c b/net/core/dev.c index 90b59fc50dc9..7a774ebf64e2 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -5601,7 +5601,7 @@ static void flush_backlog(struct work_struct *work) skb_queue_walk_safe(&sd->input_pkt_queue, skb, tmp) { if (skb->dev->reg_state == NETREG_UNREGISTERING) { __skb_unlink(skb, &sd->input_pkt_queue); - kfree_skb(skb); + dev_kfree_skb_irq(skb); input_queue_head_incr(sd); } } diff --git a/net/core/flow_offload.c b/net/core/flow_offload.c index b739cfab796e..2076219b8ba5 100644 --- a/net/core/flow_offload.c +++ b/net/core/flow_offload.c @@ -4,6 +4,7 @@ #include <net/flow_offload.h> #include <linux/rtnetlink.h> #include <linux/mutex.h> +#include <linux/rhashtable.h> struct flow_rule *flow_rule_alloc(unsigned int num_actions) { diff --git a/net/core/net-sysfs.c b/net/core/net-sysfs.c index e353b822bb15..7bd6440c63bf 100644 --- a/net/core/net-sysfs.c +++ b/net/core/net-sysfs.c @@ -1108,7 +1108,7 @@ static ssize_t tx_timeout_show(struct netdev_queue *queue, char *buf) trans_timeout = queue->trans_timeout; spin_unlock_irq(&queue->_xmit_lock); - return sprintf(buf, "%lu", trans_timeout); + return sprintf(buf, fmt_ulong, trans_timeout); } static unsigned int get_netdev_queue_index(struct netdev_queue *queue) diff --git a/net/core/rtnetlink.c b/net/core/rtnetlink.c index 9aedc15736ad..85a4b0101f76 100644 --- a/net/core/rtnetlink.c +++ b/net/core/rtnetlink.c @@ -3343,7 +3343,8 @@ replay: */ if (err < 0) { /* If device is not registered at all, free it now */ - if (dev->reg_state == NETREG_UNINITIALIZED) + if (dev->reg_state == NETREG_UNINITIALIZED || + dev->reg_state == NETREG_UNREGISTERED) free_netdev(dev); goto out; } diff --git a/net/core/sock_reuseport.c b/net/core/sock_reuseport.c index adcb3aea576d..bbdd3c7b6cb5 100644 --- a/net/core/sock_reuseport.c +++ b/net/core/sock_reuseport.c @@ -101,6 +101,7 @@ static struct sock_reuseport *reuseport_grow(struct sock_reuseport *reuse) more_reuse->prog = reuse->prog; more_reuse->reuseport_id = reuse->reuseport_id; more_reuse->bind_inany = reuse->bind_inany; + more_reuse->has_conns = reuse->has_conns; memcpy(more_reuse->socks, reuse->socks, reuse->num_socks * sizeof(struct sock *)); diff --git a/net/hsr/hsr_forward.c b/net/hsr/hsr_forward.c index ed13760463de..1ea17752fffc 100644 --- a/net/hsr/hsr_forward.c +++ b/net/hsr/hsr_forward.c @@ -120,13 +120,18 @@ static struct sk_buff *frame_get_stripped_skb(struct hsr_frame_info *frame, return skb_clone(frame->skb_std, GFP_ATOMIC); } -static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, - struct hsr_port *port, u8 proto_version) +static struct sk_buff *hsr_fill_tag(struct sk_buff *skb, + struct hsr_frame_info *frame, + struct hsr_port *port, u8 proto_version) { struct hsr_ethhdr *hsr_ethhdr; int lane_id; int lsdu_size; + /* pad to minimum packet size which is 60 + 6 (HSR tag) */ + if (skb_put_padto(skb, ETH_ZLEN + HSR_HLEN)) + return NULL; + if (port->type == HSR_PT_SLAVE_A) lane_id = 0; else @@ -144,6 +149,8 @@ static void hsr_fill_tag(struct sk_buff *skb, struct hsr_frame_info *frame, hsr_ethhdr->hsr_tag.encap_proto = hsr_ethhdr->ethhdr.h_proto; hsr_ethhdr->ethhdr.h_proto = htons(proto_version ? ETH_P_HSR : ETH_P_PRP); + + return skb; } static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, @@ -172,9 +179,10 @@ static struct sk_buff *create_tagged_skb(struct sk_buff *skb_o, memmove(dst, src, movelen); skb_reset_mac_header(skb); - hsr_fill_tag(skb, frame, port, port->hsr->prot_version); - - return skb; + /* skb_put_padto free skb on error and hsr_fill_tag returns NULL in + * that case + */ + return hsr_fill_tag(skb, frame, port, port->hsr->prot_version); } /* If the original frame was an HSR tagged frame, just clone it to be sent diff --git a/net/hsr/hsr_framereg.c b/net/hsr/hsr_framereg.c index 03b891904314..530de24b1fb5 100644 --- a/net/hsr/hsr_framereg.c +++ b/net/hsr/hsr_framereg.c @@ -325,7 +325,8 @@ void hsr_addr_subst_dest(struct hsr_node *node_src, struct sk_buff *skb, if (port->type != node_dst->addr_B_port) return; - ether_addr_copy(eth_hdr(skb)->h_dest, node_dst->macaddress_B); + if (is_valid_ether_addr(node_dst->macaddress_B)) + ether_addr_copy(eth_hdr(skb)->h_dest, node_dst->macaddress_B); } void hsr_register_frame_in(struct hsr_node *node, struct hsr_port *port, diff --git a/net/ipv4/tcp_input.c b/net/ipv4/tcp_input.c index 9615e72656d1..518f04355fbf 100644 --- a/net/ipv4/tcp_input.c +++ b/net/ipv4/tcp_input.c @@ -3488,10 +3488,8 @@ static void tcp_replace_ts_recent(struct tcp_sock *tp, u32 seq) } } -/* This routine deals with acks during a TLP episode. - * We mark the end of a TLP episode on receiving TLP dupack or when - * ack is after tlp_high_seq. - * Ref: loss detection algorithm in draft-dukkipati-tcpm-tcp-loss-probe. +/* This routine deals with acks during a TLP episode and ends an episode by + * resetting tlp_high_seq. Ref: TLP algorithm in draft-ietf-tcpm-rack */ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) { @@ -3500,7 +3498,10 @@ static void tcp_process_tlp_ack(struct sock *sk, u32 ack, int flag) if (before(ack, tp->tlp_high_seq)) return; - if (flag & FLAG_DSACKING_ACK) { + if (!tp->tlp_retrans) { + /* TLP of new data has been acknowledged */ + tp->tlp_high_seq = 0; + } else if (flag & FLAG_DSACKING_ACK) { /* This DSACK means original and TLP probe arrived; no loss */ tp->tlp_high_seq = 0; } else if (after(ack, tp->tlp_high_seq)) { diff --git a/net/ipv4/tcp_output.c b/net/ipv4/tcp_output.c index 5f5b2f0b0e60..0bc05d68cd74 100644 --- a/net/ipv4/tcp_output.c +++ b/net/ipv4/tcp_output.c @@ -2624,6 +2624,11 @@ void tcp_send_loss_probe(struct sock *sk) int pcount; int mss = tcp_current_mss(sk); + /* At most one outstanding TLP */ + if (tp->tlp_high_seq) + goto rearm_timer; + + tp->tlp_retrans = 0; skb = tcp_send_head(sk); if (skb && tcp_snd_wnd_test(tp, skb, mss)) { pcount = tp->packets_out; @@ -2641,10 +2646,6 @@ void tcp_send_loss_probe(struct sock *sk) return; } - /* At most one outstanding TLP retransmission. */ - if (tp->tlp_high_seq) - goto rearm_timer; - if (skb_still_in_host_queue(sk, skb)) goto rearm_timer; @@ -2666,10 +2667,12 @@ void tcp_send_loss_probe(struct sock *sk) if (__tcp_retransmit_skb(sk, skb, 1)) goto rearm_timer; + tp->tlp_retrans = 1; + +probe_sent: /* Record snd_nxt for loss detection. */ tp->tlp_high_seq = tp->snd_nxt; -probe_sent: NET_INC_STATS(sock_net(sk), LINUX_MIB_TCPLOSSPROBES); /* Reset s.t. tcp_rearm_rto will restart timer from now */ inet_csk(sk)->icsk_pending = 0; diff --git a/net/ipv4/udp.c b/net/ipv4/udp.c index 1b7ebbcae497..4077d589b72e 100644 --- a/net/ipv4/udp.c +++ b/net/ipv4/udp.c @@ -416,7 +416,7 @@ static struct sock *udp4_lib_lookup2(struct net *net, struct udp_hslot *hslot2, struct sk_buff *skb) { - struct sock *sk, *result; + struct sock *sk, *result, *reuseport_result; int score, badness; u32 hash = 0; @@ -426,17 +426,20 @@ static struct sock *udp4_lib_lookup2(struct net *net, score = compute_score(sk, net, saddr, sport, daddr, hnum, dif, sdif); if (score > badness) { + reuseport_result = NULL; + if (sk->sk_reuseport && sk->sk_state != TCP_ESTABLISHED) { hash = udp_ehashfn(net, daddr, hnum, saddr, sport); - result = reuseport_select_sock(sk, hash, skb, - sizeof(struct udphdr)); - if (result && !reuseport_has_conns(sk, false)) - return result; + reuseport_result = reuseport_select_sock(sk, hash, skb, + sizeof(struct udphdr)); + if (reuseport_result && !reuseport_has_conns(sk, false)) + return reuseport_result; } + + result = reuseport_result ? : sk; badness = score; - result = sk; } } return result; @@ -2051,7 +2054,7 @@ static int udp_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb) /* * UDP-Lite specific tests, ignored on UDP sockets */ - if ((is_udplite & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { + if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { /* * MIB statistics other than incrementing the error count are diff --git a/net/ipv6/ip6_gre.c b/net/ipv6/ip6_gre.c index 6532bde82b40..3a57fb9ce049 100644 --- a/net/ipv6/ip6_gre.c +++ b/net/ipv6/ip6_gre.c @@ -1562,17 +1562,18 @@ static void ip6gre_destroy_tunnels(struct net *net, struct list_head *head) static int __net_init ip6gre_init_net(struct net *net) { struct ip6gre_net *ign = net_generic(net, ip6gre_net_id); + struct net_device *ndev; int err; if (!net_has_fallback_tunnels(net)) return 0; - ign->fb_tunnel_dev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", - NET_NAME_UNKNOWN, - ip6gre_tunnel_setup); - if (!ign->fb_tunnel_dev) { + ndev = alloc_netdev(sizeof(struct ip6_tnl), "ip6gre0", + NET_NAME_UNKNOWN, ip6gre_tunnel_setup); + if (!ndev) { err = -ENOMEM; goto err_alloc_dev; } + ign->fb_tunnel_dev = ndev; dev_net_set(ign->fb_tunnel_dev, net); /* FB netdevice is special: we have one, and only one per netns. * Allowing to move it to another netns is clearly unsafe. @@ -1592,7 +1593,7 @@ static int __net_init ip6gre_init_net(struct net *net) return 0; err_reg_dev: - free_netdev(ign->fb_tunnel_dev); + free_netdev(ndev); err_alloc_dev: return err; } diff --git a/net/ipv6/udp.c b/net/ipv6/udp.c index 7d4151747340..a8d74f44056a 100644 --- a/net/ipv6/udp.c +++ b/net/ipv6/udp.c @@ -148,7 +148,7 @@ static struct sock *udp6_lib_lookup2(struct net *net, int dif, int sdif, struct udp_hslot *hslot2, struct sk_buff *skb) { - struct sock *sk, *result; + struct sock *sk, *result, *reuseport_result; int score, badness; u32 hash = 0; @@ -158,17 +158,20 @@ static struct sock *udp6_lib_lookup2(struct net *net, score = compute_score(sk, net, saddr, sport, daddr, hnum, dif, sdif); if (score > badness) { + reuseport_result = NULL; + if (sk->sk_reuseport && sk->sk_state != TCP_ESTABLISHED) { hash = udp6_ehashfn(net, daddr, hnum, saddr, sport); - result = reuseport_select_sock(sk, hash, skb, - sizeof(struct udphdr)); - if (result && !reuseport_has_conns(sk, false)) - return result; + reuseport_result = reuseport_select_sock(sk, hash, skb, + sizeof(struct udphdr)); + if (reuseport_result && !reuseport_has_conns(sk, false)) + return reuseport_result; } - result = sk; + + result = reuseport_result ? : sk; badness = score; } } @@ -643,7 +646,7 @@ static int udpv6_queue_rcv_one_skb(struct sock *sk, struct sk_buff *skb) /* * UDP-Lite specific tests, ignored on UDP sockets (see net/ipv4/udp.c). */ - if ((is_udplite & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { + if ((up->pcflag & UDPLITE_RECV_CC) && UDP_SKB_CB(skb)->partial_cov) { if (up->pcrlen == 0) { /* full coverage was set */ net_dbg_ratelimited("UDPLITE6: partial coverage %d while full coverage %d requested\n", diff --git a/net/netfilter/ipvs/ip_vs_sync.c b/net/netfilter/ipvs/ip_vs_sync.c index 605e0f68f8bd..2b8abbfe018c 100644 --- a/net/netfilter/ipvs/ip_vs_sync.c +++ b/net/netfilter/ipvs/ip_vs_sync.c @@ -1717,6 +1717,8 @@ static int sync_thread_backup(void *data) { struct ip_vs_sync_thread_data *tinfo = data; struct netns_ipvs *ipvs = tinfo->ipvs; + struct sock *sk = tinfo->sock->sk; + struct udp_sock *up = udp_sk(sk); int len; pr_info("sync thread started: state = BACKUP, mcast_ifn = %s, " @@ -1724,12 +1726,14 @@ static int sync_thread_backup(void *data) ipvs->bcfg.mcast_ifn, ipvs->bcfg.syncid, tinfo->id); while (!kthread_should_stop()) { - wait_event_interruptible(*sk_sleep(tinfo->sock->sk), - !skb_queue_empty(&tinfo->sock->sk->sk_receive_queue) - || kthread_should_stop()); + wait_event_interruptible(*sk_sleep(sk), + !skb_queue_empty_lockless(&sk->sk_receive_queue) || + !skb_queue_empty_lockless(&up->reader_queue) || + kthread_should_stop()); /* do we have data now? */ - while (!skb_queue_empty(&(tinfo->sock->sk->sk_receive_queue))) { + while (!skb_queue_empty_lockless(&sk->sk_receive_queue) || + !skb_queue_empty_lockless(&up->reader_queue)) { len = ip_vs_receive(tinfo->sock, tinfo->buf, ipvs->bcfg.sync_maxlen); if (len <= 0) { diff --git a/net/netfilter/nf_tables_api.c b/net/netfilter/nf_tables_api.c index 7647ecfa0d40..88325b264737 100644 --- a/net/netfilter/nf_tables_api.c +++ b/net/netfilter/nf_tables_api.c @@ -188,24 +188,6 @@ static void nft_netdev_unregister_hooks(struct net *net, nf_unregister_net_hook(net, &hook->ops); } -static int nft_register_basechain_hooks(struct net *net, int family, - struct nft_base_chain *basechain) -{ - if (family == NFPROTO_NETDEV) - return nft_netdev_register_hooks(net, &basechain->hook_list); - - return nf_register_net_hook(net, &basechain->ops); -} - -static void nft_unregister_basechain_hooks(struct net *net, int family, - struct nft_base_chain *basechain) -{ - if (family == NFPROTO_NETDEV) - nft_netdev_unregister_hooks(net, &basechain->hook_list); - else - nf_unregister_net_hook(net, &basechain->ops); -} - static int nf_tables_register_hook(struct net *net, const struct nft_table *table, struct nft_chain *chain) @@ -223,7 +205,10 @@ static int nf_tables_register_hook(struct net *net, if (basechain->type->ops_register) return basechain->type->ops_register(net, ops); - return nft_register_basechain_hooks(net, table->family, basechain); + if (table->family == NFPROTO_NETDEV) + return nft_netdev_register_hooks(net, &basechain->hook_list); + + return nf_register_net_hook(net, &basechain->ops); } static void nf_tables_unregister_hook(struct net *net, @@ -242,7 +227,10 @@ static void nf_tables_unregister_hook(struct net *net, if (basechain->type->ops_unregister) return basechain->type->ops_unregister(net, ops); - nft_unregister_basechain_hooks(net, table->family, basechain); + if (table->family == NFPROTO_NETDEV) + nft_netdev_unregister_hooks(net, &basechain->hook_list); + else + nf_unregister_net_hook(net, &basechain->ops); } static int nft_trans_table_add(struct nft_ctx *ctx, int msg_type) @@ -832,8 +820,7 @@ static void nft_table_disable(struct net *net, struct nft_table *table, u32 cnt) if (cnt && i++ == cnt) break; - nft_unregister_basechain_hooks(net, table->family, - nft_base_chain(chain)); + nf_tables_unregister_hook(net, table, chain); } } @@ -848,8 +835,7 @@ static int nf_tables_table_enable(struct net *net, struct nft_table *table) if (!nft_is_base_chain(chain)) continue; - err = nft_register_basechain_hooks(net, table->family, - nft_base_chain(chain)); + err = nf_tables_register_hook(net, table, chain); if (err < 0) goto err_register_hooks; @@ -894,11 +880,12 @@ static int nf_tables_updtable(struct nft_ctx *ctx) nft_trans_table_enable(trans) = false; } else if (!(flags & NFT_TABLE_F_DORMANT) && ctx->table->flags & NFT_TABLE_F_DORMANT) { + ctx->table->flags &= ~NFT_TABLE_F_DORMANT; ret = nf_tables_table_enable(ctx->net, ctx->table); - if (ret >= 0) { - ctx->table->flags &= ~NFT_TABLE_F_DORMANT; + if (ret >= 0) nft_trans_table_enable(trans) = true; - } + else + ctx->table->flags |= NFT_TABLE_F_DORMANT; } if (ret < 0) goto err; diff --git a/net/nfc/nci/core.c b/net/nfc/nci/core.c index 7cd524884304..78ea8c94dcba 100644 --- a/net/nfc/nci/core.c +++ b/net/nfc/nci/core.c @@ -1228,10 +1228,13 @@ int nci_register_device(struct nci_dev *ndev) rc = nfc_register_device(ndev->nfc_dev); if (rc) - goto destroy_rx_wq_exit; + goto destroy_tx_wq_exit; goto exit; +destroy_tx_wq_exit: + destroy_workqueue(ndev->tx_wq); + destroy_rx_wq_exit: destroy_workqueue(ndev->rx_wq); diff --git a/net/qrtr/qrtr.c b/net/qrtr/qrtr.c index 24a8c3c6da0d..300a104b9a0f 100644 --- a/net/qrtr/qrtr.c +++ b/net/qrtr/qrtr.c @@ -1180,6 +1180,7 @@ static int qrtr_release(struct socket *sock) sk->sk_state_change(sk); sock_set_flag(sk, SOCK_DEAD); + sock_orphan(sk); sock->sk = NULL; if (!sock_flag(sk, SOCK_ZAPPED)) diff --git a/net/rxrpc/recvmsg.c b/net/rxrpc/recvmsg.c index 2989742a4aa1..490b1927215c 100644 --- a/net/rxrpc/recvmsg.c +++ b/net/rxrpc/recvmsg.c @@ -543,7 +543,7 @@ try_again: list_empty(&rx->recvmsg_q) && rx->sk.sk_state != RXRPC_SERVER_LISTENING) { release_sock(&rx->sk); - return -ENODATA; + return -EAGAIN; } if (list_empty(&rx->recvmsg_q)) { diff --git a/net/rxrpc/sendmsg.c b/net/rxrpc/sendmsg.c index 1304b8608f56..03a30d014bb6 100644 --- a/net/rxrpc/sendmsg.c +++ b/net/rxrpc/sendmsg.c @@ -304,7 +304,7 @@ static int rxrpc_send_data(struct rxrpc_sock *rx, /* this should be in poll */ sk_clear_bit(SOCKWQ_ASYNC_NOSPACE, sk); - if (sk->sk_err || (sk->sk_shutdown & SEND_SHUTDOWN)) + if (sk->sk_shutdown & SEND_SHUTDOWN) return -EPIPE; more = msg->msg_flags & MSG_MORE; diff --git a/net/sched/act_ct.c b/net/sched/act_ct.c index 67504aece9ae..5928efb6449c 100644 --- a/net/sched/act_ct.c +++ b/net/sched/act_ct.c @@ -673,9 +673,10 @@ static int tcf_ct_ipv6_is_fragment(struct sk_buff *skb, bool *frag) } static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, - u8 family, u16 zone) + u8 family, u16 zone, bool *defrag) { enum ip_conntrack_info ctinfo; + struct qdisc_skb_cb cb; struct nf_conn *ct; int err = 0; bool frag; @@ -693,6 +694,7 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, return err; skb_get(skb); + cb = *qdisc_skb_cb(skb); if (family == NFPROTO_IPV4) { enum ip_defrag_users user = IP_DEFRAG_CONNTRACK_IN + zone; @@ -703,6 +705,9 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, local_bh_enable(); if (err && err != -EINPROGRESS) goto out_free; + + if (!err) + *defrag = true; } else { /* NFPROTO_IPV6 */ #if IS_ENABLED(CONFIG_NF_DEFRAG_IPV6) enum ip6_defrag_users user = IP6_DEFRAG_CONNTRACK_IN + zone; @@ -711,12 +716,16 @@ static int tcf_ct_handle_fragments(struct net *net, struct sk_buff *skb, err = nf_ct_frag6_gather(net, skb, user); if (err && err != -EINPROGRESS) goto out_free; + + if (!err) + *defrag = true; #else err = -EOPNOTSUPP; goto out_free; #endif } + *qdisc_skb_cb(skb) = cb; skb_clear_hash(skb); skb->ignore_df = 1; return err; @@ -914,6 +923,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a, int nh_ofs, err, retval; struct tcf_ct_params *p; bool skip_add = false; + bool defrag = false; struct nf_conn *ct; u8 family; @@ -946,7 +956,7 @@ static int tcf_ct_act(struct sk_buff *skb, const struct tc_action *a, */ nh_ofs = skb_network_offset(skb); skb_pull_rcsum(skb, nh_ofs); - err = tcf_ct_handle_fragments(net, skb, family, p->zone); + err = tcf_ct_handle_fragments(net, skb, family, p->zone, &defrag); if (err == -EINPROGRESS) { retval = TC_ACT_STOLEN; goto out; @@ -1014,6 +1024,8 @@ out_push: out: tcf_action_update_bstats(&c->common, skb); + if (defrag) + qdisc_skb_cb(skb)->pkt_len = skb->len; return retval; drop: diff --git a/net/sched/cls_api.c b/net/sched/cls_api.c index e62beec0d844..4619cb3cb0a8 100644 --- a/net/sched/cls_api.c +++ b/net/sched/cls_api.c @@ -20,7 +20,6 @@ #include <linux/kmod.h> #include <linux/slab.h> #include <linux/idr.h> -#include <linux/rhashtable.h> #include <linux/jhash.h> #include <linux/rculist.h> #include <net/net_namespace.h> diff --git a/net/sctp/stream.c b/net/sctp/stream.c index 67f7e71f9129..bda2536dd740 100644 --- a/net/sctp/stream.c +++ b/net/sctp/stream.c @@ -22,17 +22,11 @@ #include <net/sctp/sm.h> #include <net/sctp/stream_sched.h> -/* Migrates chunks from stream queues to new stream queues if needed, - * but not across associations. Also, removes those chunks to streams - * higher than the new max. - */ -static void sctp_stream_outq_migrate(struct sctp_stream *stream, - struct sctp_stream *new, __u16 outcnt) +static void sctp_stream_shrink_out(struct sctp_stream *stream, __u16 outcnt) { struct sctp_association *asoc; struct sctp_chunk *ch, *temp; struct sctp_outq *outq; - int i; asoc = container_of(stream, struct sctp_association, stream); outq = &asoc->outqueue; @@ -56,6 +50,19 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream, sctp_chunk_free(ch); } +} + +/* Migrates chunks from stream queues to new stream queues if needed, + * but not across associations. Also, removes those chunks to streams + * higher than the new max. + */ +static void sctp_stream_outq_migrate(struct sctp_stream *stream, + struct sctp_stream *new, __u16 outcnt) +{ + int i; + + if (stream->outcnt > outcnt) + sctp_stream_shrink_out(stream, outcnt); if (new) { /* Here we actually move the old ext stuff into the new @@ -1037,11 +1044,13 @@ struct sctp_chunk *sctp_process_strreset_resp( nums = ntohs(addstrm->number_of_streams); number = stream->outcnt - nums; - if (result == SCTP_STRRESET_PERFORMED) + if (result == SCTP_STRRESET_PERFORMED) { for (i = number; i < stream->outcnt; i++) SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN; - else + } else { + sctp_stream_shrink_out(stream, number); stream->outcnt = number; + } *evp = sctp_ulpevent_make_stream_change_event(asoc, flags, 0, nums, GFP_ATOMIC); diff --git a/net/smc/af_smc.c b/net/smc/af_smc.c index 903321543838..1163d51196da 100644 --- a/net/smc/af_smc.c +++ b/net/smc/af_smc.c @@ -126,8 +126,10 @@ EXPORT_SYMBOL_GPL(smc_proto6); static void smc_restore_fallback_changes(struct smc_sock *smc) { - smc->clcsock->file->private_data = smc->sk.sk_socket; - smc->clcsock->file = NULL; + if (smc->clcsock->file) { /* non-accepted sockets have no file yet */ + smc->clcsock->file->private_data = smc->sk.sk_socket; + smc->clcsock->file = NULL; + } } static int __smc_release(struct smc_sock *smc) @@ -352,7 +354,7 @@ static int smcr_lgr_reg_rmbs(struct smc_link *link, */ mutex_lock(&lgr->llc_conf_mutex); for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (lgr->lnk[i].state != SMC_LNK_ACTIVE) + if (!smc_link_active(&lgr->lnk[i])) continue; rc = smcr_link_reg_rmb(&lgr->lnk[i], rmb_desc); if (rc) @@ -632,7 +634,9 @@ static int smc_connect_rdma(struct smc_sock *smc, for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { struct smc_link *l = &smc->conn.lgr->lnk[i]; - if (l->peer_qpn == ntoh24(aclc->qpn)) { + if (l->peer_qpn == ntoh24(aclc->qpn) && + !memcmp(l->peer_gid, &aclc->lcl.gid, SMC_GID_SIZE) && + !memcmp(l->peer_mac, &aclc->lcl.mac, sizeof(l->peer_mac))) { link = l; break; } diff --git a/net/smc/smc_cdc.c b/net/smc/smc_cdc.c index a47e8855e045..ce468ff62a19 100644 --- a/net/smc/smc_cdc.c +++ b/net/smc/smc_cdc.c @@ -66,9 +66,13 @@ int smc_cdc_get_free_slot(struct smc_connection *conn, rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf, wr_rdma_buf, (struct smc_wr_tx_pend_priv **)pend); - if (conn->killed) + if (conn->killed) { /* abnormal termination */ + if (!rc) + smc_wr_tx_put_slot(link, + (struct smc_wr_tx_pend_priv *)pend); rc = -EPIPE; + } return rc; } diff --git a/net/smc/smc_core.c b/net/smc/smc_core.c index f69d205b3e11..f82a2e599917 100644 --- a/net/smc/smc_core.c +++ b/net/smc/smc_core.c @@ -45,18 +45,10 @@ static struct smc_lgr_list smc_lgr_list = { /* established link groups */ static atomic_t lgr_cnt = ATOMIC_INIT(0); /* number of existing link groups */ static DECLARE_WAIT_QUEUE_HEAD(lgrs_deleted); -struct smc_ib_up_work { - struct work_struct work; - struct smc_link_group *lgr; - struct smc_ib_device *smcibdev; - u8 ibport; -}; - static void smc_buf_free(struct smc_link_group *lgr, bool is_rmb, struct smc_buf_desc *buf_desc); static void __smc_lgr_terminate(struct smc_link_group *lgr, bool soft); -static void smc_link_up_work(struct work_struct *work); static void smc_link_down_work(struct work_struct *work); /* return head of link group list and its lock for a given link group */ @@ -326,7 +318,6 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk, get_device(&ini->ib_dev->ibdev->dev); atomic_inc(&ini->ib_dev->lnk_cnt); - lnk->state = SMC_LNK_ACTIVATING; lnk->link_id = smcr_next_link_id(lgr); lnk->lgr = lgr; lnk->link_idx = link_idx; @@ -362,6 +353,7 @@ int smcr_link_init(struct smc_link_group *lgr, struct smc_link *lnk, rc = smc_wr_create_link(lnk); if (rc) goto destroy_qp; + lnk->state = SMC_LNK_ACTIVATING; return 0; destroy_qp: @@ -452,7 +444,7 @@ static int smc_lgr_create(struct smc_sock *smc, struct smc_init_info *ini) } smc->conn.lgr = lgr; spin_lock_bh(lgr_lock); - list_add(&lgr->list, lgr_list); + list_add_tail(&lgr->list, lgr_list); spin_unlock_bh(lgr_lock); return 0; @@ -550,8 +542,7 @@ struct smc_link *smc_switch_conns(struct smc_link_group *lgr, smc_wr_wakeup_tx_wait(from_lnk); for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (lgr->lnk[i].state != SMC_LNK_ACTIVE || - i == from_lnk->link_idx) + if (!smc_link_active(&lgr->lnk[i]) || i == from_lnk->link_idx) continue; if (is_dev_err && from_lnk->smcibdev == lgr->lnk[i].smcibdev && from_lnk->ibport == lgr->lnk[i].ibport) { @@ -1106,67 +1097,23 @@ static void smc_conn_abort_work(struct work_struct *work) sock_put(&smc->sk); /* sock_hold done by schedulers of abort_work */ } -/* link is up - establish alternate link if applicable */ -static void smcr_link_up(struct smc_link_group *lgr, - struct smc_ib_device *smcibdev, u8 ibport) -{ - struct smc_link *link = NULL; - - if (list_empty(&lgr->list) || - lgr->type == SMC_LGR_SYMMETRIC || - lgr->type == SMC_LGR_ASYMMETRIC_PEER) - return; - - if (lgr->role == SMC_SERV) { - /* trigger local add link processing */ - link = smc_llc_usable_link(lgr); - if (!link) - return; - smc_llc_srv_add_link_local(link); - } else { - /* invite server to start add link processing */ - u8 gid[SMC_GID_SIZE]; - - if (smc_ib_determine_gid(smcibdev, ibport, lgr->vlan_id, gid, - NULL)) - return; - if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) { - /* some other llc task is ongoing */ - wait_event_timeout(lgr->llc_flow_waiter, - (list_empty(&lgr->list) || - lgr->llc_flow_lcl.type == SMC_LLC_FLOW_NONE), - SMC_LLC_WAIT_TIME); - } - /* lgr or device no longer active? */ - if (!list_empty(&lgr->list) && - smc_ib_port_active(smcibdev, ibport)) - link = smc_llc_usable_link(lgr); - if (link) - smc_llc_send_add_link(link, smcibdev->mac[ibport - 1], - gid, NULL, SMC_LLC_REQ); - wake_up(&lgr->llc_flow_waiter); /* wake up next waiter */ - } -} - void smcr_port_add(struct smc_ib_device *smcibdev, u8 ibport) { - struct smc_ib_up_work *ib_work; struct smc_link_group *lgr, *n; list_for_each_entry_safe(lgr, n, &smc_lgr_list.list, list) { + struct smc_link *link; + if (strncmp(smcibdev->pnetid[ibport - 1], lgr->pnet_id, SMC_MAX_PNETID_LEN) || lgr->type == SMC_LGR_SYMMETRIC || lgr->type == SMC_LGR_ASYMMETRIC_PEER) continue; - ib_work = kmalloc(sizeof(*ib_work), GFP_KERNEL); - if (!ib_work) - continue; - INIT_WORK(&ib_work->work, smc_link_up_work); - ib_work->lgr = lgr; - ib_work->smcibdev = smcibdev; - ib_work->ibport = ibport; - schedule_work(&ib_work->work); + + /* trigger local add link processing */ + link = smc_llc_usable_link(lgr); + if (link) + smc_llc_add_link_local(link); } } @@ -1204,10 +1151,12 @@ static void smcr_link_down(struct smc_link *lnk) SMC_LLC_WAIT_TIME); mutex_lock(&lgr->llc_conf_mutex); } - if (!list_empty(&lgr->list)) + if (!list_empty(&lgr->list)) { smc_llc_send_delete_link(to_lnk, del_link_id, SMC_LLC_REQ, true, SMC_LLC_DEL_LOST_PATH); + smcr_link_clear(lnk, true); + } wake_up(&lgr->llc_flow_waiter); /* wake up next waiter */ } } @@ -1247,20 +1196,6 @@ void smcr_port_err(struct smc_ib_device *smcibdev, u8 ibport) } } -static void smc_link_up_work(struct work_struct *work) -{ - struct smc_ib_up_work *ib_work = container_of(work, - struct smc_ib_up_work, - work); - struct smc_link_group *lgr = ib_work->lgr; - - if (list_empty(&lgr->list)) - goto out; - smcr_link_up(lgr, ib_work->smcibdev, ib_work->ibport); -out: - kfree(ib_work); -} - static void smc_link_down_work(struct work_struct *work) { struct smc_link *link = container_of(work, struct smc_link, @@ -1333,7 +1268,7 @@ static bool smcr_lgr_match(struct smc_link_group *lgr, return false; for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (lgr->lnk[i].state != SMC_LNK_ACTIVE) + if (!smc_link_active(&lgr->lnk[i])) continue; if ((lgr->role == SMC_SERV || lgr->lnk[i].peer_qpn == clcqpn) && !memcmp(lgr->lnk[i].peer_gid, &lcl->gid, SMC_GID_SIZE) && @@ -1376,7 +1311,7 @@ int smc_conn_create(struct smc_sock *smc, struct smc_init_info *ini) smcr_lgr_match(lgr, ini->ib_lcl, role, ini->ib_clcqpn)) && !lgr->sync_err && lgr->vlan_id == ini->vlan_id && - (role == SMC_CLNT || + (role == SMC_CLNT || ini->is_smcd || lgr->conns_num < SMC_RMBS_PER_LGR_MAX)) { /* link group found */ ini->cln_first_contact = SMC_REUSE_CONTACT; @@ -1781,14 +1716,14 @@ static int __smc_buf_create(struct smc_sock *smc, bool is_smcd, bool is_rmb) void smc_sndbuf_sync_sg_for_cpu(struct smc_connection *conn) { - if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk)) + if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(conn->lnk)) return; smc_ib_sync_sg_for_cpu(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE); } void smc_sndbuf_sync_sg_for_device(struct smc_connection *conn) { - if (!conn->lgr || conn->lgr->is_smcd || !smc_link_usable(conn->lnk)) + if (!conn->lgr || conn->lgr->is_smcd || !smc_link_active(conn->lnk)) return; smc_ib_sync_sg_for_device(conn->lnk, conn->sndbuf_desc, DMA_TO_DEVICE); } @@ -1800,7 +1735,7 @@ void smc_rmb_sync_sg_for_cpu(struct smc_connection *conn) if (!conn->lgr || conn->lgr->is_smcd) return; for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (!smc_link_usable(&conn->lgr->lnk[i])) + if (!smc_link_active(&conn->lgr->lnk[i])) continue; smc_ib_sync_sg_for_cpu(&conn->lgr->lnk[i], conn->rmb_desc, DMA_FROM_DEVICE); @@ -1814,7 +1749,7 @@ void smc_rmb_sync_sg_for_device(struct smc_connection *conn) if (!conn->lgr || conn->lgr->is_smcd) return; for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (!smc_link_usable(&conn->lgr->lnk[i])) + if (!smc_link_active(&conn->lgr->lnk[i])) continue; smc_ib_sync_sg_for_device(&conn->lgr->lnk[i], conn->rmb_desc, DMA_FROM_DEVICE); @@ -1837,8 +1772,12 @@ int smc_buf_create(struct smc_sock *smc, bool is_smcd) return rc; /* create rmb */ rc = __smc_buf_create(smc, is_smcd, true); - if (rc) + if (rc) { + mutex_lock(&smc->conn.lgr->sndbufs_lock); + list_del(&smc->conn.sndbuf_desc->list); + mutex_unlock(&smc->conn.lgr->sndbufs_lock); smc_buf_free(smc->conn.lgr, false, smc->conn.sndbuf_desc); + } return rc; } diff --git a/net/smc/smc_core.h b/net/smc/smc_core.h index c3ff512fd891..1c4d5439d0ff 100644 --- a/net/smc/smc_core.h +++ b/net/smc/smc_core.h @@ -349,6 +349,11 @@ static inline bool smc_link_usable(struct smc_link *lnk) return true; } +static inline bool smc_link_active(struct smc_link *lnk) +{ + return lnk->state == SMC_LNK_ACTIVE; +} + struct smc_sock; struct smc_clc_msg_accept_confirm; struct smc_clc_msg_local; diff --git a/net/smc/smc_ib.c b/net/smc/smc_ib.c index 7637fdebbb78..1c314dbdc7fa 100644 --- a/net/smc/smc_ib.c +++ b/net/smc/smc_ib.c @@ -506,6 +506,10 @@ long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev) int cqe_size_order, smc_order; long rc; + mutex_lock(&smcibdev->mutex); + rc = 0; + if (smcibdev->initialized) + goto out; /* the calculated number of cq entries fits to mlx5 cq allocation */ cqe_size_order = cache_line_size() == 128 ? 7 : 6; smc_order = MAX_ORDER - cqe_size_order - 1; @@ -517,7 +521,7 @@ long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev) rc = PTR_ERR_OR_ZERO(smcibdev->roce_cq_send); if (IS_ERR(smcibdev->roce_cq_send)) { smcibdev->roce_cq_send = NULL; - return rc; + goto out; } smcibdev->roce_cq_recv = ib_create_cq(smcibdev->ibdev, smc_wr_rx_cq_handler, NULL, @@ -529,21 +533,26 @@ long smc_ib_setup_per_ibdev(struct smc_ib_device *smcibdev) } smc_wr_add_dev(smcibdev); smcibdev->initialized = 1; - return rc; + goto out; err: ib_destroy_cq(smcibdev->roce_cq_send); +out: + mutex_unlock(&smcibdev->mutex); return rc; } static void smc_ib_cleanup_per_ibdev(struct smc_ib_device *smcibdev) { + mutex_lock(&smcibdev->mutex); if (!smcibdev->initialized) - return; + goto out; smcibdev->initialized = 0; ib_destroy_cq(smcibdev->roce_cq_recv); ib_destroy_cq(smcibdev->roce_cq_send); smc_wr_remove_dev(smcibdev); +out: + mutex_unlock(&smcibdev->mutex); } static struct ib_client smc_ib_client; @@ -566,6 +575,7 @@ static int smc_ib_add_dev(struct ib_device *ibdev) INIT_WORK(&smcibdev->port_event_work, smc_ib_port_event_work); atomic_set(&smcibdev->lnk_cnt, 0); init_waitqueue_head(&smcibdev->lnks_deleted); + mutex_init(&smcibdev->mutex); mutex_lock(&smc_ib_devices.mutex); list_add_tail(&smcibdev->list, &smc_ib_devices.list); mutex_unlock(&smc_ib_devices.mutex); diff --git a/net/smc/smc_ib.h b/net/smc/smc_ib.h index ae6776e1e726..2ce481187dd0 100644 --- a/net/smc/smc_ib.h +++ b/net/smc/smc_ib.h @@ -52,6 +52,7 @@ struct smc_ib_device { /* ib-device infos for smc */ DECLARE_BITMAP(ports_going_away, SMC_MAX_PORTS); atomic_t lnk_cnt; /* number of links on ibdev */ wait_queue_head_t lnks_deleted; /* wait 4 removal of all links*/ + struct mutex mutex; /* protect dev setup+cleanup */ }; struct smc_buf_desc; diff --git a/net/smc/smc_llc.c b/net/smc/smc_llc.c index c1a038689c63..df5b0a6ea848 100644 --- a/net/smc/smc_llc.c +++ b/net/smc/smc_llc.c @@ -428,7 +428,7 @@ static int smc_llc_send_confirm_rkey(struct smc_link *send_link, rtok_ix = 1; for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { link = &send_link->lgr->lnk[i]; - if (link->state == SMC_LNK_ACTIVE && link != send_link) { + if (smc_link_active(link) && link != send_link) { rkeyllc->rtoken[rtok_ix].link_id = link->link_id; rkeyllc->rtoken[rtok_ix].rmb_key = htonl(rmb_desc->mr_rx[link->link_idx]->rkey); @@ -895,6 +895,36 @@ out: return rc; } +/* as an SMC client, invite server to start the add_link processing */ +static void smc_llc_cli_add_link_invite(struct smc_link *link, + struct smc_llc_qentry *qentry) +{ + struct smc_link_group *lgr = smc_get_lgr(link); + struct smc_init_info ini; + + if (lgr->type == SMC_LGR_SYMMETRIC || + lgr->type == SMC_LGR_ASYMMETRIC_PEER) + goto out; + + ini.vlan_id = lgr->vlan_id; + smc_pnet_find_alt_roce(lgr, &ini, link->smcibdev); + if (!ini.ib_dev) + goto out; + + smc_llc_send_add_link(link, ini.ib_dev->mac[ini.ib_port - 1], + ini.ib_gid, NULL, SMC_LLC_REQ); +out: + kfree(qentry); +} + +static bool smc_llc_is_local_add_link(union smc_llc_msg *llc) +{ + if (llc->raw.hdr.common.type == SMC_LLC_ADD_LINK && + !llc->add_link.qp_mtu && !llc->add_link.link_num) + return true; + return false; +} + static void smc_llc_process_cli_add_link(struct smc_link_group *lgr) { struct smc_llc_qentry *qentry; @@ -902,7 +932,10 @@ static void smc_llc_process_cli_add_link(struct smc_link_group *lgr) qentry = smc_llc_flow_qentry_clr(&lgr->llc_flow_lcl); mutex_lock(&lgr->llc_conf_mutex); - smc_llc_cli_add_link(qentry->link, qentry); + if (smc_llc_is_local_add_link(&qentry->msg)) + smc_llc_cli_add_link_invite(qentry->link, qentry); + else + smc_llc_cli_add_link(qentry->link, qentry); mutex_unlock(&lgr->llc_conf_mutex); } @@ -911,7 +944,7 @@ static int smc_llc_active_link_count(struct smc_link_group *lgr) int i, link_count = 0; for (i = 0; i < SMC_LINKS_PER_LGR_MAX; i++) { - if (!smc_link_usable(&lgr->lnk[i])) + if (!smc_link_active(&lgr->lnk[i])) continue; link_count++; } @@ -1051,12 +1084,14 @@ static int smc_llc_srv_conf_link(struct smc_link *link, if (rc) return -ENOLINK; /* receive CONFIRM LINK response over the RoCE fabric */ - qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_FIRST_TIME, - SMC_LLC_CONFIRM_LINK); - if (!qentry) { + qentry = smc_llc_wait(lgr, link, SMC_LLC_WAIT_FIRST_TIME, 0); + if (!qentry || + qentry->msg.raw.hdr.common.type != SMC_LLC_CONFIRM_LINK) { /* send DELETE LINK */ smc_llc_send_delete_link(link, link_new->link_id, SMC_LLC_REQ, false, SMC_LLC_DEL_LOST_PATH); + if (qentry) + smc_llc_flow_qentry_del(&lgr->llc_flow_lcl); return -ENOLINK; } smc_llc_save_peer_uid(qentry); @@ -1158,14 +1193,14 @@ static void smc_llc_process_srv_add_link(struct smc_link_group *lgr) mutex_unlock(&lgr->llc_conf_mutex); } -/* enqueue a local add_link req to trigger a new add_link flow, only as SERV */ -void smc_llc_srv_add_link_local(struct smc_link *link) +/* enqueue a local add_link req to trigger a new add_link flow */ +void smc_llc_add_link_local(struct smc_link *link) { struct smc_llc_msg_add_link add_llc = {0}; add_llc.hd.length = sizeof(add_llc); add_llc.hd.common.type = SMC_LLC_ADD_LINK; - /* no dev and port needed, we as server ignore client data anyway */ + /* no dev and port needed */ smc_llc_enqueue(link, (union smc_llc_msg *)&add_llc); } @@ -1345,7 +1380,7 @@ static void smc_llc_process_srv_delete_link(struct smc_link_group *lgr) if (lgr->type == SMC_LGR_SINGLE && !list_empty(&lgr->list)) { /* trigger setup of asymm alt link */ - smc_llc_srv_add_link_local(lnk); + smc_llc_add_link_local(lnk); } out: mutex_unlock(&lgr->llc_conf_mutex); @@ -1474,7 +1509,18 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry) if (list_empty(&lgr->list)) goto out; /* lgr is terminating */ if (lgr->role == SMC_CLNT) { - if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK) { + if (smc_llc_is_local_add_link(llc)) { + if (lgr->llc_flow_lcl.type == + SMC_LLC_FLOW_ADD_LINK) + break; /* add_link in progress */ + if (smc_llc_flow_start(&lgr->llc_flow_lcl, + qentry)) { + schedule_work(&lgr->llc_add_link_work); + } + return; + } + if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK && + !lgr->llc_flow_lcl.qentry) { /* a flow is waiting for this message */ smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry); @@ -1498,28 +1544,13 @@ static void smc_llc_event_handler(struct smc_llc_qentry *qentry) } break; case SMC_LLC_DELETE_LINK: - if (lgr->role == SMC_CLNT) { - /* server requests to delete this link, send response */ - if (lgr->llc_flow_lcl.type != SMC_LLC_FLOW_NONE) { - /* DEL LINK REQ during ADD LINK SEQ */ - smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, - qentry); - wake_up(&lgr->llc_msg_waiter); - } else if (smc_llc_flow_start(&lgr->llc_flow_lcl, - qentry)) { - schedule_work(&lgr->llc_del_link_work); - } - } else { - if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK && - !lgr->llc_flow_lcl.qentry) { - /* DEL LINK REQ during ADD LINK SEQ */ - smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, - qentry); - wake_up(&lgr->llc_msg_waiter); - } else if (smc_llc_flow_start(&lgr->llc_flow_lcl, - qentry)) { - schedule_work(&lgr->llc_del_link_work); - } + if (lgr->llc_flow_lcl.type == SMC_LLC_FLOW_ADD_LINK && + !lgr->llc_flow_lcl.qentry) { + /* DEL LINK REQ during ADD LINK SEQ */ + smc_llc_flow_qentry_set(&lgr->llc_flow_lcl, qentry); + wake_up(&lgr->llc_msg_waiter); + } else if (smc_llc_flow_start(&lgr->llc_flow_lcl, qentry)) { + schedule_work(&lgr->llc_del_link_work); } return; case SMC_LLC_CONFIRM_RKEY: @@ -1585,23 +1616,30 @@ again: static void smc_llc_rx_response(struct smc_link *link, struct smc_llc_qentry *qentry) { + enum smc_llc_flowtype flowtype = link->lgr->llc_flow_lcl.type; + struct smc_llc_flow *flow = &link->lgr->llc_flow_lcl; u8 llc_type = qentry->msg.raw.hdr.common.type; switch (llc_type) { case SMC_LLC_TEST_LINK: - if (link->state == SMC_LNK_ACTIVE) + if (smc_link_active(link)) complete(&link->llc_testlink_resp); break; case SMC_LLC_ADD_LINK: - case SMC_LLC_DELETE_LINK: - case SMC_LLC_CONFIRM_LINK: case SMC_LLC_ADD_LINK_CONT: + case SMC_LLC_CONFIRM_LINK: + if (flowtype != SMC_LLC_FLOW_ADD_LINK || flow->qentry) + break; /* drop out-of-flow response */ + goto assign; + case SMC_LLC_DELETE_LINK: + if (flowtype != SMC_LLC_FLOW_DEL_LINK || flow->qentry) + break; /* drop out-of-flow response */ + goto assign; case SMC_LLC_CONFIRM_RKEY: case SMC_LLC_DELETE_RKEY: - /* assign responses to the local flow, we requested them */ - smc_llc_flow_qentry_set(&link->lgr->llc_flow_lcl, qentry); - wake_up(&link->lgr->llc_msg_waiter); - return; + if (flowtype != SMC_LLC_FLOW_RKEY || flow->qentry) + break; /* drop out-of-flow response */ + goto assign; case SMC_LLC_CONFIRM_RKEY_CONT: /* not used because max links is 3 */ break; @@ -1610,6 +1648,11 @@ static void smc_llc_rx_response(struct smc_link *link, break; } kfree(qentry); + return; +assign: + /* assign responses to the local flow, we requested them */ + smc_llc_flow_qentry_set(&link->lgr->llc_flow_lcl, qentry); + wake_up(&link->lgr->llc_msg_waiter); } static void smc_llc_enqueue(struct smc_link *link, union smc_llc_msg *llc) @@ -1663,7 +1706,7 @@ static void smc_llc_testlink_work(struct work_struct *work) u8 user_data[16] = { 0 }; int rc; - if (link->state != SMC_LNK_ACTIVE) + if (!smc_link_active(link)) return; /* don't reschedule worker */ expire_time = link->wr_rx_tstamp + link->llc_testlink_time; if (time_is_after_jiffies(expire_time)) { @@ -1675,7 +1718,7 @@ static void smc_llc_testlink_work(struct work_struct *work) /* receive TEST LINK response over RoCE fabric */ rc = wait_for_completion_interruptible_timeout(&link->llc_testlink_resp, SMC_LLC_WAIT_TIME); - if (link->state != SMC_LNK_ACTIVE) + if (!smc_link_active(link)) return; /* link state changed */ if (rc <= 0) { smcr_link_down_cond_sched(link); diff --git a/net/smc/smc_llc.h b/net/smc/smc_llc.h index a5d2fe3eea61..cc00a2ec4e92 100644 --- a/net/smc/smc_llc.h +++ b/net/smc/smc_llc.h @@ -103,7 +103,7 @@ void smc_llc_send_link_delete_all(struct smc_link_group *lgr, bool ord, u32 rsn); int smc_llc_cli_add_link(struct smc_link *link, struct smc_llc_qentry *qentry); int smc_llc_srv_add_link(struct smc_link *link); -void smc_llc_srv_add_link_local(struct smc_link *link); +void smc_llc_add_link_local(struct smc_link *link); int smc_llc_init(void) __init; #endif /* SMC_LLC_H */ diff --git a/net/tipc/link.c b/net/tipc/link.c index 263d950e70e9..d40f8e5b7683 100644 --- a/net/tipc/link.c +++ b/net/tipc/link.c @@ -827,11 +827,11 @@ int tipc_link_timeout(struct tipc_link *l, struct sk_buff_head *xmitq) state |= l->bc_rcvlink->rcv_unacked; state |= l->rcv_unacked; state |= !skb_queue_empty(&l->transmq); - state |= !skb_queue_empty(&l->deferdq); probe = mstate->probing; probe |= l->silent_intv_cnt; if (probe || mstate->monitoring) l->silent_intv_cnt++; + probe |= !skb_queue_empty(&l->deferdq); if (l->snd_nxt == l->checkpoint) { tipc_link_update_cwin(l, 0, 0); probe = true; diff --git a/net/vmw_vsock/virtio_transport.c b/net/vmw_vsock/virtio_transport.c index dfbaf6bd8b1c..2700a63ab095 100644 --- a/net/vmw_vsock/virtio_transport.c +++ b/net/vmw_vsock/virtio_transport.c @@ -22,7 +22,7 @@ #include <net/af_vsock.h> static struct workqueue_struct *virtio_vsock_workqueue; -static struct virtio_vsock *the_virtio_vsock; +static struct virtio_vsock __rcu *the_virtio_vsock; static DEFINE_MUTEX(the_virtio_vsock_mutex); /* protects the_virtio_vsock */ struct virtio_vsock { diff --git a/scripts/decode_stacktrace.sh b/scripts/decode_stacktrace.sh index 66a6d511b524..0869def435ee 100755 --- a/scripts/decode_stacktrace.sh +++ b/scripts/decode_stacktrace.sh @@ -87,8 +87,8 @@ parse_symbol() { return fi - # Strip out the base of the path - code=${code#$basepath/} + # Strip out the base of the path on each line + code=$(while read -r line; do echo "${line#$basepath/}"; done <<< "$code") # In the case of inlines, move everything to same line code=${code//$'\n'/' '} diff --git a/scripts/gdb/linux/symbols.py b/scripts/gdb/linux/symbols.py index be984aa29b75..1be9763cf8bb 100644 --- a/scripts/gdb/linux/symbols.py +++ b/scripts/gdb/linux/symbols.py @@ -96,7 +96,7 @@ lx-symbols command.""" return "" attrs = sect_attrs['attrs'] section_name_to_address = { - attrs[n]['name'].string(): attrs[n]['address'] + attrs[n]['battr']['attr']['name'].string(): attrs[n]['address'] for n in range(int(sect_attrs['nsections']))} args = [] for section_name in [".data", ".data..read_mostly", ".rodata", ".bss", diff --git a/sound/core/info.c b/sound/core/info.c index 8c6bc5241df5..9fec3070f8ba 100644 --- a/sound/core/info.c +++ b/sound/core/info.c @@ -606,7 +606,9 @@ int snd_info_get_line(struct snd_info_buffer *buffer, char *line, int len) { int c; - if (snd_BUG_ON(!buffer || !buffer->buffer)) + if (snd_BUG_ON(!buffer)) + return 1; + if (!buffer->buffer) return 1; if (len <= 0 || buffer->stop || buffer->error) return 1; diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index 1b06c4261248..1b2d8e56390a 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c @@ -7587,6 +7587,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = { SND_PCI_QUIRK(0x144d, 0xc169, "Samsung Notebook 9 Pen (NP930SBE-K01US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), SND_PCI_QUIRK(0x144d, 0xc176, "Samsung Notebook 9 Pro (NP930MBE-K04US)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), SND_PCI_QUIRK(0x144d, 0xc740, "Samsung Ativ book 8 (NP870Z5G)", ALC269_FIXUP_ATIV_BOOK_8), + SND_PCI_QUIRK(0x144d, 0xc812, "Samsung Notebook Pen S (NT950SBE-X58)", ALC298_FIXUP_SAMSUNG_HEADPHONE_VERY_QUIET), SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC), SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC), diff --git a/sound/soc/amd/raven/pci-acp3x.c b/sound/soc/amd/raven/pci-acp3x.c index f25ce50f1a90..ebf4388b6262 100644 --- a/sound/soc/amd/raven/pci-acp3x.c +++ b/sound/soc/amd/raven/pci-acp3x.c @@ -232,9 +232,7 @@ static int snd_acp3x_probe(struct pci_dev *pci, } pm_runtime_set_autosuspend_delay(&pci->dev, 2000); pm_runtime_use_autosuspend(&pci->dev); - pm_runtime_set_active(&pci->dev); pm_runtime_put_noidle(&pci->dev); - pm_runtime_enable(&pci->dev); pm_runtime_allow(&pci->dev); return 0; @@ -303,7 +301,7 @@ static void snd_acp3x_remove(struct pci_dev *pci) ret = acp3x_deinit(adata->acp3x_base); if (ret) dev_err(&pci->dev, "ACP de-init failed\n"); - pm_runtime_disable(&pci->dev); + pm_runtime_forbid(&pci->dev); pm_runtime_get_noresume(&pci->dev); pci_disable_msi(pci); pci_release_regions(pci); diff --git a/sound/soc/codecs/max98373.c b/sound/soc/codecs/max98373.c index 96718e3a1ad0..d87402a86c88 100644 --- a/sound/soc/codecs/max98373.c +++ b/sound/soc/codecs/max98373.c @@ -779,13 +779,6 @@ static int max98373_probe(struct snd_soc_component *component) regmap_write(max98373->regmap, MAX98373_R202A_PCM_TO_SPK_MONO_MIX_2, 0x1); - /* Set inital volume (0dB) */ - regmap_write(max98373->regmap, - MAX98373_R203D_AMP_DIG_VOL_CTRL, - 0x00); - regmap_write(max98373->regmap, - MAX98373_R203E_AMP_PATH_GAIN, - 0x00); /* Enable DC blocker */ regmap_write(max98373->regmap, MAX98373_R203F_AMP_DSP_CFG, @@ -869,7 +862,6 @@ static const struct snd_soc_component_driver soc_codec_dev_max98373 = { .num_dapm_widgets = ARRAY_SIZE(max98373_dapm_widgets), .dapm_routes = max98373_audio_map, .num_dapm_routes = ARRAY_SIZE(max98373_audio_map), - .idle_bias_on = 1, .use_pmdown_time = 1, .endianness = 1, .non_legacy_dai_naming = 1, diff --git a/sound/soc/codecs/rt286.c b/sound/soc/codecs/rt286.c index 9593a9a27bf8..e8d14eefc41b 100644 --- a/sound/soc/codecs/rt286.c +++ b/sound/soc/codecs/rt286.c @@ -272,13 +272,13 @@ static int rt286_jack_detect(struct rt286_priv *rt286, bool *hp, bool *mic) regmap_read(rt286->regmap, RT286_GET_MIC1_SENSE, &buf); *mic = buf & 0x80000000; } - if (!*mic) { + + if (!*hp) { snd_soc_dapm_disable_pin(dapm, "HV"); snd_soc_dapm_disable_pin(dapm, "VREF"); - } - if (!*hp) snd_soc_dapm_disable_pin(dapm, "LDO1"); - snd_soc_dapm_sync(dapm); + snd_soc_dapm_sync(dapm); + } return 0; } diff --git a/sound/soc/codecs/rt5670.c b/sound/soc/codecs/rt5670.c index 70fee6849ab0..dfbc0ca38ff7 100644 --- a/sound/soc/codecs/rt5670.c +++ b/sound/soc/codecs/rt5670.c @@ -31,18 +31,19 @@ #include "rt5670.h" #include "rt5670-dsp.h" -#define RT5670_DEV_GPIO BIT(0) -#define RT5670_IN2_DIFF BIT(1) -#define RT5670_DMIC_EN BIT(2) -#define RT5670_DMIC1_IN2P BIT(3) -#define RT5670_DMIC1_GPIO6 BIT(4) -#define RT5670_DMIC1_GPIO7 BIT(5) -#define RT5670_DMIC2_INR BIT(6) -#define RT5670_DMIC2_GPIO8 BIT(7) -#define RT5670_DMIC3_GPIO5 BIT(8) -#define RT5670_JD_MODE1 BIT(9) -#define RT5670_JD_MODE2 BIT(10) -#define RT5670_JD_MODE3 BIT(11) +#define RT5670_DEV_GPIO BIT(0) +#define RT5670_IN2_DIFF BIT(1) +#define RT5670_DMIC_EN BIT(2) +#define RT5670_DMIC1_IN2P BIT(3) +#define RT5670_DMIC1_GPIO6 BIT(4) +#define RT5670_DMIC1_GPIO7 BIT(5) +#define RT5670_DMIC2_INR BIT(6) +#define RT5670_DMIC2_GPIO8 BIT(7) +#define RT5670_DMIC3_GPIO5 BIT(8) +#define RT5670_JD_MODE1 BIT(9) +#define RT5670_JD_MODE2 BIT(10) +#define RT5670_JD_MODE3 BIT(11) +#define RT5670_GPIO1_IS_EXT_SPK_EN BIT(12) static unsigned long rt5670_quirk; static unsigned int quirk_override; @@ -602,9 +603,9 @@ int rt5670_set_jack_detect(struct snd_soc_component *component, EXPORT_SYMBOL_GPL(rt5670_set_jack_detect); 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 */ @@ -1447,6 +1448,33 @@ static int rt5670_hp_event(struct snd_soc_dapm_widget *w, return 0; } +static int rt5670_spk_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 rt5670_priv *rt5670 = snd_soc_component_get_drvdata(component); + + if (!rt5670->pdata.gpio1_is_ext_spk_en) + return 0; + + switch (event) { + case SND_SOC_DAPM_POST_PMU: + regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, + RT5670_GP1_OUT_MASK, RT5670_GP1_OUT_HI); + break; + + case SND_SOC_DAPM_PRE_PMD: + regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, + RT5670_GP1_OUT_MASK, RT5670_GP1_OUT_LO); + break; + + default: + return 0; + } + + return 0; +} + static int rt5670_bst1_event(struct snd_soc_dapm_widget *w, struct snd_kcontrol *kcontrol, int event) { @@ -1860,7 +1888,9 @@ static const struct snd_soc_dapm_widget rt5670_specific_dapm_widgets[] = { }; static const struct snd_soc_dapm_widget rt5672_specific_dapm_widgets[] = { - SND_SOC_DAPM_PGA("SPO Amp", SND_SOC_NOPM, 0, 0, NULL, 0), + SND_SOC_DAPM_PGA_E("SPO Amp", SND_SOC_NOPM, 0, 0, NULL, 0, + rt5670_spk_event, SND_SOC_DAPM_PRE_PMD | + SND_SOC_DAPM_POST_PMU), SND_SOC_DAPM_OUTPUT("SPOLP"), SND_SOC_DAPM_OUTPUT("SPOLN"), SND_SOC_DAPM_OUTPUT("SPORP"), @@ -2857,14 +2887,14 @@ static const struct dmi_system_id dmi_platform_intel_quirks[] = { }, { .callback = rt5670_quirk_cb, - .ident = "Lenovo Thinkpad Tablet 10", + .ident = "Lenovo Miix 2 10", .matches = { DMI_MATCH(DMI_SYS_VENDOR, "LENOVO"), DMI_MATCH(DMI_PRODUCT_VERSION, "Lenovo Miix 2 10"), }, .driver_data = (unsigned long *)(RT5670_DMIC_EN | RT5670_DMIC1_IN2P | - RT5670_DEV_GPIO | + RT5670_GPIO1_IS_EXT_SPK_EN | RT5670_JD_MODE2), }, { @@ -2924,6 +2954,10 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, rt5670->pdata.dev_gpio = true; dev_info(&i2c->dev, "quirk dev_gpio\n"); } + if (rt5670_quirk & RT5670_GPIO1_IS_EXT_SPK_EN) { + rt5670->pdata.gpio1_is_ext_spk_en = true; + dev_info(&i2c->dev, "quirk GPIO1 is external speaker enable\n"); + } if (rt5670_quirk & RT5670_IN2_DIFF) { rt5670->pdata.in2_diff = true; dev_info(&i2c->dev, "quirk IN2_DIFF\n"); @@ -3023,6 +3057,13 @@ static int rt5670_i2c_probe(struct i2c_client *i2c, RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); } + if (rt5670->pdata.gpio1_is_ext_spk_en) { + regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL1, + RT5670_GP1_PIN_MASK, RT5670_GP1_PIN_GPIO1); + regmap_update_bits(rt5670->regmap, RT5670_GPIO_CTRL2, + RT5670_GP1_PF_MASK, RT5670_GP1_PF_OUT); + } + if (rt5670->pdata.jd_mode) { regmap_update_bits(rt5670->regmap, RT5670_GLB_CLK, RT5670_SCLK_SRC_MASK, RT5670_SCLK_SRC_RCCLK); diff --git a/sound/soc/codecs/rt5670.h b/sound/soc/codecs/rt5670.h index a8c3e44770b8..de0203369b7c 100644 --- a/sound/soc/codecs/rt5670.h +++ b/sound/soc/codecs/rt5670.h @@ -757,7 +757,7 @@ #define RT5670_PWR_VREF2_BIT 4 #define RT5670_PWR_FV2 (0x1 << 3) #define RT5670_PWR_FV2_BIT 3 -#define RT5670_LDO_SEL_MASK (0x3) +#define RT5670_LDO_SEL_MASK (0x7) #define RT5670_LDO_SEL_SFT 0 /* Power Management for Analog 2 (0x64) */ diff --git a/sound/soc/codecs/rt5682.c b/sound/soc/codecs/rt5682.c index 7d6670abdb08..d503b5bef4ba 100644 --- a/sound/soc/codecs/rt5682.c +++ b/sound/soc/codecs/rt5682.c @@ -967,13 +967,12 @@ int rt5682_headset_detect(struct snd_soc_component *component, int jack_insert) rt5682_enable_push_button_irq(component, false); snd_soc_component_update_bits(component, RT5682_CBJ_CTRL_1, RT5682_TRIG_JD_MASK, RT5682_TRIG_JD_LOW); - if (snd_soc_dapm_get_pin_status(dapm, "MICBIAS")) + if (!snd_soc_dapm_get_pin_status(dapm, "MICBIAS")) snd_soc_component_update_bits(component, - RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0); - else + RT5682_PWR_ANLG_1, RT5682_PWR_MB, 0); + if (!snd_soc_dapm_get_pin_status(dapm, "Vref2")) snd_soc_component_update_bits(component, - RT5682_PWR_ANLG_1, - RT5682_PWR_VREF2 | RT5682_PWR_MB, 0); + RT5682_PWR_ANLG_1, RT5682_PWR_VREF2, 0); snd_soc_component_update_bits(component, RT5682_PWR_ANLG_3, RT5682_PWR_CBJ, 0); @@ -992,16 +991,17 @@ static int rt5682_set_jack_detect(struct snd_soc_component *component, rt5682->hs_jack = hs_jack; - if (!rt5682->is_sdw) { - if (!hs_jack) { - regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, - RT5682_JD1_EN_MASK, RT5682_JD1_DIS); - regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, - RT5682_POW_JDH | RT5682_POW_JDL, 0); - cancel_delayed_work_sync(&rt5682->jack_detect_work); - return 0; - } + if (!hs_jack) { + regmap_update_bits(rt5682->regmap, RT5682_IRQ_CTRL_2, + RT5682_JD1_EN_MASK, RT5682_JD1_DIS); + regmap_update_bits(rt5682->regmap, RT5682_RC_CLK_CTRL, + RT5682_POW_JDH | RT5682_POW_JDL, 0); + cancel_delayed_work_sync(&rt5682->jack_detect_work); + return 0; + } + + if (!rt5682->is_sdw) { switch (rt5682->pdata.jd_src) { case RT5682_JD1: snd_soc_component_update_bits(component, @@ -1082,7 +1082,8 @@ void rt5682_jack_detect_handler(struct work_struct *work) /* jack was out, report jack type */ rt5682->jack_type = rt5682_headset_detect(rt5682->component, 1); - } else { + } else if ((rt5682->jack_type & SND_JACK_HEADSET) == + SND_JACK_HEADSET) { /* jack is already in, report button event */ rt5682->jack_type = SND_JACK_HEADSET; btn_type = rt5682_button_detect(rt5682->component); @@ -1608,8 +1609,7 @@ static const struct snd_soc_dapm_widget rt5682_dapm_widgets[] = { 0, set_filter_clk, SND_SOC_DAPM_PRE_PMU), SND_SOC_DAPM_SUPPLY("Vref1", RT5682_PWR_ANLG_1, RT5682_PWR_VREF1_BIT, 0, rt5682_set_verf, SND_SOC_DAPM_PRE_PMU | SND_SOC_DAPM_POST_PMU), - SND_SOC_DAPM_SUPPLY("Vref2", RT5682_PWR_ANLG_1, RT5682_PWR_VREF2_BIT, 0, - NULL, 0), + SND_SOC_DAPM_SUPPLY("Vref2", SND_SOC_NOPM, 0, 0, NULL, 0), SND_SOC_DAPM_SUPPLY("MICBIAS", SND_SOC_NOPM, 0, 0, NULL, 0), /* ASRC */ @@ -2492,6 +2492,15 @@ static int rt5682_wclk_prepare(struct clk_hw *hw) snd_soc_dapm_force_enable_pin_unlocked(dapm, "MICBIAS"); snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, RT5682_PWR_MB, RT5682_PWR_MB); + + snd_soc_dapm_force_enable_pin_unlocked(dapm, "Vref2"); + snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, + RT5682_PWR_VREF2 | RT5682_PWR_FV2, + RT5682_PWR_VREF2); + usleep_range(55000, 60000); + snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, + RT5682_PWR_FV2, RT5682_PWR_FV2); + snd_soc_dapm_force_enable_pin_unlocked(dapm, "I2S1"); snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2F"); snd_soc_dapm_force_enable_pin_unlocked(dapm, "PLL2B"); @@ -2517,9 +2526,12 @@ static void rt5682_wclk_unprepare(struct clk_hw *hw) snd_soc_dapm_mutex_lock(dapm); snd_soc_dapm_disable_pin_unlocked(dapm, "MICBIAS"); + snd_soc_dapm_disable_pin_unlocked(dapm, "Vref2"); if (!rt5682->jack_type) snd_soc_component_update_bits(component, RT5682_PWR_ANLG_1, + RT5682_PWR_VREF2 | RT5682_PWR_FV2 | RT5682_PWR_MB, 0); + snd_soc_dapm_disable_pin_unlocked(dapm, "I2S1"); snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2F"); snd_soc_dapm_disable_pin_unlocked(dapm, "PLL2B"); diff --git a/sound/soc/codecs/wm8974.c b/sound/soc/codecs/wm8974.c index 06ba36595ddd..7cfc89602fc3 100644 --- a/sound/soc/codecs/wm8974.c +++ b/sound/soc/codecs/wm8974.c @@ -186,7 +186,7 @@ SOC_DAPM_SINGLE("PCM Playback Switch", WM8974_MONOMIX, 0, 1, 0), /* Boost mixer */ static const struct snd_kcontrol_new wm8974_boost_mixer[] = { -SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 0), +SOC_DAPM_SINGLE("Aux Switch", WM8974_INPPGA, 6, 1, 1), }; /* Input PGA */ @@ -474,6 +474,10 @@ static int wm8974_set_dai_fmt(struct snd_soc_dai *codec_dai, iface |= 0x0008; break; case SND_SOC_DAIFMT_DSP_A: + if ((fmt & SND_SOC_DAIFMT_INV_MASK) == SND_SOC_DAIFMT_IB_IF || + (fmt & SND_SOC_DAIFMT_INV_MASK) == SND_SOC_DAIFMT_NB_IF) { + return -EINVAL; + } iface |= 0x00018; break; default: diff --git a/sound/soc/generic/audio-graph-card.c b/sound/soc/generic/audio-graph-card.c index 9ad35d9940fe..97b4f5480a31 100644 --- a/sound/soc/generic/audio-graph-card.c +++ b/sound/soc/generic/audio-graph-card.c @@ -317,8 +317,8 @@ static int graph_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node; - dai_link->dpcm_playback = 1; - dai_link->dpcm_capture = 1; + snd_soc_dai_link_set_capabilities(dai_link); + dai_link->ops = &graph_ops; dai_link->init = asoc_simple_dai_init; diff --git a/sound/soc/generic/simple-card.c b/sound/soc/generic/simple-card.c index 55e9f8800b3e..04d4d28ed511 100644 --- a/sound/soc/generic/simple-card.c +++ b/sound/soc/generic/simple-card.c @@ -231,8 +231,8 @@ static int simple_dai_link_of_dpcm(struct asoc_simple_priv *priv, if (ret < 0) goto out_put_node; - dai_link->dpcm_playback = 1; - dai_link->dpcm_capture = 1; + snd_soc_dai_link_set_capabilities(dai_link); + dai_link->ops = &simple_ops; dai_link->init = asoc_simple_dai_init; diff --git a/sound/soc/intel/boards/bdw-rt5677.c b/sound/soc/intel/boards/bdw-rt5677.c index 5f96d7ac0a22..bed4d5f73d9c 100644 --- a/sound/soc/intel/boards/bdw-rt5677.c +++ b/sound/soc/intel/boards/bdw-rt5677.c @@ -354,6 +354,7 @@ static struct snd_soc_dai_link bdw_rt5677_dais[] = { { .name = "Codec DSP", .stream_name = "Wake on Voice", + .capture_only = 1, .ops = &bdw_rt5677_dsp_ops, SND_SOC_DAILINK_REG(dsp), }, diff --git a/sound/soc/intel/boards/bytcht_es8316.c b/sound/soc/intel/boards/bytcht_es8316.c index 9e5fc9430628..ecbc58e8a37f 100644 --- a/sound/soc/intel/boards/bytcht_es8316.c +++ b/sound/soc/intel/boards/bytcht_es8316.c @@ -543,8 +543,10 @@ static int snd_byt_cht_es8316_mc_probe(struct platform_device *pdev) if (cnt) { ret = device_add_properties(codec_dev, props); - if (ret) + if (ret) { + put_device(codec_dev); return ret; + } } devm_acpi_dev_add_driver_gpios(codec_dev, byt_cht_es8316_gpios); diff --git a/sound/soc/intel/boards/cht_bsw_rt5672.c b/sound/soc/intel/boards/cht_bsw_rt5672.c index 7a43c70a1378..22e432768edb 100644 --- a/sound/soc/intel/boards/cht_bsw_rt5672.c +++ b/sound/soc/intel/boards/cht_bsw_rt5672.c @@ -253,21 +253,20 @@ static int cht_codec_fixup(struct snd_soc_pcm_runtime *rtd, params_set_format(params, SNDRV_PCM_FORMAT_S24_LE); /* - * Default mode for SSP configuration is TDM 4 slot + * Default mode for SSP configuration is TDM 4 slot. One board/design, + * the Lenovo Miix 2 10 uses not 1 but 2 codecs connected to SSP2. The + * second piggy-backed, output-only codec is inside the keyboard-dock + * (which has extra speakers). Unlike the main rt5672 codec, we cannot + * configure this codec, it is hard coded to use 2 channel 24 bit I2S. + * Since we only support 2 channels anyways, there is no need for TDM + * on any cht-bsw-rt5672 designs. So we simply use I2S 2ch everywhere. */ - ret = snd_soc_dai_set_fmt(asoc_rtd_to_codec(rtd, 0), - SND_SOC_DAIFMT_DSP_B | - SND_SOC_DAIFMT_IB_NF | + ret = snd_soc_dai_set_fmt(asoc_rtd_to_cpu(rtd, 0), + SND_SOC_DAIFMT_I2S | + SND_SOC_DAIFMT_NB_NF | SND_SOC_DAIFMT_CBS_CFS); if (ret < 0) { - dev_err(rtd->dev, "can't set format to TDM %d\n", ret); - return ret; - } - - /* TDM 4 slots 24 bit, set Rx & Tx bitmask to 4 active slots */ - ret = snd_soc_dai_set_tdm_slot(asoc_rtd_to_codec(rtd, 0), 0xF, 0xF, 4, 24); - if (ret < 0) { - dev_err(rtd->dev, "can't set codec TDM slot %d\n", ret); + dev_err(rtd->dev, "can't set format to I2S, err %d\n", ret); return ret; } diff --git a/sound/soc/qcom/Kconfig b/sound/soc/qcom/Kconfig index f51b28d1b94d..92f51d0e9fe2 100644 --- a/sound/soc/qcom/Kconfig +++ b/sound/soc/qcom/Kconfig @@ -72,7 +72,7 @@ config SND_SOC_QDSP6_ASM_DAI config SND_SOC_QDSP6 tristate "SoC ALSA audio driver for QDSP6" - depends on QCOM_APR && HAS_DMA + depends on QCOM_APR select SND_SOC_QDSP6_COMMON select SND_SOC_QDSP6_CORE select SND_SOC_QDSP6_AFE diff --git a/sound/soc/rockchip/rk3399_gru_sound.c b/sound/soc/rockchip/rk3399_gru_sound.c index f45e5aaa4b30..9539b0d024fe 100644 --- a/sound/soc/rockchip/rk3399_gru_sound.c +++ b/sound/soc/rockchip/rk3399_gru_sound.c @@ -219,19 +219,32 @@ static int rockchip_sound_dmic_hw_params(struct snd_pcm_substream *substream, return 0; } +static int rockchip_sound_startup(struct snd_pcm_substream *substream) +{ + struct snd_pcm_runtime *runtime = substream->runtime; + + runtime->hw.formats = SNDRV_PCM_FMTBIT_S16_LE; + return snd_pcm_hw_constraint_minmax(runtime, SNDRV_PCM_HW_PARAM_RATE, + 8000, 96000); +} + static const struct snd_soc_ops rockchip_sound_max98357a_ops = { + .startup = rockchip_sound_startup, .hw_params = rockchip_sound_max98357a_hw_params, }; static const struct snd_soc_ops rockchip_sound_rt5514_ops = { + .startup = rockchip_sound_startup, .hw_params = rockchip_sound_rt5514_hw_params, }; static const struct snd_soc_ops rockchip_sound_da7219_ops = { + .startup = rockchip_sound_startup, .hw_params = rockchip_sound_da7219_hw_params, }; static const struct snd_soc_ops rockchip_sound_dmic_ops = { + .startup = rockchip_sound_startup, .hw_params = rockchip_sound_dmic_hw_params, }; diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c index 0f30f5aabaa8..2b8abf88ec60 100644 --- a/sound/soc/soc-core.c +++ b/sound/soc/soc-core.c @@ -2573,6 +2573,33 @@ int snd_soc_register_component(struct device *dev, EXPORT_SYMBOL_GPL(snd_soc_register_component); /** + * snd_soc_unregister_component_by_driver - Unregister component using a given driver + * from the ASoC core + * + * @dev: The device to unregister + * @component_driver: The component driver to unregister + */ +void snd_soc_unregister_component_by_driver(struct device *dev, + const struct snd_soc_component_driver *component_driver) +{ + struct snd_soc_component *component; + + if (!component_driver) + return; + + mutex_lock(&client_mutex); + component = snd_soc_lookup_component_nolocked(dev, component_driver->name); + if (!component) + goto out; + + snd_soc_del_component_unlocked(component); + +out: + mutex_unlock(&client_mutex); +} +EXPORT_SYMBOL_GPL(snd_soc_unregister_component_by_driver); + +/** * snd_soc_unregister_component - Unregister all related component * from the ASoC core * diff --git a/sound/soc/soc-dai.c b/sound/soc/soc-dai.c index b05e18b63a1c..457159975b01 100644 --- a/sound/soc/soc-dai.c +++ b/sound/soc/soc-dai.c @@ -391,6 +391,44 @@ bool snd_soc_dai_stream_valid(struct snd_soc_dai *dai, int dir) return stream->channels_min; } +/* + * snd_soc_dai_link_set_capabilities() - set dai_link properties based on its DAIs + */ +void snd_soc_dai_link_set_capabilities(struct snd_soc_dai_link *dai_link) +{ + struct snd_soc_dai_link_component *cpu; + struct snd_soc_dai_link_component *codec; + struct snd_soc_dai *dai; + bool supported[SNDRV_PCM_STREAM_LAST + 1]; + int direction; + int i; + + for_each_pcm_streams(direction) { + supported[direction] = true; + + for_each_link_cpus(dai_link, i, cpu) { + dai = snd_soc_find_dai(cpu); + if (!dai || !snd_soc_dai_stream_valid(dai, direction)) { + supported[direction] = false; + break; + } + } + if (!supported[direction]) + continue; + for_each_link_codecs(dai_link, i, codec) { + dai = snd_soc_find_dai(codec); + if (!dai || !snd_soc_dai_stream_valid(dai, direction)) { + supported[direction] = false; + break; + } + } + } + + dai_link->dpcm_playback = supported[SNDRV_PCM_STREAM_PLAYBACK]; + dai_link->dpcm_capture = supported[SNDRV_PCM_STREAM_CAPTURE]; +} +EXPORT_SYMBOL_GPL(snd_soc_dai_link_set_capabilities); + void snd_soc_dai_action(struct snd_soc_dai *dai, int stream, int action) { diff --git a/sound/soc/soc-devres.c b/sound/soc/soc-devres.c index 11e5d7962370..4534a1c03e8e 100644 --- a/sound/soc/soc-devres.c +++ b/sound/soc/soc-devres.c @@ -48,7 +48,9 @@ EXPORT_SYMBOL_GPL(devm_snd_soc_register_dai); static void devm_component_release(struct device *dev, void *res) { - snd_soc_unregister_component(*(struct device **)res); + const struct snd_soc_component_driver **cmpnt_drv = res; + + snd_soc_unregister_component_by_driver(dev, *cmpnt_drv); } /** @@ -65,7 +67,7 @@ int devm_snd_soc_register_component(struct device *dev, const struct snd_soc_component_driver *cmpnt_drv, struct snd_soc_dai_driver *dai_drv, int num_dai) { - struct device **ptr; + const struct snd_soc_component_driver **ptr; int ret; ptr = devres_alloc(devm_component_release, sizeof(*ptr), GFP_KERNEL); @@ -74,7 +76,7 @@ int devm_snd_soc_register_component(struct device *dev, ret = snd_soc_register_component(dev, cmpnt_drv, dai_drv, num_dai); if (ret == 0) { - *ptr = dev; + *ptr = cmpnt_drv; devres_add(dev, ptr); } else { devres_free(ptr); diff --git a/sound/soc/soc-generic-dmaengine-pcm.c b/sound/soc/soc-generic-dmaengine-pcm.c index 80a4e71f2d95..61844403f181 100644 --- a/sound/soc/soc-generic-dmaengine-pcm.c +++ b/sound/soc/soc-generic-dmaengine-pcm.c @@ -478,7 +478,7 @@ void snd_dmaengine_pcm_unregister(struct device *dev) pcm = soc_component_to_pcm(component); - snd_soc_unregister_component(dev); + snd_soc_unregister_component_by_driver(dev, component->driver); dmaengine_pcm_release_chan(pcm); kfree(pcm); } diff --git a/sound/soc/soc-topology.c b/sound/soc/soc-topology.c index 43e5745b06aa..6eaa00c21011 100644 --- a/sound/soc/soc-topology.c +++ b/sound/soc/soc-topology.c @@ -1261,17 +1261,29 @@ static int soc_tplg_dapm_graph_elems_load(struct soc_tplg *tplg, list_add(&routes[i]->dobj.list, &tplg->comp->dobj_list); ret = soc_tplg_add_route(tplg, routes[i]); - if (ret < 0) + if (ret < 0) { + /* + * this route was added to the list, it will + * be freed in remove_route() so increment the + * counter to skip it in the error handling + * below. + */ + i++; break; + } /* add route, but keep going if some fail */ snd_soc_dapm_add_routes(dapm, routes[i], 1); } - /* free memory allocated for all dapm routes in case of error */ - if (ret < 0) - for (i = 0; i < count ; i++) - kfree(routes[i]); + /* + * free memory allocated for all dapm routes not added to the + * list in case of error + */ + if (ret < 0) { + while (i < count) + kfree(routes[i++]); + } /* * free pointer to array of dapm routes as this is no longer needed. @@ -1359,7 +1371,6 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( if (err < 0) { dev_err(tplg->dev, "ASoC: failed to init %s\n", mc->hdr.name); - soc_tplg_free_tlv(tplg, &kc[i]); goto err_sm; } } @@ -1367,6 +1378,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_dmixer_create( err_sm: for (; i >= 0; i--) { + soc_tplg_free_tlv(tplg, &kc[i]); sm = (struct soc_mixer_control *)kc[i].private_value; kfree(sm); kfree(kc[i].name); diff --git a/sound/soc/sof/core.c b/sound/soc/sof/core.c index 339c4930b0c0..adc7c37145d6 100644 --- a/sound/soc/sof/core.c +++ b/sound/soc/sof/core.c @@ -345,15 +345,15 @@ int snd_sof_device_remove(struct device *dev) struct snd_sof_pdata *pdata = sdev->pdata; int ret; - ret = snd_sof_dsp_power_down_notify(sdev); - if (ret < 0) - dev_warn(dev, "error: %d failed to prepare DSP for device removal", - ret); - if (IS_ENABLED(CONFIG_SND_SOC_SOF_PROBE_WORK_QUEUE)) cancel_work_sync(&sdev->probe_work); if (sdev->fw_state > SOF_FW_BOOT_NOT_STARTED) { + ret = snd_sof_dsp_power_down_notify(sdev); + if (ret < 0) + dev_warn(dev, "error: %d failed to prepare DSP for device removal", + ret); + snd_sof_fw_unload(sdev); snd_sof_ipc_free(sdev); snd_sof_free_debug(sdev); diff --git a/sound/soc/sof/imx/imx8.c b/sound/soc/sof/imx/imx8.c index 63f9c20a1bac..a4fa8451d8cb 100644 --- a/sound/soc/sof/imx/imx8.c +++ b/sound/soc/sof/imx/imx8.c @@ -375,6 +375,14 @@ static int imx8_ipc_pcm_params(struct snd_sof_dev *sdev, static struct snd_soc_dai_driver imx8_dai[] = { { .name = "esai-port", + .playback = { + .channels_min = 1, + .channels_max = 8, + }, + .capture = { + .channels_min = 1, + .channels_max = 8, + }, }, }; diff --git a/sound/soc/sof/imx/imx8m.c b/sound/soc/sof/imx/imx8m.c index fa86a9e2990f..287114a37688 100644 --- a/sound/soc/sof/imx/imx8m.c +++ b/sound/soc/sof/imx/imx8m.c @@ -240,6 +240,14 @@ static int imx8m_ipc_pcm_params(struct snd_sof_dev *sdev, static struct snd_soc_dai_driver imx8m_dai[] = { { .name = "sai-port", + .playback = { + .channels_min = 1, + .channels_max = 32, + }, + .capture = { + .channels_min = 1, + .channels_max = 32, + }, }, }; diff --git a/tools/perf/pmu-events/arch/s390/cf_z15/extended.json b/tools/perf/pmu-events/arch/s390/cf_z15/extended.json index 2df2e231e9ee..24c4ba2a9ae5 100644 --- a/tools/perf/pmu-events/arch/s390/cf_z15/extended.json +++ b/tools/perf/pmu-events/arch/s390/cf_z15/extended.json @@ -380,7 +380,7 @@ { "Unit": "CPU-M-CF", "EventCode": "265", - "EventName": "DFLT_CCERROR", + "EventName": "DFLT_CCFINISH", "BriefDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2", "PublicDescription": "Increments by one for every DEFLATE CONVERSION CALL instruction executed that ended in Condition Codes 0, 1 or 2" }, diff --git a/tools/testing/selftests/net/fib_nexthop_multiprefix.sh b/tools/testing/selftests/net/fib_nexthop_multiprefix.sh index 9dc35a16e415..51df5e305855 100755 --- a/tools/testing/selftests/net/fib_nexthop_multiprefix.sh +++ b/tools/testing/selftests/net/fib_nexthop_multiprefix.sh @@ -144,7 +144,7 @@ setup() cleanup() { - for n in h1 r1 h2 h3 h4 + for n in h0 r1 h1 h2 h3 do ip netns del ${n} 2>/dev/null done diff --git a/tools/testing/selftests/net/ip_defrag.sh b/tools/testing/selftests/net/ip_defrag.sh index 15d3489ecd9c..ceb7ad4dbd94 100755 --- a/tools/testing/selftests/net/ip_defrag.sh +++ b/tools/testing/selftests/net/ip_defrag.sh @@ -6,6 +6,8 @@ set +x set -e +modprobe -q nf_defrag_ipv6 + readonly NETNS="ns-$(mktemp -u XXXXXX)" setup() { diff --git a/tools/testing/selftests/net/txtimestamp.sh b/tools/testing/selftests/net/txtimestamp.sh index eea6f5193693..31637769f59f 100755 --- a/tools/testing/selftests/net/txtimestamp.sh +++ b/tools/testing/selftests/net/txtimestamp.sh @@ -75,7 +75,7 @@ main() { fi } -if [[ "$(ip netns identify)" == "root" ]]; then +if [[ -z "$(ip netns identify)" ]]; then ./in_netns.sh $0 $@ else main $@ |