Merge remote-tracking branch 'djwong/ocfs2-vfs-reflink-6' into for-linus
authorAl Viro <viro@zeniv.linux.org.uk>
Fri, 16 Dec 2016 21:21:05 +0000 (16:21 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Fri, 16 Dec 2016 21:21:05 +0000 (16:21 -0500)
208 files changed:
CREDITS
Documentation/devicetree/bindings/net/ethernet.txt
Documentation/networking/nf_conntrack-sysctl.txt
MAINTAINERS
Makefile
arch/arc/include/asm/delay.h
arch/arc/include/asm/pgtable.h
arch/arc/mm/cache.c
arch/arm/boot/dts/Makefile
arch/arm/boot/dts/stih407-family.dtsi
arch/arm/boot/dts/sun5i-gr8-evb.dts [moved from arch/arm/boot/dts/ntc-gr8-evb.dts with 99% similarity]
arch/arm/boot/dts/sun5i-gr8.dtsi [moved from arch/arm/boot/dts/ntc-gr8.dtsi with 100% similarity]
arch/arm64/boot/dts/arm/juno-base.dtsi
arch/arm64/boot/dts/arm/juno-r1.dts
arch/arm64/boot/dts/arm/juno-r2.dts
arch/arm64/boot/dts/arm/juno.dts
drivers/ata/ahci.c
drivers/ata/libata-scsi.c
drivers/block/zram/zram_drv.c
drivers/clk/bcm/Kconfig
drivers/clk/sunxi-ng/ccu-sun6i-a31.c
drivers/clk/sunxi-ng/ccu-sun8i-a33.c
drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c
drivers/gpu/drm/amd/powerplay/smumgr/polaris10_smc.c
drivers/gpu/drm/arm/hdlcd_drv.c
drivers/gpu/drm/drm_ioctl.c
drivers/gpu/drm/i915/i915_gem.c
drivers/gpu/drm/i915/intel_display.c
drivers/gpu/drm/radeon/radeon_atpx_handler.c
drivers/i2c/busses/i2c-octeon-core.c
drivers/i2c/busses/i2c-octeon-core.h
drivers/input/mouse/psmouse-base.c
drivers/net/can/usb/peak_usb/pcan_ucan.h
drivers/net/can/usb/peak_usb/pcan_usb_core.c
drivers/net/can/usb/peak_usb/pcan_usb_core.h
drivers/net/can/usb/peak_usb/pcan_usb_fd.c
drivers/net/ethernet/altera/altera_tse_main.c
drivers/net/ethernet/amd/xgbe/xgbe-main.c
drivers/net/ethernet/aurora/nb8800.c
drivers/net/ethernet/broadcom/bcmsysport.c
drivers/net/ethernet/broadcom/genet/bcmgenet.c
drivers/net/ethernet/broadcom/genet/bcmmii.c
drivers/net/ethernet/cadence/macb.c
drivers/net/ethernet/chelsio/cxgb4/t4_pci_id_tbl.h
drivers/net/ethernet/freescale/fec.h
drivers/net/ethernet/freescale/fec_main.c
drivers/net/ethernet/freescale/fman/fman_memac.c
drivers/net/ethernet/freescale/fman/mac.c
drivers/net/ethernet/freescale/fs_enet/fs_enet-main.c
drivers/net/ethernet/freescale/gianfar.c
drivers/net/ethernet/freescale/ucc_geth.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igbvf/netdev.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/intel/ixgbevf/ixgbevf_main.c
drivers/net/ethernet/marvell/mvneta.c
drivers/net/ethernet/mediatek/mtk_eth_soc.c
drivers/net/ethernet/mellanox/mlx4/en_netdev.c
drivers/net/ethernet/mellanox/mlx4/main.c
drivers/net/ethernet/mellanox/mlx4/mcg.c
drivers/net/ethernet/qualcomm/emac/emac-phy.c
drivers/net/ethernet/qualcomm/emac/emac.c
drivers/net/ethernet/renesas/ravb_main.c
drivers/net/ethernet/renesas/sh_eth.c
drivers/net/ethernet/stmicro/stmmac/dwmac-generic.c
drivers/net/ethernet/stmicro/stmmac/dwmac-ipq806x.c
drivers/net/ethernet/stmicro/stmmac/dwmac-lpc18xx.c
drivers/net/ethernet/stmicro/stmmac/dwmac-meson.c
drivers/net/ethernet/stmicro/stmmac/dwmac-meson8b.c
drivers/net/ethernet/stmicro/stmmac/dwmac-rk.c
drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sti.c
drivers/net/ethernet/stmicro/stmmac/dwmac-stm32.c
drivers/net/ethernet/stmicro/stmmac/dwmac-sunxi.c
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.h
drivers/net/ethernet/synopsys/dwc_eth_qos.c
drivers/net/ethernet/ti/cpsw.c
drivers/net/ethernet/ti/davinci_emac.c
drivers/net/geneve.c
drivers/net/ipvlan/ipvlan_main.c
drivers/net/irda/w83977af_ir.c
drivers/net/macvtap.c
drivers/net/phy/realtek.c
drivers/net/tun.c
drivers/net/usb/asix_devices.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/qmi_wwan.c
drivers/net/vxlan.c
drivers/net/wireless/marvell/mwifiex/cfg80211.c
drivers/of/of_mdio.c
drivers/pci/host/pcie-designware-plat.c
drivers/pci/pcie/aer/aer_inject.c
drivers/pci/probe.c
drivers/pwm/pwm-meson.c
drivers/pwm/sysfs.c
drivers/scsi/be2iscsi/be_mgmt.c
drivers/scsi/hpsa.c
drivers/scsi/hpsa.h
drivers/scsi/libfc/fc_lport.c
drivers/scsi/mpt3sas/mpt3sas_scsih.c
drivers/scsi/mvsas/mv_sas.c
drivers/scsi/qlogicpti.h
fs/btrfs/ctree.h
fs/btrfs/file.c
fs/btrfs/ioctl.c
fs/cifs/cifsencrypt.c
fs/cifs/cifssmb.c
fs/cifs/connect.c
fs/isofs/rock.c
fs/ocfs2/alloc.c
fs/ocfs2/aops.c
fs/ocfs2/file.c
fs/ocfs2/file.h
fs/ocfs2/inode.h
fs/ocfs2/move_extents.c
fs/ocfs2/refcounttree.c
fs/ocfs2/refcounttree.h
fs/ocfs2/xattr.c
fs/overlayfs/super.c
fs/read_write.c
fs/xfs/xfs_file.c
fs/xfs/xfs_reflink.c
include/asm-generic/export.h
include/linux/compiler-gcc.h
include/linux/fs.h
include/linux/mlx4/device.h
include/linux/of_mdio.h
include/linux/pagemap.h
include/linux/pci.h
include/net/ipv6.h
include/net/netfilter/nf_conntrack.h
include/net/netfilter/nf_tables.h
include/uapi/linux/input-event-codes.h
include/uapi/linux/tc_act/Kbuild
init/Kconfig
kernel/bpf/verifier.c
kernel/module.c
lib/debugobjects.c
lib/test_kasan.c
mm/huge_memory.c
mm/kasan/kasan.c
mm/kasan/kasan.h
mm/kasan/report.c
mm/khugepaged.c
mm/mlock.c
mm/mremap.c
mm/truncate.c
mm/vmscan.c
mm/workingset.c
net/core/flow.c
net/core/rtnetlink.c
net/core/sock.c
net/dccp/ipv4.c
net/dsa/dsa.c
net/dsa/dsa2.c
net/dsa/slave.c
net/ipv4/Kconfig
net/ipv4/af_inet.c
net/ipv4/esp4.c
net/ipv4/ip_output.c
net/ipv4/netfilter.c
net/ipv4/netfilter/arp_tables.c
net/ipv6/datagram.c
net/ipv6/esp6.c
net/ipv6/icmp.c
net/ipv6/ip6_offload.c
net/ipv6/ip6_tunnel.c
net/ipv6/ip6_vti.c
net/ipv6/netfilter/nf_conntrack_reasm.c
net/ipv6/netfilter/nf_defrag_ipv6_hooks.c
net/ipv6/netfilter/nf_reject_ipv6.c
net/ipv6/output_core.c
net/l2tp/l2tp_ip.c
net/l2tp/l2tp_ip6.c
net/netfilter/nf_nat_core.c
net/netfilter/nf_tables_api.c
net/netfilter/nft_hash.c
net/netfilter/nft_range.c
net/netlink/af_netlink.c
net/netlink/af_netlink.h
net/openvswitch/conntrack.c
net/packet/af_packet.c
net/rds/tcp.c
net/sched/act_pedit.c
net/sched/cls_basic.c
net/sched/cls_bpf.c
net/sched/cls_cgroup.c
net/sched/cls_flow.c
net/sched/cls_flower.c
net/sched/cls_matchall.c
net/sched/cls_rsvp.h
net/sched/cls_tcindex.c
net/tipc/bearer.c
net/tipc/bearer.h
net/tipc/link.c
net/tipc/udp_media.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_user.c
samples/bpf/bpf_helpers.h
samples/bpf/sampleip_kern.c
samples/bpf/trace_event_kern.c
scripts/kconfig/Makefile
sound/sparc/dbri.c
virt/kvm/arm/vgic/vgic-v2.c
virt/kvm/arm/vgic/vgic-v3.c
virt/kvm/kvm_main.c

diff --git a/CREDITS b/CREDITS
index 8373676..d7ebdfb 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -9,7 +9,7 @@
                        Linus
 ----------
 
-M: Matt Mackal
+N: Matt Mackal
 E: mpm@selenic.com
 D: SLOB slab allocator
 
@@ -1910,7 +1910,7 @@ S: Ra'annana, Israel
 
 N: Andi Kleen
 E: andi@firstfloor.org
-U: http://www.halobates.de
+W: http://www.halobates.de
 D: network, x86, NUMA, various hacks
 S: Schwalbenstr. 96
 S: 85551 Ottobrunn
@@ -2089,8 +2089,8 @@ D: ST Microelectronics SPEAr13xx PCI host bridge driver
 D: Synopsys Designware PCI host bridge driver
 
 N: Gabor Kuti
-M: seasons@falcon.sch.bme.hu
-M: seasons@makosteszta.sote.hu
+E: seasons@falcon.sch.bme.hu
+E: seasons@makosteszta.sote.hu
 D: Original author of software suspend
 
 N: Jaroslav Kysela
index e1d7681..0515095 100644 (file)
@@ -9,10 +9,26 @@ The following properties are common to the Ethernet controllers:
 - max-speed: number, specifies maximum speed in Mbit/s supported by the device;
 - max-frame-size: number, maximum transfer unit (IEEE defined MTU), rather than
   the maximum frame size (there's contradiction in ePAPR).
-- phy-mode: string, operation mode of the PHY interface; supported values are
-  "mii", "gmii", "sgmii", "qsgmii", "tbi", "rev-mii", "rmii", "rgmii", "rgmii-id",
-  "rgmii-rxid", "rgmii-txid", "rtbi", "smii", "xgmii", "trgmii"; this is now a
-  de-facto standard property;
+- phy-mode: string, operation mode of the PHY interface. This is now a de-facto
+  standard property; supported values are:
+  * "mii"
+  * "gmii"
+  * "sgmii"
+  * "qsgmii"
+  * "tbi"
+  * "rev-mii"
+  * "rmii"
+  * "rgmii" (RX and TX delays are added by the MAC when required)
+  * "rgmii-id" (RGMII with internal RX and TX delays provided by the PHY, the
+     MAC should not add the RX or TX delays in this case)
+  * "rgmii-rxid" (RGMII with internal RX delay provided by the PHY, the MAC
+     should not add an RX delay in this case)
+  * "rgmii-txid" (RGMII with internal TX delay provided by the PHY, the MAC
+     should not add an TX delay in this case)
+  * "rtbi"
+  * "smii"
+  * "xgmii"
+  * "trgmii"
 - phy-connection-type: the same as "phy-mode" property but described in ePAPR;
 - phy-handle: phandle, specifies a reference to a node representing a PHY
   device; this property is described in ePAPR and so preferred;
index 399e4e8..433b672 100644 (file)
@@ -62,10 +62,13 @@ nf_conntrack_generic_timeout - INTEGER (seconds)
        protocols.
 
 nf_conntrack_helper - BOOLEAN
-       0 - disabled
-       not 0 - enabled (default)
+       0 - disabled (default)
+       not 0 - enabled
 
        Enable automatic conntrack helper assignment.
+       If disabled it is required to set up iptables rules to assign
+       helpers to connections.  See the CT target description in the
+       iptables-extensions(8) man page for further information.
 
 nf_conntrack_icmp_timeout - INTEGER (seconds)
        default 30
index 8d41484..63cefa6 100644 (file)
@@ -9257,11 +9257,12 @@ S:      Maintained
 F:     drivers/pci/host/*layerscape*
 
 PCI DRIVER FOR IMX6
-M:     Richard Zhu <Richard.Zhu@freescale.com>
+M:     Richard Zhu <hongxing.zhu@nxp.com>
 M:     Lucas Stach <l.stach@pengutronix.de>
 L:     linux-pci@vger.kernel.org
 L:     linux-arm-kernel@lists.infradead.org (moderated for non-subscribers)
 S:     Maintained
+F:     Documentation/devicetree/bindings/pci/fsl,imx6q-pcie.txt
 F:     drivers/pci/host/*imx6*
 
 PCI DRIVER FOR TI KEYSTONE
@@ -9320,17 +9321,11 @@ F:      drivers/pci/host/pci-exynos.c
 
 PCI DRIVER FOR SYNOPSIS DESIGNWARE
 M:     Jingoo Han <jingoohan1@gmail.com>
-M:     Pratyush Anand <pratyush.anand@gmail.com>
-L:     linux-pci@vger.kernel.org
-S:     Maintained
-F:     drivers/pci/host/*designware*
-
-PCI DRIVER FOR SYNOPSYS PROTOTYPING DEVICE
-M:     Jose Abreu <Jose.Abreu@synopsys.com>
+M:     Joao Pinto <Joao.Pinto@synopsys.com>
 L:     linux-pci@vger.kernel.org
 S:     Maintained
 F:     Documentation/devicetree/bindings/pci/designware-pcie.txt
-F:     drivers/pci/host/pcie-designware-plat.c
+F:     drivers/pci/host/*designware*
 
 PCI DRIVER FOR GENERIC OF HOSTS
 M:     Will Deacon <will.deacon@arm.com>
index 694111b..369099d 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
 VERSION = 4
 PATCHLEVEL = 9
 SUBLEVEL = 0
-EXTRAVERSION = -rc7
+EXTRAVERSION = -rc8
 NAME = Psychotic Stoned Sheep
 
 # *DOCUMENTATION*
@@ -607,6 +607,13 @@ else
 include/config/auto.conf: ;
 endif # $(dot-config)
 
+# For the kernel to actually contain only the needed exported symbols,
+# we have to build modules as well to determine what those symbols are.
+# (this can be evaluated only once include/config/auto.conf has been included)
+ifdef CONFIG_TRIM_UNUSED_KSYMS
+  KBUILD_MODULES := 1
+endif
+
 # The all: target is the default when no target is given on the
 # command line.
 # This allow a user to issue only 'make' to build a kernel including modules
@@ -944,7 +951,7 @@ ifdef CONFIG_GDB_SCRIPTS
 endif
 ifdef CONFIG_TRIM_UNUSED_KSYMS
        $(Q)$(CONFIG_SHELL) $(srctree)/scripts/adjust_autoksyms.sh \
-         "$(MAKE) KBUILD_MODULES=1 -f $(srctree)/Makefile vmlinux_prereq"
+         "$(MAKE) -f $(srctree)/Makefile vmlinux"
 endif
 
 # standalone target for easier testing
@@ -1019,8 +1026,6 @@ prepare2: prepare3 prepare-compiler-check outputmakefile asm-generic
 prepare1: prepare2 $(version_h) include/generated/utsrelease.h \
                    include/config/auto.conf
        $(cmd_crmodverdir)
-       $(Q)test -e include/generated/autoksyms.h || \
-           touch   include/generated/autoksyms.h
 
 archprepare: archheaders archscripts prepare1 scripts_basic
 
index 08e7e2a..a36e860 100644 (file)
 static inline void __delay(unsigned long loops)
 {
        __asm__ __volatile__(
-       "       lp  1f  \n"
-       "       nop     \n"
-       "1:             \n"
-       : "+l"(loops));
+       "       mov lp_count, %0        \n"
+       "       lp  1f                  \n"
+       "       nop                     \n"
+       "1:                             \n"
+       : : "r"(loops));
 }
 
 extern void __bad_udelay(void);
index 89eeb37..e94ca72 100644 (file)
@@ -280,7 +280,7 @@ static inline void pmd_set(pmd_t *pmdp, pte_t *ptep)
 
 #define pte_page(pte)          pfn_to_page(pte_pfn(pte))
 #define mk_pte(page, prot)     pfn_pte(page_to_pfn(page), prot)
-#define pfn_pte(pfn, prot)     __pte(((pfn) << PAGE_SHIFT) | pgprot_val(prot))
+#define pfn_pte(pfn, prot)     __pte(__pfn_to_phys(pfn) | pgprot_val(prot))
 
 /* Don't use virt_to_pfn for macros below: could cause truncations for PAE40*/
 #define pte_pfn(pte)           (pte_val(pte) >> PAGE_SHIFT)
index 2b96cfc..50d7169 100644 (file)
@@ -23,7 +23,7 @@
 
 static int l2_line_sz;
 static int ioc_exists;
-int slc_enable = 1, ioc_enable = 1;
+int slc_enable = 1, ioc_enable = 0;
 unsigned long perip_base = ARC_UNCACHED_ADDR_SPACE; /* legacy value for boot */
 unsigned long perip_end = 0xFFFFFFFF; /* legacy value */
 
index befcd26..c558ba7 100644 (file)
@@ -745,7 +745,6 @@ dtb-$(CONFIG_MACH_SUN4I) += \
        sun4i-a10-pcduino2.dtb \
        sun4i-a10-pov-protab2-ips9.dtb
 dtb-$(CONFIG_MACH_SUN5I) += \
-       ntc-gr8-evb.dtb \
        sun5i-a10s-auxtek-t003.dtb \
        sun5i-a10s-auxtek-t004.dtb \
        sun5i-a10s-mk802.dtb \
@@ -761,6 +760,7 @@ dtb-$(CONFIG_MACH_SUN5I) += \
        sun5i-a13-olinuxino-micro.dtb \
        sun5i-a13-q8-tablet.dtb \
        sun5i-a13-utoo-p66.dtb \
+       sun5i-gr8-evb.dtb \
        sun5i-r8-chip.dtb
 dtb-$(CONFIG_MACH_SUN6I) += \
        sun6i-a31-app4-evb1.dtb \
index 91096a4..8f79b41 100644 (file)
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c0_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c1_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c2_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c3_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c4_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c5_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c10_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
                        clock-frequency = <400000>;
                        pinctrl-names = "default";
                        pinctrl-0 = <&pinctrl_i2c11_default>;
+                       #address-cells = <1>;
+                       #size-cells = <0>;
 
                        status = "disabled";
                };
similarity index 99%
rename from arch/arm/boot/dts/ntc-gr8-evb.dts
rename to arch/arm/boot/dts/sun5i-gr8-evb.dts
index 4b622f3..714381f 100644 (file)
@@ -44,7 +44,7 @@
  */
 
 /dts-v1/;
-#include "ntc-gr8.dtsi"
+#include "sun5i-gr8.dtsi"
 #include "sunxi-common-regulators.dtsi"
 
 #include <dt-bindings/gpio/gpio.h>
index 334271a..7d3a2ac 100644 (file)
                #address-cells = <3>;
                #size-cells = <2>;
                dma-coherent;
-               ranges = <0x01000000 0x00 0x5f800000 0x00 0x5f800000 0x0 0x00800000>,
+               ranges = <0x01000000 0x00 0x00000000 0x00 0x5f800000 0x0 0x00800000>,
                         <0x02000000 0x00 0x50000000 0x00 0x50000000 0x0 0x08000000>,
                         <0x42000000 0x40 0x00000000 0x40 0x00000000 0x1 0x00000000>;
                #interrupt-cells = <1>;
index 123a58b..f0b857d 100644 (file)
@@ -76,7 +76,7 @@
                                compatible = "arm,idle-state";
                                arm,psci-suspend-param = <0x1010000>;
                                local-timer-stop;
-                               entry-latency-us = <300>;
+                               entry-latency-us = <400>;
                                exit-latency-us = <1200>;
                                min-residency-us = <2500>;
                        };
index 007be82..26aaa6a 100644 (file)
@@ -76,7 +76,7 @@
                                compatible = "arm,idle-state";
                                arm,psci-suspend-param = <0x1010000>;
                                local-timer-stop;
-                               entry-latency-us = <300>;
+                               entry-latency-us = <400>;
                                exit-latency-us = <1200>;
                                min-residency-us = <2500>;
                        };
index a7270ef..6e154d9 100644 (file)
@@ -76,7 +76,7 @@
                                compatible = "arm,idle-state";
                                arm,psci-suspend-param = <0x1010000>;
                                local-timer-stop;
-                               entry-latency-us = <300>;
+                               entry-latency-us = <400>;
                                exit-latency-us = <1200>;
                                min-residency-us = <2500>;
                        };
index 9669fc7..74f4c66 100644 (file)
@@ -1436,13 +1436,6 @@ static int ahci_init_msi(struct pci_dev *pdev, unsigned int n_ports,
                                "ahci: MRSM is on, fallback to single MSI\n");
                        pci_free_irq_vectors(pdev);
                }
-
-               /*
-                * -ENOSPC indicated we don't have enough vectors.  Don't bother
-                * trying a single vectors for any other error:
-                */
-               if (nvec < 0 && nvec != -ENOSPC)
-                       return nvec;
        }
 
        /*
index 9cceb4a..c4eb4ae 100644 (file)
@@ -1088,7 +1088,7 @@ static void ata_gen_passthru_sense(struct ata_queued_cmd *qc)
                desc[1] = tf->command; /* status */
                desc[2] = tf->device;
                desc[3] = tf->nsect;
-               desc[0] = 0;
+               desc[7] = 0;
                if (tf->flags & ATA_TFLAG_LBA48)  {
                        desc[8] |= 0x80;
                        if (tf->hob_nsect)
index 04365b1..5163c8f 100644 (file)
@@ -1403,7 +1403,8 @@ static ssize_t hot_remove_store(struct class *class,
        zram = idr_find(&zram_index_idr, dev_id);
        if (zram) {
                ret = zram_remove(zram);
-               idr_remove(&zram_index_idr, dev_id);
+               if (!ret)
+                       idr_remove(&zram_index_idr, dev_id);
        } else {
                ret = -ENODEV;
        }
index f21e9b7..e3eed5a 100644 (file)
@@ -20,7 +20,7 @@ config CLK_BCM_KONA
 
 config COMMON_CLK_IPROC
        bool "Broadcom iProc clock support"
-       depends on ARCH_BCM_IPROC || COMPILE_TEST
+       depends on ARCH_BCM_IPROC || ARCH_BCM_63XX || COMPILE_TEST
        depends on COMMON_CLK
        default ARCH_BCM_IPROC
        help
index 4a82a49..fc75a33 100644 (file)
@@ -143,7 +143,7 @@ static SUNXI_CCU_NKM_WITH_MUX_GATE_LOCK(pll_mipi_clk, "pll-mipi",
                                        4, 2,   /* K */
                                        0, 4,   /* M */
                                        21, 0,  /* mux */
-                                       BIT(31),        /* gate */
+                                       BIT(31) | BIT(23) | BIT(22), /* gate */
                                        BIT(28),        /* lock */
                                        CLK_SET_RATE_UNGATE);
 
index 96b40ca..9bd1f78 100644 (file)
@@ -131,7 +131,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_mipi_clk, "pll-mipi",
                                    8, 4,               /* N */
                                    4, 2,               /* K */
                                    0, 4,               /* M */
-                                   BIT(31),            /* gate */
+                                   BIT(31) | BIT(23) | BIT(22), /* gate */
                                    BIT(28),            /* lock */
                                    CLK_SET_RATE_UNGATE);
 
index 02ca5dd..6c343a9 100644 (file)
@@ -485,7 +485,6 @@ static int amdgpu_atpx_power_state(enum vga_switcheroo_client_id id,
  */
 static bool amdgpu_atpx_pci_probe_handle(struct pci_dev *pdev)
 {
-       struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
        acpi_handle dhandle, atpx_handle;
        acpi_status status;
 
@@ -500,7 +499,6 @@ static bool amdgpu_atpx_pci_probe_handle(struct pci_dev *pdev)
        }
        amdgpu_atpx_priv.dhandle = dhandle;
        amdgpu_atpx_priv.atpx.handle = atpx_handle;
-       amdgpu_atpx_priv.bridge_pm_usable = parent_pdev && parent_pdev->bridge_d3;
        return true;
 }
 
@@ -562,17 +560,25 @@ static bool amdgpu_atpx_detect(void)
        struct pci_dev *pdev = NULL;
        bool has_atpx = false;
        int vga_count = 0;
+       bool d3_supported = false;
+       struct pci_dev *parent_pdev;
 
        while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
                vga_count++;
 
                has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
+
+               parent_pdev = pci_upstream_bridge(pdev);
+               d3_supported |= parent_pdev && parent_pdev->bridge_d3;
        }
 
        while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_OTHER << 8, pdev)) != NULL) {
                vga_count++;
 
                has_atpx |= (amdgpu_atpx_pci_probe_handle(pdev) == true);
+
+               parent_pdev = pci_upstream_bridge(pdev);
+               d3_supported |= parent_pdev && parent_pdev->bridge_d3;
        }
 
        if (has_atpx && vga_count == 2) {
@@ -580,6 +586,7 @@ static bool amdgpu_atpx_detect(void)
                printk(KERN_INFO "vga_switcheroo: detected switching method %s handle\n",
                       acpi_method_name);
                amdgpu_atpx_priv.atpx_detected = true;
+               amdgpu_atpx_priv.bridge_pm_usable = d3_supported;
                amdgpu_atpx_init();
                return true;
        }
index 4ccc0b7..71bb2f8 100644 (file)
@@ -2214,6 +2214,7 @@ uint32_t polaris10_get_mac_definition(uint32_t value)
 int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr)
 {
        struct polaris10_smumgr *smu_data = (struct polaris10_smumgr *)(hwmgr->smumgr->backend);
+       struct smu7_hwmgr *data = (struct smu7_hwmgr *)(hwmgr->backend);
        uint32_t tmp;
        int result;
        bool error = false;
@@ -2233,8 +2234,10 @@ int polaris10_process_firmware_header(struct pp_hwmgr *hwmgr)
                        offsetof(SMU74_Firmware_Header, SoftRegisters),
                        &tmp, SMC_RAM_END);
 
-       if (!result)
+       if (!result) {
+               data->soft_regs_start = tmp;
                smu_data->smu7_data.soft_regs_start = tmp;
+       }
 
        error |= (0 != result);
 
index fb6a418..e138fb5 100644 (file)
@@ -375,7 +375,6 @@ static int hdlcd_drm_bind(struct device *dev)
 
 err_fbdev:
        drm_kms_helper_poll_fini(drm);
-       drm_mode_config_cleanup(drm);
        drm_vblank_cleanup(drm);
 err_vblank:
        pm_runtime_disable(drm->dev);
@@ -387,6 +386,7 @@ err_unload:
        drm_irq_uninstall(drm);
        of_reserved_mem_device_release(drm->dev);
 err_free:
+       drm_mode_config_cleanup(drm);
        dev_set_drvdata(dev, NULL);
        drm_dev_unref(drm);
 
index 0ad2c47..71c3473 100644 (file)
@@ -254,10 +254,12 @@ static int drm_getcap(struct drm_device *dev, void *data, struct drm_file *file_
                req->value = dev->mode_config.async_page_flip;
                break;
        case DRM_CAP_PAGE_FLIP_TARGET:
-               req->value = 1;
-               drm_for_each_crtc(crtc, dev) {
-                       if (!crtc->funcs->page_flip_target)
-                               req->value = 0;
+               if (drm_core_check_feature(dev, DRIVER_MODESET)) {
+                       req->value = 1;
+                       drm_for_each_crtc(crtc, dev) {
+                               if (!crtc->funcs->page_flip_target)
+                                       req->value = 0;
+                       }
                }
                break;
        case DRM_CAP_CURSOR_WIDTH:
index 91ab7e9..00eb481 100644 (file)
@@ -2268,7 +2268,7 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
                        page = shmem_read_mapping_page(mapping, i);
                        if (IS_ERR(page)) {
                                ret = PTR_ERR(page);
-                               goto err_pages;
+                               goto err_sg;
                        }
                }
 #ifdef CONFIG_SWIOTLB
@@ -2311,8 +2311,9 @@ i915_gem_object_get_pages_gtt(struct drm_i915_gem_object *obj)
 
        return 0;
 
-err_pages:
+err_sg:
        sg_mark_end(sg);
+err_pages:
        for_each_sgt_page(page, sgt_iter, st)
                put_page(page);
        sg_free_table(st);
index 81c1149..3cb70d7 100644 (file)
@@ -12260,7 +12260,7 @@ static int intel_crtc_page_flip(struct drm_crtc *crtc,
        intel_crtc->reset_count = i915_reset_count(&dev_priv->gpu_error);
        if (i915_reset_in_progress_or_wedged(&dev_priv->gpu_error)) {
                ret = -EIO;
-               goto cleanup;
+               goto unlock;
        }
 
        atomic_inc(&intel_crtc->unpin_work_count);
@@ -12352,6 +12352,7 @@ cleanup_unpin:
        intel_unpin_fb_obj(fb, crtc->primary->state->rotation);
 cleanup_pending:
        atomic_dec(&intel_crtc->unpin_work_count);
+unlock:
        mutex_unlock(&dev->struct_mutex);
 cleanup:
        crtc->primary->fb = old_fb;
index 4129b12..0ae13cd 100644 (file)
@@ -479,7 +479,6 @@ static int radeon_atpx_power_state(enum vga_switcheroo_client_id id,
  */
 static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
 {
-       struct pci_dev *parent_pdev = pci_upstream_bridge(pdev);
        acpi_handle dhandle, atpx_handle;
        acpi_status status;
 
@@ -493,7 +492,6 @@ static bool radeon_atpx_pci_probe_handle(struct pci_dev *pdev)
 
        radeon_atpx_priv.dhandle = dhandle;
        radeon_atpx_priv.atpx.handle = atpx_handle;
-       radeon_atpx_priv.bridge_pm_usable = parent_pdev && parent_pdev->bridge_d3;
        return true;
 }
 
@@ -555,11 +553,16 @@ static bool radeon_atpx_detect(void)
        struct pci_dev *pdev = NULL;
        bool has_atpx = false;
        int vga_count = 0;
+       bool d3_supported = false;
+       struct pci_dev *parent_pdev;
 
        while ((pdev = pci_get_class(PCI_CLASS_DISPLAY_VGA << 8, pdev)) != NULL) {
                vga_count++;
 
                has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
+
+               parent_pdev = pci_upstream_bridge(pdev);
+               d3_supported |= parent_pdev && parent_pdev->bridge_d3;
        }
 
        /* some newer PX laptops mark the dGPU as a non-VGA display device */
@@ -567,6 +570,9 @@ static bool radeon_atpx_detect(void)
                vga_count++;
 
                has_atpx |= (radeon_atpx_pci_probe_handle(pdev) == true);
+
+               parent_pdev = pci_upstream_bridge(pdev);
+               d3_supported |= parent_pdev && parent_pdev->bridge_d3;
        }
 
        if (has_atpx && vga_count == 2) {
@@ -574,6 +580,7 @@ static bool radeon_atpx_detect(void)
                printk(KERN_INFO "vga_switcheroo: detected switching method %s handle\n",
                       acpi_method_name);
                radeon_atpx_priv.atpx_detected = true;
+               radeon_atpx_priv.bridge_pm_usable = d3_supported;
                radeon_atpx_init();
                return true;
        }
index 419b54b..5e63b17 100644 (file)
@@ -381,9 +381,7 @@ static int octeon_i2c_read(struct octeon_i2c *i2c, int target,
                if (result)
                        return result;
 
-               data[i] = octeon_i2c_data_read(i2c, &result);
-               if (result)
-                       return result;
+               data[i] = octeon_i2c_data_read(i2c);
                if (recv_len && i == 0) {
                        if (data[i] > I2C_SMBUS_BLOCK_MAX + 1)
                                return -EPROTO;
index 1db7c83..87151ea 100644 (file)
@@ -5,7 +5,6 @@
 #include <linux/i2c.h>
 #include <linux/i2c-smbus.h>
 #include <linux/io.h>
-#include <linux/iopoll.h>
 #include <linux/kernel.h>
 #include <linux/pci.h>
 
@@ -145,9 +144,9 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8
        u64 tmp;
 
        __raw_writeq(SW_TWSI_V | eop_reg | data, i2c->twsi_base + SW_TWSI(i2c));
-
-       readq_poll_timeout(i2c->twsi_base + SW_TWSI(i2c), tmp, tmp & SW_TWSI_V,
-                          I2C_OCTEON_EVENT_WAIT, i2c->adap.timeout);
+       do {
+               tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       } while ((tmp & SW_TWSI_V) != 0);
 }
 
 #define octeon_i2c_ctl_write(i2c, val)                                 \
@@ -164,28 +163,24 @@ static inline void octeon_i2c_reg_write(struct octeon_i2c *i2c, u64 eop_reg, u8
  *
  * The I2C core registers are accessed indirectly via the SW_TWSI CSR.
  */
-static inline int octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg,
-                                     int *error)
+static inline u8 octeon_i2c_reg_read(struct octeon_i2c *i2c, u64 eop_reg)
 {
        u64 tmp;
-       int ret;
 
        __raw_writeq(SW_TWSI_V | eop_reg | SW_TWSI_R, i2c->twsi_base + SW_TWSI(i2c));
+       do {
+               tmp = __raw_readq(i2c->twsi_base + SW_TWSI(i2c));
+       } while ((tmp & SW_TWSI_V) != 0);
 
-       ret = readq_poll_timeout(i2c->twsi_base + SW_TWSI(i2c), tmp,
-                                tmp & SW_TWSI_V, I2C_OCTEON_EVENT_WAIT,
-                                i2c->adap.timeout);
-       if (error)
-               *error = ret;
        return tmp & 0xFF;
 }
 
 #define octeon_i2c_ctl_read(i2c)                                       \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL, NULL)
-#define octeon_i2c_data_read(i2c, error)                               \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA, error)
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_CTL)
+#define octeon_i2c_data_read(i2c)                                      \
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_DATA)
 #define octeon_i2c_stat_read(i2c)                                      \
-       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT, NULL)
+       octeon_i2c_reg_read(i2c, SW_TWSI_EOP_TWSI_STAT)
 
 /**
  * octeon_i2c_read_int - read the TWSI_INT register
index fb4b185..bee2674 100644 (file)
@@ -1115,10 +1115,6 @@ static int psmouse_extensions(struct psmouse *psmouse,
                if (psmouse_try_protocol(psmouse, PSMOUSE_TOUCHKIT_PS2,
                                         &max_proto, set_properties, true))
                        return PSMOUSE_TOUCHKIT_PS2;
-
-               if (psmouse_try_protocol(psmouse, PSMOUSE_BYD,
-                                        &max_proto, set_properties, true))
-                       return PSMOUSE_BYD;
        }
 
        /*
index e8fc495..2147678 100644 (file)
@@ -43,11 +43,22 @@ struct __packed pucan_command {
        u16     args[3];
 };
 
+#define PUCAN_TSLOW_BRP_BITS           10
+#define PUCAN_TSLOW_TSGEG1_BITS                8
+#define PUCAN_TSLOW_TSGEG2_BITS                7
+#define PUCAN_TSLOW_SJW_BITS           7
+
+#define PUCAN_TSLOW_BRP_MASK           ((1 << PUCAN_TSLOW_BRP_BITS) - 1)
+#define PUCAN_TSLOW_TSEG1_MASK         ((1 << PUCAN_TSLOW_TSGEG1_BITS) - 1)
+#define PUCAN_TSLOW_TSEG2_MASK         ((1 << PUCAN_TSLOW_TSGEG2_BITS) - 1)
+#define PUCAN_TSLOW_SJW_MASK           ((1 << PUCAN_TSLOW_SJW_BITS) - 1)
+
 /* uCAN TIMING_SLOW command fields */
-#define PUCAN_TSLOW_SJW_T(s, t)                (((s) & 0xf) | ((!!(t)) << 7))
-#define PUCAN_TSLOW_TSEG2(t)           ((t) & 0xf)
-#define PUCAN_TSLOW_TSEG1(t)           ((t) & 0x3f)
-#define PUCAN_TSLOW_BRP(b)             ((b) & 0x3ff)
+#define PUCAN_TSLOW_SJW_T(s, t)                (((s) & PUCAN_TSLOW_SJW_MASK) | \
+                                                               ((!!(t)) << 7))
+#define PUCAN_TSLOW_TSEG2(t)           ((t) & PUCAN_TSLOW_TSEG2_MASK)
+#define PUCAN_TSLOW_TSEG1(t)           ((t) & PUCAN_TSLOW_TSEG1_MASK)
+#define PUCAN_TSLOW_BRP(b)             ((b) & PUCAN_TSLOW_BRP_MASK)
 
 struct __packed pucan_timing_slow {
        __le16  opcode_channel;
@@ -60,11 +71,21 @@ struct __packed pucan_timing_slow {
        __le16  brp;            /* BaudRate Prescaler */
 };
 
+#define PUCAN_TFAST_BRP_BITS           10
+#define PUCAN_TFAST_TSGEG1_BITS                5
+#define PUCAN_TFAST_TSGEG2_BITS                4
+#define PUCAN_TFAST_SJW_BITS           4
+
+#define PUCAN_TFAST_BRP_MASK           ((1 << PUCAN_TFAST_BRP_BITS) - 1)
+#define PUCAN_TFAST_TSEG1_MASK         ((1 << PUCAN_TFAST_TSGEG1_BITS) - 1)
+#define PUCAN_TFAST_TSEG2_MASK         ((1 << PUCAN_TFAST_TSGEG2_BITS) - 1)
+#define PUCAN_TFAST_SJW_MASK           ((1 << PUCAN_TFAST_SJW_BITS) - 1)
+
 /* uCAN TIMING_FAST command fields */
-#define PUCAN_TFAST_SJW(s)             ((s) & 0x3)
-#define PUCAN_TFAST_TSEG2(t)           ((t) & 0x7)
-#define PUCAN_TFAST_TSEG1(t)           ((t) & 0xf)
-#define PUCAN_TFAST_BRP(b)             ((b) & 0x3ff)
+#define PUCAN_TFAST_SJW(s)             ((s) & PUCAN_TFAST_SJW_MASK)
+#define PUCAN_TFAST_TSEG2(t)           ((t) & PUCAN_TFAST_TSEG2_MASK)
+#define PUCAN_TFAST_TSEG1(t)           ((t) & PUCAN_TFAST_TSEG1_MASK)
+#define PUCAN_TFAST_BRP(b)             ((b) & PUCAN_TFAST_BRP_MASK)
 
 struct __packed pucan_timing_fast {
        __le16  opcode_channel;
index c06382c..f3141ca 100644 (file)
@@ -39,6 +39,7 @@ static struct usb_device_id peak_usb_table[] = {
        {USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBPRO_PRODUCT_ID)},
        {USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBFD_PRODUCT_ID)},
        {USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBPROFD_PRODUCT_ID)},
+       {USB_DEVICE(PCAN_USB_VENDOR_ID, PCAN_USBX6_PRODUCT_ID)},
        {} /* Terminating entry */
 };
 
@@ -50,6 +51,7 @@ static const struct peak_usb_adapter *const peak_usb_adapters_list[] = {
        &pcan_usb_pro,
        &pcan_usb_fd,
        &pcan_usb_pro_fd,
+       &pcan_usb_x6,
 };
 
 /*
index 506fe50..3cbfb06 100644 (file)
@@ -27,6 +27,7 @@
 #define PCAN_USBPRO_PRODUCT_ID         0x000d
 #define PCAN_USBPROFD_PRODUCT_ID       0x0011
 #define PCAN_USBFD_PRODUCT_ID          0x0012
+#define PCAN_USBX6_PRODUCT_ID          0x0014
 
 #define PCAN_USB_DRIVER_NAME           "peak_usb"
 
@@ -90,6 +91,7 @@ extern const struct peak_usb_adapter pcan_usb;
 extern const struct peak_usb_adapter pcan_usb_pro;
 extern const struct peak_usb_adapter pcan_usb_fd;
 extern const struct peak_usb_adapter pcan_usb_pro_fd;
+extern const struct peak_usb_adapter pcan_usb_x6;
 
 struct peak_time_ref {
        struct timeval tv_host_0, tv_host;
index ce44a03..3047325 100644 (file)
@@ -993,24 +993,24 @@ static void pcan_usb_fd_free(struct peak_usb_device *dev)
 static const struct can_bittiming_const pcan_usb_fd_const = {
        .name = "pcan_usb_fd",
        .tseg1_min = 1,
-       .tseg1_max = 64,
+       .tseg1_max = (1 << PUCAN_TSLOW_TSGEG1_BITS),
        .tseg2_min = 1,
-       .tseg2_max = 16,
-       .sjw_max = 16,
+       .tseg2_max = (1 << PUCAN_TSLOW_TSGEG2_BITS),
+       .sjw_max = (1 << PUCAN_TSLOW_SJW_BITS),
        .brp_min = 1,
-       .brp_max = 1024,
+       .brp_max = (1 << PUCAN_TSLOW_BRP_BITS),
        .brp_inc = 1,
 };
 
 static const struct can_bittiming_const pcan_usb_fd_data_const = {
        .name = "pcan_usb_fd",
        .tseg1_min = 1,
-       .tseg1_max = 16,
+       .tseg1_max = (1 << PUCAN_TFAST_TSGEG1_BITS),
        .tseg2_min = 1,
-       .tseg2_max = 8,
-       .sjw_max = 4,
+       .tseg2_max = (1 << PUCAN_TFAST_TSGEG2_BITS),
+       .sjw_max = (1 << PUCAN_TFAST_SJW_BITS),
        .brp_min = 1,
-       .brp_max = 1024,
+       .brp_max = (1 << PUCAN_TFAST_BRP_BITS),
        .brp_inc = 1,
 };
 
@@ -1065,24 +1065,24 @@ const struct peak_usb_adapter pcan_usb_fd = {
 static const struct can_bittiming_const pcan_usb_pro_fd_const = {
        .name = "pcan_usb_pro_fd",
        .tseg1_min = 1,
-       .tseg1_max = 64,
+       .tseg1_max = (1 << PUCAN_TSLOW_TSGEG1_BITS),
        .tseg2_min = 1,
-       .tseg2_max = 16,
-       .sjw_max = 16,
+       .tseg2_max = (1 << PUCAN_TSLOW_TSGEG2_BITS),
+       .sjw_max = (1 << PUCAN_TSLOW_SJW_BITS),
        .brp_min = 1,
-       .brp_max = 1024,
+       .brp_max = (1 << PUCAN_TSLOW_BRP_BITS),
        .brp_inc = 1,
 };
 
 static const struct can_bittiming_const pcan_usb_pro_fd_data_const = {
        .name = "pcan_usb_pro_fd",
        .tseg1_min = 1,
-       .tseg1_max = 16,
+       .tseg1_max = (1 << PUCAN_TFAST_TSGEG1_BITS),
        .tseg2_min = 1,
-       .tseg2_max = 8,
-       .sjw_max = 4,
+       .tseg2_max = (1 << PUCAN_TFAST_TSGEG2_BITS),
+       .sjw_max = (1 << PUCAN_TFAST_SJW_BITS),
        .brp_min = 1,
-       .brp_max = 1024,
+       .brp_max = (1 << PUCAN_TFAST_BRP_BITS),
        .brp_inc = 1,
 };
 
@@ -1132,3 +1132,75 @@ const struct peak_usb_adapter pcan_usb_pro_fd = {
 
        .do_get_berr_counter = pcan_usb_fd_get_berr_counter,
 };
+
+/* describes the PCAN-USB X6 adapter */
+static const struct can_bittiming_const pcan_usb_x6_const = {
+       .name = "pcan_usb_x6",
+       .tseg1_min = 1,
+       .tseg1_max = (1 << PUCAN_TSLOW_TSGEG1_BITS),
+       .tseg2_min = 1,
+       .tseg2_max = (1 << PUCAN_TSLOW_TSGEG2_BITS),
+       .sjw_max = (1 << PUCAN_TSLOW_SJW_BITS),
+       .brp_min = 1,
+       .brp_max = (1 << PUCAN_TSLOW_BRP_BITS),
+       .brp_inc = 1,
+};
+
+static const struct can_bittiming_const pcan_usb_x6_data_const = {
+       .name = "pcan_usb_x6",
+       .tseg1_min = 1,
+       .tseg1_max = (1 << PUCAN_TFAST_TSGEG1_BITS),
+       .tseg2_min = 1,
+       .tseg2_max = (1 << PUCAN_TFAST_TSGEG2_BITS),
+       .sjw_max = (1 << PUCAN_TFAST_SJW_BITS),
+       .brp_min = 1,
+       .brp_max = (1 << PUCAN_TFAST_BRP_BITS),
+       .brp_inc = 1,
+};
+
+const struct peak_usb_adapter pcan_usb_x6 = {
+       .name = "PCAN-USB X6",
+       .device_id = PCAN_USBX6_PRODUCT_ID,
+       .ctrl_count = PCAN_USBPROFD_CHANNEL_COUNT,
+       .ctrlmode_supported = CAN_CTRLMODE_FD |
+                       CAN_CTRLMODE_3_SAMPLES | CAN_CTRLMODE_LISTENONLY,
+       .clock = {
+               .freq = PCAN_UFD_CRYSTAL_HZ,
+       },
+       .bittiming_const = &pcan_usb_x6_const,
+       .data_bittiming_const = &pcan_usb_x6_data_const,
+
+       /* size of device private data */
+       .sizeof_dev_private = sizeof(struct pcan_usb_fd_device),
+
+       /* timestamps usage */
+       .ts_used_bits = 32,
+       .ts_period = 1000000, /* calibration period in ts. */
+       .us_per_ts_scale = 1, /* us = (ts * scale) >> shift */
+       .us_per_ts_shift = 0,
+
+       /* give here messages in/out endpoints */
+       .ep_msg_in = PCAN_USBPRO_EP_MSGIN,
+       .ep_msg_out = {PCAN_USBPRO_EP_MSGOUT_0, PCAN_USBPRO_EP_MSGOUT_1},
+
+       /* size of rx/tx usb buffers */
+       .rx_buffer_size = PCAN_UFD_RX_BUFFER_SIZE,
+       .tx_buffer_size = PCAN_UFD_TX_BUFFER_SIZE,
+
+       /* device callbacks */
+       .intf_probe = pcan_usb_pro_probe,       /* same as PCAN-USB Pro */
+       .dev_init = pcan_usb_fd_init,
+
+       .dev_exit = pcan_usb_fd_exit,
+       .dev_free = pcan_usb_fd_free,
+       .dev_set_bus = pcan_usb_fd_set_bus,
+       .dev_set_bittiming = pcan_usb_fd_set_bittiming_slow,
+       .dev_set_data_bittiming = pcan_usb_fd_set_bittiming_fast,
+       .dev_decode_buf = pcan_usb_fd_decode_buf,
+       .dev_start = pcan_usb_fd_start,
+       .dev_stop = pcan_usb_fd_stop,
+       .dev_restart_async = pcan_usb_fd_restart_async,
+       .dev_encode_msg = pcan_usb_fd_encode_msg,
+
+       .do_get_berr_counter = pcan_usb_fd_get_berr_counter,
+};
index bda31f3..a0eee72 100644 (file)
@@ -400,12 +400,6 @@ static int tse_rx(struct altera_tse_private *priv, int limit)
 
                skb_put(skb, pktlength);
 
-               /* make cache consistent with receive packet buffer */
-               dma_sync_single_for_cpu(priv->device,
-                                       priv->rx_ring[entry].dma_addr,
-                                       priv->rx_ring[entry].len,
-                                       DMA_FROM_DEVICE);
-
                dma_unmap_single(priv->device, priv->rx_ring[entry].dma_addr,
                                 priv->rx_ring[entry].len, DMA_FROM_DEVICE);
 
@@ -469,7 +463,6 @@ static int tse_tx_complete(struct altera_tse_private *priv)
 
        if (unlikely(netif_queue_stopped(priv->dev) &&
                     tse_tx_avail(priv) > TSE_TX_THRESH(priv))) {
-               netif_tx_lock(priv->dev);
                if (netif_queue_stopped(priv->dev) &&
                    tse_tx_avail(priv) > TSE_TX_THRESH(priv)) {
                        if (netif_msg_tx_done(priv))
@@ -477,7 +470,6 @@ static int tse_tx_complete(struct altera_tse_private *priv)
                                           __func__);
                        netif_wake_queue(priv->dev);
                }
-               netif_tx_unlock(priv->dev);
        }
 
        spin_unlock(&priv->tx_lock);
@@ -592,10 +584,6 @@ static int tse_start_xmit(struct sk_buff *skb, struct net_device *dev)
        buffer->dma_addr = dma_addr;
        buffer->len = nopaged_len;
 
-       /* Push data out of the cache hierarchy into main memory */
-       dma_sync_single_for_device(priv->device, buffer->dma_addr,
-                                  buffer->len, DMA_TO_DEVICE);
-
        priv->dmaops->tx_buffer(priv, buffer);
 
        skb_tx_timestamp(skb);
@@ -819,6 +807,8 @@ static int init_phy(struct net_device *dev)
 
        if (!phydev) {
                netdev_err(dev, "Could not find the PHY\n");
+               if (fixed_link)
+                       of_phy_deregister_fixed_link(priv->device->of_node);
                return -ENODEV;
        }
 
@@ -1545,10 +1535,15 @@ err_free_netdev:
 static int altera_tse_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
+       struct altera_tse_private *priv = netdev_priv(ndev);
 
-       if (ndev->phydev)
+       if (ndev->phydev) {
                phy_disconnect(ndev->phydev);
 
+               if (of_phy_is_fixed_link(priv->device->of_node))
+                       of_phy_deregister_fixed_link(priv->device->of_node);
+       }
+
        platform_set_drvdata(pdev, NULL);
        altera_tse_mdio_destroy(ndev);
        unregister_netdev(ndev);
index 9de0788..4f76351 100644 (file)
@@ -829,7 +829,7 @@ static int xgbe_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
+#ifdef CONFIG_PM_SLEEP
 static int xgbe_suspend(struct device *dev)
 {
        struct net_device *netdev = dev_get_drvdata(dev);
@@ -874,7 +874,7 @@ static int xgbe_resume(struct device *dev)
 
        return ret;
 }
-#endif /* CONFIG_PM */
+#endif /* CONFIG_PM_SLEEP */
 
 #ifdef CONFIG_ACPI
 static const struct acpi_device_id xgbe_acpi_match[] = {
index 00c38bf..e078d8d 100644 (file)
@@ -1466,12 +1466,12 @@ static int nb8800_probe(struct platform_device *pdev)
 
        ret = nb8800_hw_init(dev);
        if (ret)
-               goto err_free_bus;
+               goto err_deregister_fixed_link;
 
        if (ops && ops->init) {
                ret = ops->init(dev);
                if (ret)
-                       goto err_free_bus;
+                       goto err_deregister_fixed_link;
        }
 
        dev->netdev_ops = &nb8800_netdev_ops;
@@ -1504,6 +1504,9 @@ static int nb8800_probe(struct platform_device *pdev)
 
 err_free_dma:
        nb8800_dma_free(dev);
+err_deregister_fixed_link:
+       if (of_phy_is_fixed_link(pdev->dev.of_node))
+               of_phy_deregister_fixed_link(pdev->dev.of_node);
 err_free_bus:
        of_node_put(priv->phy_node);
        mdiobus_unregister(bus);
@@ -1521,6 +1524,8 @@ static int nb8800_remove(struct platform_device *pdev)
        struct nb8800_priv *priv = netdev_priv(ndev);
 
        unregister_netdev(ndev);
+       if (of_phy_is_fixed_link(pdev->dev.of_node))
+               of_phy_deregister_fixed_link(pdev->dev.of_node);
        of_node_put(priv->phy_node);
 
        mdiobus_unregister(priv->mii_bus);
index c3354b9..25d1eb4 100644 (file)
@@ -1755,13 +1755,13 @@ static int bcm_sysport_probe(struct platform_device *pdev)
        if (priv->irq0 <= 0 || priv->irq1 <= 0) {
                dev_err(&pdev->dev, "invalid interrupts\n");
                ret = -EINVAL;
-               goto err;
+               goto err_free_netdev;
        }
 
        priv->base = devm_ioremap_resource(&pdev->dev, r);
        if (IS_ERR(priv->base)) {
                ret = PTR_ERR(priv->base);
-               goto err;
+               goto err_free_netdev;
        }
 
        priv->netdev = dev;
@@ -1779,7 +1779,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
                ret = of_phy_register_fixed_link(dn);
                if (ret) {
                        dev_err(&pdev->dev, "failed to register fixed PHY\n");
-                       goto err;
+                       goto err_free_netdev;
                }
 
                priv->phy_dn = dn;
@@ -1821,7 +1821,7 @@ static int bcm_sysport_probe(struct platform_device *pdev)
        ret = register_netdev(dev);
        if (ret) {
                dev_err(&pdev->dev, "failed to register net_device\n");
-               goto err;
+               goto err_deregister_fixed_link;
        }
 
        priv->rev = topctrl_readl(priv, REV_CNTL) & REV_MASK;
@@ -1832,7 +1832,11 @@ static int bcm_sysport_probe(struct platform_device *pdev)
                 priv->base, priv->irq0, priv->irq1, txq, rxq);
 
        return 0;
-err:
+
+err_deregister_fixed_link:
+       if (of_phy_is_fixed_link(dn))
+               of_phy_deregister_fixed_link(dn);
+err_free_netdev:
        free_netdev(dev);
        return ret;
 }
@@ -1840,11 +1844,14 @@ err:
 static int bcm_sysport_remove(struct platform_device *pdev)
 {
        struct net_device *dev = dev_get_drvdata(&pdev->dev);
+       struct device_node *dn = pdev->dev.of_node;
 
        /* Not much to do, ndo_close has been called
         * and we use managed allocations
         */
        unregister_netdev(dev);
+       if (of_phy_is_fixed_link(dn))
+               of_phy_deregister_fixed_link(dn);
        free_netdev(dev);
        dev_set_drvdata(&pdev->dev, NULL);
 
index 4464bc5..a4e60e5 100644 (file)
@@ -1172,6 +1172,7 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
                                          struct bcmgenet_tx_ring *ring)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
+       struct device *kdev = &priv->pdev->dev;
        struct enet_cb *tx_cb_ptr;
        struct netdev_queue *txq;
        unsigned int pkts_compl = 0;
@@ -1199,13 +1200,13 @@ static unsigned int __bcmgenet_tx_reclaim(struct net_device *dev,
                if (tx_cb_ptr->skb) {
                        pkts_compl++;
                        bytes_compl += GENET_CB(tx_cb_ptr->skb)->bytes_sent;
-                       dma_unmap_single(&dev->dev,
+                       dma_unmap_single(kdev,
                                         dma_unmap_addr(tx_cb_ptr, dma_addr),
                                         dma_unmap_len(tx_cb_ptr, dma_len),
                                         DMA_TO_DEVICE);
                        bcmgenet_free_cb(tx_cb_ptr);
                } else if (dma_unmap_addr(tx_cb_ptr, dma_addr)) {
-                       dma_unmap_page(&dev->dev,
+                       dma_unmap_page(kdev,
                                       dma_unmap_addr(tx_cb_ptr, dma_addr),
                                       dma_unmap_len(tx_cb_ptr, dma_len),
                                       DMA_TO_DEVICE);
@@ -1775,6 +1776,7 @@ static int bcmgenet_alloc_rx_buffers(struct bcmgenet_priv *priv,
 
 static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
 {
+       struct device *kdev = &priv->pdev->dev;
        struct enet_cb *cb;
        int i;
 
@@ -1782,7 +1784,7 @@ static void bcmgenet_free_rx_buffers(struct bcmgenet_priv *priv)
                cb = &priv->rx_cbs[i];
 
                if (dma_unmap_addr(cb, dma_addr)) {
-                       dma_unmap_single(&priv->dev->dev,
+                       dma_unmap_single(kdev,
                                         dma_unmap_addr(cb, dma_addr),
                                         priv->rx_buf_len, DMA_FROM_DEVICE);
                        dma_unmap_addr_set(cb, dma_addr, 0);
index 457c3bc..e876076 100644 (file)
@@ -542,8 +542,10 @@ static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv)
        /* Make sure we initialize MoCA PHYs with a link down */
        if (phy_mode == PHY_INTERFACE_MODE_MOCA) {
                phydev = of_phy_find_device(dn);
-               if (phydev)
+               if (phydev) {
                        phydev->link = 0;
+                       put_device(&phydev->mdio.dev);
+               }
        }
 
        return 0;
@@ -625,6 +627,7 @@ static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv)
 int bcmgenet_mii_init(struct net_device *dev)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
+       struct device_node *dn = priv->pdev->dev.of_node;
        int ret;
 
        ret = bcmgenet_mii_alloc(priv);
@@ -638,6 +641,8 @@ int bcmgenet_mii_init(struct net_device *dev)
        return 0;
 
 out:
+       if (of_phy_is_fixed_link(dn))
+               of_phy_deregister_fixed_link(dn);
        of_node_put(priv->phy_dn);
        mdiobus_unregister(priv->mii_bus);
        mdiobus_free(priv->mii_bus);
@@ -647,7 +652,10 @@ out:
 void bcmgenet_mii_exit(struct net_device *dev)
 {
        struct bcmgenet_priv *priv = netdev_priv(dev);
+       struct device_node *dn = priv->pdev->dev.of_node;
 
+       if (of_phy_is_fixed_link(dn))
+               of_phy_deregister_fixed_link(dn);
        of_node_put(priv->phy_dn);
        mdiobus_unregister(priv->mii_bus);
        mdiobus_free(priv->mii_bus);
index 533653b..ec09fce 100644 (file)
@@ -975,6 +975,7 @@ static inline void macb_init_rx_ring(struct macb *bp)
                addr += bp->rx_buffer_size;
        }
        bp->rx_ring[RX_RING_SIZE - 1].addr |= MACB_BIT(RX_WRAP);
+       bp->rx_tail = 0;
 }
 
 static int macb_rx(struct macb *bp, int budget)
@@ -1156,6 +1157,7 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                if (status & MACB_BIT(RXUBR)) {
                        ctrl = macb_readl(bp, NCR);
                        macb_writel(bp, NCR, ctrl & ~MACB_BIT(RE));
+                       wmb();
                        macb_writel(bp, NCR, ctrl | MACB_BIT(RE));
 
                        if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
@@ -1616,8 +1618,6 @@ static void macb_init_rings(struct macb *bp)
        bp->queues[0].tx_head = 0;
        bp->queues[0].tx_tail = 0;
        bp->queues[0].tx_ring[TX_RING_SIZE - 1].ctrl |= MACB_BIT(TX_WRAP);
-
-       bp->rx_tail = 0;
 }
 
 static void macb_reset_hw(struct macb *bp)
@@ -2770,6 +2770,7 @@ static irqreturn_t at91ether_interrupt(int irq, void *dev_id)
        if (intstatus & MACB_BIT(RXUBR)) {
                ctl = macb_readl(lp, NCR);
                macb_writel(lp, NCR, ctl & ~MACB_BIT(RE));
+               wmb();
                macb_writel(lp, NCR, ctl | MACB_BIT(RE));
        }
 
index df1573c..ecf3ccc 100644 (file)
@@ -168,6 +168,7 @@ CH_PCI_DEVICE_ID_TABLE_DEFINE_BEGIN
        CH_PCI_ID_TABLE_FENTRY(0x509a), /* Custom T520-CR */
        CH_PCI_ID_TABLE_FENTRY(0x509b), /* Custom T540-CR LOM */
        CH_PCI_ID_TABLE_FENTRY(0x509c), /* Custom T520-CR*/
+       CH_PCI_ID_TABLE_FENTRY(0x509d), /* Custom T540-CR*/
 
        /* T6 adapters:
         */
index c865135..5ea740b 100644 (file)
@@ -574,6 +574,8 @@ struct fec_enet_private {
        unsigned int reload_period;
        int pps_enable;
        unsigned int next_counter;
+
+       u64 ethtool_stats[0];
 };
 
 void fec_ptp_init(struct platform_device *pdev);
index 5aa9d4d..5f77caa 100644 (file)
@@ -2313,14 +2313,24 @@ static const struct fec_stat {
        { "IEEE_rx_octets_ok", IEEE_R_OCTETS_OK },
 };
 
-static void fec_enet_get_ethtool_stats(struct net_device *dev,
-       struct ethtool_stats *stats, u64 *data)
+static void fec_enet_update_ethtool_stats(struct net_device *dev)
 {
        struct fec_enet_private *fep = netdev_priv(dev);
        int i;
 
        for (i = 0; i < ARRAY_SIZE(fec_stats); i++)
-               data[i] = readl(fep->hwp + fec_stats[i].offset);
+               fep->ethtool_stats[i] = readl(fep->hwp + fec_stats[i].offset);
+}
+
+static void fec_enet_get_ethtool_stats(struct net_device *dev,
+                                      struct ethtool_stats *stats, u64 *data)
+{
+       struct fec_enet_private *fep = netdev_priv(dev);
+
+       if (netif_running(dev))
+               fec_enet_update_ethtool_stats(dev);
+
+       memcpy(data, fep->ethtool_stats, ARRAY_SIZE(fec_stats) * sizeof(u64));
 }
 
 static void fec_enet_get_strings(struct net_device *netdev,
@@ -2874,6 +2884,8 @@ fec_enet_close(struct net_device *ndev)
        if (fep->quirks & FEC_QUIRK_ERR006687)
                imx6q_cpuidle_fec_irqs_unused();
 
+       fec_enet_update_ethtool_stats(ndev);
+
        fec_enet_clk_enable(ndev, false);
        pinctrl_pm_select_sleep_state(&fep->pdev->dev);
        pm_runtime_mark_last_busy(&fep->pdev->dev);
@@ -3180,6 +3192,8 @@ static int fec_enet_init(struct net_device *ndev)
 
        fec_restart(ndev);
 
+       fec_enet_update_ethtool_stats(ndev);
+
        return 0;
 }
 
@@ -3278,7 +3292,8 @@ fec_probe(struct platform_device *pdev)
        fec_enet_get_queue_num(pdev, &num_tx_qs, &num_rx_qs);
 
        /* Init network device */
-       ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private),
+       ndev = alloc_etherdev_mqs(sizeof(struct fec_enet_private) +
+                                 ARRAY_SIZE(fec_stats) * sizeof(u64),
                                  num_tx_qs, num_rx_qs);
        if (!ndev)
                return -ENOMEM;
@@ -3475,6 +3490,8 @@ failed_regulator:
 failed_clk_ipg:
        fec_enet_clk_enable(ndev, false);
 failed_clk:
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
 failed_phy:
        of_node_put(phy_node);
 failed_ioremap:
@@ -3488,6 +3505,7 @@ fec_drv_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct fec_enet_private *fep = netdev_priv(ndev);
+       struct device_node *np = pdev->dev.of_node;
 
        cancel_work_sync(&fep->tx_timeout_work);
        fec_ptp_stop(pdev);
@@ -3495,6 +3513,8 @@ fec_drv_remove(struct platform_device *pdev)
        fec_enet_mii_remove(fep);
        if (fep->reg_phy)
                regulator_disable(fep->reg_phy);
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
        of_node_put(fep->phy_node);
        free_netdev(ndev);
 
index 53ef51e..71a5ded 100644 (file)
@@ -1107,6 +1107,9 @@ int memac_free(struct fman_mac *memac)
 {
        free_init_resources(memac);
 
+       if (memac->pcsphy)
+               put_device(&memac->pcsphy->mdio.dev);
+
        kfree(memac->memac_drv_param);
        kfree(memac);
 
index 8fe6b3e..736db9d 100644 (file)
@@ -892,6 +892,8 @@ static int mac_probe(struct platform_device *_of_dev)
                priv->fixed_link->duplex = phy->duplex;
                priv->fixed_link->pause = phy->pause;
                priv->fixed_link->asym_pause = phy->asym_pause;
+
+               put_device(&phy->mdio.dev);
        }
 
        err = mac_dev->init(mac_dev);
index dc120c1..4b86260 100644 (file)
@@ -980,7 +980,7 @@ static int fs_enet_probe(struct platform_device *ofdev)
                err = clk_prepare_enable(clk);
                if (err) {
                        ret = err;
-                       goto out_free_fpi;
+                       goto out_deregister_fixed_link;
                }
                fpi->clk_per = clk;
        }
@@ -1061,6 +1061,9 @@ out_put:
        of_node_put(fpi->phy_node);
        if (fpi->clk_per)
                clk_disable_unprepare(fpi->clk_per);
+out_deregister_fixed_link:
+       if (of_phy_is_fixed_link(ofdev->dev.of_node))
+               of_phy_deregister_fixed_link(ofdev->dev.of_node);
 out_free_fpi:
        kfree(fpi);
        return ret;
@@ -1079,6 +1082,8 @@ static int fs_enet_remove(struct platform_device *ofdev)
        of_node_put(fep->fpi->phy_node);
        if (fep->fpi->clk_per)
                clk_disable_unprepare(fep->fpi->clk_per);
+       if (of_phy_is_fixed_link(ofdev->dev.of_node))
+               of_phy_deregister_fixed_link(ofdev->dev.of_node);
        free_netdev(ndev);
        return 0;
 }
index 4b4f5bc..9061c2f 100644 (file)
@@ -1312,6 +1312,7 @@ static void gfar_init_addr_hash_table(struct gfar_private *priv)
  */
 static int gfar_probe(struct platform_device *ofdev)
 {
+       struct device_node *np = ofdev->dev.of_node;
        struct net_device *dev = NULL;
        struct gfar_private *priv = NULL;
        int err = 0, i;
@@ -1462,6 +1463,8 @@ static int gfar_probe(struct platform_device *ofdev)
        return 0;
 
 register_fail:
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
        unmap_group_regs(priv);
        gfar_free_rx_queues(priv);
        gfar_free_tx_queues(priv);
@@ -1474,11 +1477,16 @@ register_fail:
 static int gfar_remove(struct platform_device *ofdev)
 {
        struct gfar_private *priv = platform_get_drvdata(ofdev);
+       struct device_node *np = ofdev->dev.of_node;
 
        of_node_put(priv->phy_node);
        of_node_put(priv->tbi_node);
 
        unregister_netdev(priv->ndev);
+
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
+
        unmap_group_regs(priv);
        gfar_free_rx_queues(priv);
        gfar_free_tx_queues(priv);
index 186ef8f..f76d332 100644 (file)
@@ -3868,9 +3868,8 @@ static int ucc_geth_probe(struct platform_device* ofdev)
        dev = alloc_etherdev(sizeof(*ugeth));
 
        if (dev == NULL) {
-               of_node_put(ug_info->tbi_node);
-               of_node_put(ug_info->phy_node);
-               return -ENOMEM;
+               err = -ENOMEM;
+               goto err_deregister_fixed_link;
        }
 
        ugeth = netdev_priv(dev);
@@ -3907,10 +3906,7 @@ static int ucc_geth_probe(struct platform_device* ofdev)
                if (netif_msg_probe(ugeth))
                        pr_err("%s: Cannot register net device, aborting\n",
                               dev->name);
-               free_netdev(dev);
-               of_node_put(ug_info->tbi_node);
-               of_node_put(ug_info->phy_node);
-               return err;
+               goto err_free_netdev;
        }
 
        mac_addr = of_get_mac_address(np);
@@ -3923,16 +3919,29 @@ static int ucc_geth_probe(struct platform_device* ofdev)
        ugeth->node = np;
 
        return 0;
+
+err_free_netdev:
+       free_netdev(dev);
+err_deregister_fixed_link:
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
+       of_node_put(ug_info->tbi_node);
+       of_node_put(ug_info->phy_node);
+
+       return err;
 }
 
 static int ucc_geth_remove(struct platform_device* ofdev)
 {
        struct net_device *dev = platform_get_drvdata(ofdev);
        struct ucc_geth_private *ugeth = netdev_priv(dev);
+       struct device_node *np = ofdev->dev.of_node;
 
        unregister_netdev(dev);
        free_netdev(dev);
        ucc_geth_memclean(ugeth);
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
        of_node_put(ugeth->ug_info->tbi_node);
        of_node_put(ugeth->ug_info->phy_node);
 
index edc9a6a..9affd7c 100644 (file)
@@ -4931,11 +4931,15 @@ static int igb_tso(struct igb_ring *tx_ring,
 
        /* initialize outer IP header fields */
        if (ip.v4->version == 4) {
+               unsigned char *csum_start = skb_checksum_start(skb);
+               unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4);
+
                /* IP header will have to cancel out any data that
                 * is not a part of the outer IP header
                 */
-               ip.v4->check = csum_fold(csum_add(lco_csum(skb),
-                                                 csum_unfold(l4.tcp->check)));
+               ip.v4->check = csum_fold(csum_partial(trans_start,
+                                                     csum_start - trans_start,
+                                                     0));
                type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
 
                ip.v4->tot_len = 0;
index 12bb877..7dff7f6 100644 (file)
@@ -1965,11 +1965,15 @@ static int igbvf_tso(struct igbvf_ring *tx_ring,
 
        /* initialize outer IP header fields */
        if (ip.v4->version == 4) {
+               unsigned char *csum_start = skb_checksum_start(skb);
+               unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4);
+
                /* IP header will have to cancel out any data that
                 * is not a part of the outer IP header
                 */
-               ip.v4->check = csum_fold(csum_add(lco_csum(skb),
-                                                 csum_unfold(l4.tcp->check)));
+               ip.v4->check = csum_fold(csum_partial(trans_start,
+                                                     csum_start - trans_start,
+                                                     0));
                type_tucmd |= E1000_ADVTXD_TUCMD_IPV4;
 
                ip.v4->tot_len = 0;
index bd93d82..fee1f29 100644 (file)
@@ -7277,11 +7277,15 @@ static int ixgbe_tso(struct ixgbe_ring *tx_ring,
 
        /* initialize outer IP header fields */
        if (ip.v4->version == 4) {
+               unsigned char *csum_start = skb_checksum_start(skb);
+               unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4);
+
                /* IP header will have to cancel out any data that
                 * is not a part of the outer IP header
                 */
-               ip.v4->check = csum_fold(csum_add(lco_csum(skb),
-                                                 csum_unfold(l4.tcp->check)));
+               ip.v4->check = csum_fold(csum_partial(trans_start,
+                                                     csum_start - trans_start,
+                                                     0));
                type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
 
                ip.v4->tot_len = 0;
index 7eaac32..cbf70fe 100644 (file)
@@ -3329,11 +3329,15 @@ static int ixgbevf_tso(struct ixgbevf_ring *tx_ring,
 
        /* initialize outer IP header fields */
        if (ip.v4->version == 4) {
+               unsigned char *csum_start = skb_checksum_start(skb);
+               unsigned char *trans_start = ip.hdr + (ip.v4->ihl * 4);
+
                /* IP header will have to cancel out any data that
                 * is not a part of the outer IP header
                 */
-               ip.v4->check = csum_fold(csum_add(lco_csum(skb),
-                                                 csum_unfold(l4.tcp->check)));
+               ip.v4->check = csum_fold(csum_partial(trans_start,
+                                                     csum_start - trans_start,
+                                                     0));
                type_tucmd |= IXGBE_ADVTXD_TUCMD_IPV4;
 
                ip.v4->tot_len = 0;
index 0c0a45a..707bc46 100644 (file)
@@ -4191,6 +4191,8 @@ err_clk:
        clk_disable_unprepare(pp->clk);
 err_put_phy_node:
        of_node_put(phy_node);
+       if (of_phy_is_fixed_link(dn))
+               of_phy_deregister_fixed_link(dn);
 err_free_irq:
        irq_dispose_mapping(dev->irq);
 err_free_netdev:
@@ -4202,6 +4204,7 @@ err_free_netdev:
 static int mvneta_remove(struct platform_device *pdev)
 {
        struct net_device  *dev = platform_get_drvdata(pdev);
+       struct device_node *dn = pdev->dev.of_node;
        struct mvneta_port *pp = netdev_priv(dev);
 
        unregister_netdev(dev);
@@ -4209,6 +4212,8 @@ static int mvneta_remove(struct platform_device *pdev)
        clk_disable_unprepare(pp->clk);
        free_percpu(pp->ports);
        free_percpu(pp->stats);
+       if (of_phy_is_fixed_link(dn))
+               of_phy_deregister_fixed_link(dn);
        irq_dispose_mapping(dev->irq);
        of_node_put(pp->phy_node);
        free_netdev(dev);
index 4a62ffd..86a89cb 100644 (file)
@@ -318,6 +318,8 @@ static int mtk_phy_connect(struct net_device *dev)
        return 0;
 
 err_phy:
+       if (of_phy_is_fixed_link(mac->of_node))
+               of_phy_deregister_fixed_link(mac->of_node);
        of_node_put(np);
        dev_err(eth->dev, "%s: invalid phy\n", __func__);
        return -EINVAL;
@@ -1923,6 +1925,8 @@ static void mtk_uninit(struct net_device *dev)
        struct mtk_eth *eth = mac->hw;
 
        phy_disconnect(dev->phydev);
+       if (of_phy_is_fixed_link(mac->of_node))
+               of_phy_deregister_fixed_link(mac->of_node);
        mtk_irq_disable(eth, MTK_QDMA_INT_MASK, ~0);
        mtk_irq_disable(eth, MTK_PDMA_INT_MASK, ~0);
 }
index a60f635..fb8bb02 100644 (file)
@@ -2079,13 +2079,6 @@ err:
        return -ENOMEM;
 }
 
-static void mlx4_en_shutdown(struct net_device *dev)
-{
-       rtnl_lock();
-       netif_device_detach(dev);
-       mlx4_en_close(dev);
-       rtnl_unlock();
-}
 
 static int mlx4_en_copy_priv(struct mlx4_en_priv *dst,
                             struct mlx4_en_priv *src,
@@ -2162,8 +2155,6 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
 {
        struct mlx4_en_priv *priv = netdev_priv(dev);
        struct mlx4_en_dev *mdev = priv->mdev;
-       bool shutdown = mdev->dev->persist->interface_state &
-                                           MLX4_INTERFACE_STATE_SHUTDOWN;
 
        en_dbg(DRV, priv, "Destroying netdev on port:%d\n", priv->port);
 
@@ -2171,10 +2162,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
        if (priv->registered) {
                devlink_port_type_clear(mlx4_get_devlink_port(mdev->dev,
                                                              priv->port));
-               if (shutdown)
-                       mlx4_en_shutdown(dev);
-               else
-                       unregister_netdev(dev);
+               unregister_netdev(dev);
        }
 
        if (priv->allocated)
@@ -2203,8 +2191,7 @@ void mlx4_en_destroy_netdev(struct net_device *dev)
        kfree(priv->tx_ring);
        kfree(priv->tx_cq);
 
-       if (!shutdown)
-               free_netdev(dev);
+       free_netdev(dev);
 }
 
 static int mlx4_en_change_mtu(struct net_device *dev, int new_mtu)
index 6f4e67b..75d07fa 100644 (file)
@@ -4147,11 +4147,8 @@ static void mlx4_shutdown(struct pci_dev *pdev)
 
        mlx4_info(persist->dev, "mlx4_shutdown was called\n");
        mutex_lock(&persist->interface_state_mutex);
-       if (persist->interface_state & MLX4_INTERFACE_STATE_UP) {
-               /* Notify mlx4 clients that the kernel is being shut down */
-               persist->interface_state |= MLX4_INTERFACE_STATE_SHUTDOWN;
+       if (persist->interface_state & MLX4_INTERFACE_STATE_UP)
                mlx4_unload_one(pdev);
-       }
        mutex_unlock(&persist->interface_state_mutex);
 }
 
index 94b891c..1a670b6 100644 (file)
@@ -1457,7 +1457,12 @@ EXPORT_SYMBOL_GPL(mlx4_multicast_detach);
 int mlx4_flow_steer_promisc_add(struct mlx4_dev *dev, u8 port,
                                u32 qpn, enum mlx4_net_trans_promisc_mode mode)
 {
-       struct mlx4_net_trans_rule rule;
+       struct mlx4_net_trans_rule rule = {
+               .queue_mode = MLX4_NET_TRANS_Q_FIFO,
+               .exclusive = 0,
+               .allow_loopback = 1,
+       };
+
        u64 *regid_p;
 
        switch (mode) {
index da4e90d..99a14df 100644 (file)
@@ -212,6 +212,7 @@ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt)
 
                phy_np = of_parse_phandle(np, "phy-handle", 0);
                adpt->phydev = of_phy_find_device(phy_np);
+               of_node_put(phy_np);
        }
 
        if (!adpt->phydev) {
index 4fede4b..57b35ae 100644 (file)
@@ -711,6 +711,8 @@ static int emac_probe(struct platform_device *pdev)
 err_undo_napi:
        netif_napi_del(&adpt->rx_q.napi);
 err_undo_mdiobus:
+       if (!has_acpi_companion(&pdev->dev))
+               put_device(&adpt->phydev->mdio.dev);
        mdiobus_unregister(adpt->mii_bus);
 err_undo_clocks:
        emac_clks_teardown(adpt);
@@ -730,6 +732,8 @@ static int emac_remove(struct platform_device *pdev)
 
        emac_clks_teardown(adpt);
 
+       if (!has_acpi_companion(&pdev->dev))
+               put_device(&adpt->phydev->mdio.dev);
        mdiobus_unregister(adpt->mii_bus);
        free_netdev(netdev);
 
index 630536b..d6a2178 100644 (file)
@@ -1008,20 +1008,18 @@ static int ravb_phy_init(struct net_device *ndev)
        of_node_put(pn);
        if (!phydev) {
                netdev_err(ndev, "failed to connect PHY\n");
-               return -ENOENT;
+               err = -ENOENT;
+               goto err_deregister_fixed_link;
        }
 
        /* This driver only support 10/100Mbit speeds on Gen3
         * at this time.
         */
        if (priv->chip_id == RCAR_GEN3) {
-               int err;
-
                err = phy_set_max_speed(phydev, SPEED_100);
                if (err) {
                        netdev_err(ndev, "failed to limit PHY to 100Mbit/s\n");
-                       phy_disconnect(phydev);
-                       return err;
+                       goto err_phy_disconnect;
                }
 
                netdev_info(ndev, "limited PHY to 100Mbit/s\n");
@@ -1033,6 +1031,14 @@ static int ravb_phy_init(struct net_device *ndev)
        phy_attached_info(phydev);
 
        return 0;
+
+err_phy_disconnect:
+       phy_disconnect(phydev);
+err_deregister_fixed_link:
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
+
+       return err;
 }
 
 /* PHY control start function */
@@ -1634,6 +1640,7 @@ static void ravb_set_rx_mode(struct net_device *ndev)
 /* Device close function for Ethernet AVB */
 static int ravb_close(struct net_device *ndev)
 {
+       struct device_node *np = ndev->dev.parent->of_node;
        struct ravb_private *priv = netdev_priv(ndev);
        struct ravb_tstamp_skb *ts_skb, *ts_skb2;
 
@@ -1663,6 +1670,8 @@ static int ravb_close(struct net_device *ndev)
        if (ndev->phydev) {
                phy_stop(ndev->phydev);
                phy_disconnect(ndev->phydev);
+               if (of_phy_is_fixed_link(np))
+                       of_phy_deregister_fixed_link(np);
        }
 
        if (priv->chip_id != RCAR_GEN2) {
index 05b0dc5..1a92de7 100644 (file)
@@ -518,7 +518,7 @@ static struct sh_eth_cpu_data r7s72100_data = {
 
        .ecsr_value     = ECSR_ICD,
        .ecsipr_value   = ECSIPR_ICDIP,
-       .eesipr_value   = 0xff7f009f,
+       .eesipr_value   = 0xe77f009f,
 
        .tx_check       = EESR_TC1 | EESR_FTC,
        .eesr_err_check = EESR_TWB1 | EESR_TWB | EESR_TABT | EESR_RABT |
index b1e5f24..e6e6c2f 100644 (file)
@@ -50,10 +50,23 @@ static int dwmac_generic_probe(struct platform_device *pdev)
        if (plat_dat->init) {
                ret = plat_dat->init(pdev, plat_dat->bsp_priv);
                if (ret)
-                       return ret;
+                       goto err_remove_config_dt;
        }
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               goto err_exit;
+
+       return 0;
+
+err_exit:
+       if (plat_dat->exit)
+               plat_dat->exit(pdev, plat_dat->bsp_priv);
+err_remove_config_dt:
+       if (pdev->dev.of_node)
+               stmmac_remove_config_dt(pdev, plat_dat);
+
+       return ret;
 }
 
 static const struct of_device_id dwmac_generic_match[] = {
index 36d3355..866444b 100644 (file)
@@ -271,15 +271,17 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
                return PTR_ERR(plat_dat);
 
        gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
-       if (!gmac)
-               return -ENOMEM;
+       if (!gmac) {
+               err = -ENOMEM;
+               goto err_remove_config_dt;
+       }
 
        gmac->pdev = pdev;
 
        err = ipq806x_gmac_of_parse(gmac);
        if (err) {
                dev_err(dev, "device tree parsing error\n");
-               return err;
+               goto err_remove_config_dt;
        }
 
        regmap_write(gmac->qsgmii_csr, QSGMII_PCS_CAL_LCKDT_CTL,
@@ -300,7 +302,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
        default:
                dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
                        phy_modes(gmac->phy_mode));
-               return -EINVAL;
+               err = -EINVAL;
+               goto err_remove_config_dt;
        }
        regmap_write(gmac->nss_common, NSS_COMMON_GMAC_CTL(gmac->id), val);
 
@@ -319,7 +322,8 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
        default:
                dev_err(&pdev->dev, "Unsupported PHY mode: \"%s\"\n",
                        phy_modes(gmac->phy_mode));
-               return -EINVAL;
+               err = -EINVAL;
+               goto err_remove_config_dt;
        }
        regmap_write(gmac->nss_common, NSS_COMMON_CLK_SRC_CTRL, val);
 
@@ -346,7 +350,16 @@ static int ipq806x_gmac_probe(struct platform_device *pdev)
        plat_dat->bsp_priv = gmac;
        plat_dat->fix_mac_speed = ipq806x_gmac_fix_mac_speed;
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       err = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (err)
+               goto err_remove_config_dt;
+
+       return 0;
+
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
+
+       return err;
 }
 
 static const struct of_device_id ipq806x_gmac_dwmac_match[] = {
index 78e9d18..3d3f43d 100644 (file)
@@ -46,7 +46,8 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev)
        reg = syscon_regmap_lookup_by_compatible("nxp,lpc1850-creg");
        if (IS_ERR(reg)) {
                dev_err(&pdev->dev, "syscon lookup failed\n");
-               return PTR_ERR(reg);
+               ret = PTR_ERR(reg);
+               goto err_remove_config_dt;
        }
 
        if (plat_dat->interface == PHY_INTERFACE_MODE_MII) {
@@ -55,13 +56,23 @@ static int lpc18xx_dwmac_probe(struct platform_device *pdev)
                ethmode = LPC18XX_CREG_CREG6_ETHMODE_RMII;
        } else {
                dev_err(&pdev->dev, "Only MII and RMII mode supported\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_remove_config_dt;
        }
 
        regmap_update_bits(reg, LPC18XX_CREG_CREG6,
                           LPC18XX_CREG_CREG6_ETHMODE_MASK, ethmode);
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               goto err_remove_config_dt;
+
+       return 0;
+
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
+
+       return ret;
 }
 
 static const struct of_device_id lpc18xx_dwmac_match[] = {
index 309d995..7fdd176 100644 (file)
@@ -64,18 +64,31 @@ static int meson6_dwmac_probe(struct platform_device *pdev)
                return PTR_ERR(plat_dat);
 
        dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
-       if (!dwmac)
-               return -ENOMEM;
+       if (!dwmac) {
+               ret = -ENOMEM;
+               goto err_remove_config_dt;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        dwmac->reg = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(dwmac->reg))
-               return PTR_ERR(dwmac->reg);
+       if (IS_ERR(dwmac->reg)) {
+               ret = PTR_ERR(dwmac->reg);
+               goto err_remove_config_dt;
+       }
 
        plat_dat->bsp_priv = dwmac;
        plat_dat->fix_mac_speed = meson6_dwmac_fix_mac_speed;
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               goto err_remove_config_dt;
+
+       return 0;
+
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
+
+       return ret;
 }
 
 static const struct of_device_id meson6_dwmac_match[] = {
index 250e4ce..ffaed1f 100644 (file)
@@ -264,32 +264,48 @@ static int meson8b_dwmac_probe(struct platform_device *pdev)
                return PTR_ERR(plat_dat);
 
        dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
-       if (!dwmac)
-               return -ENOMEM;
+       if (!dwmac) {
+               ret = -ENOMEM;
+               goto err_remove_config_dt;
+       }
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 1);
        dwmac->regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(dwmac->regs))
-               return PTR_ERR(dwmac->regs);
+       if (IS_ERR(dwmac->regs)) {
+               ret = PTR_ERR(dwmac->regs);
+               goto err_remove_config_dt;
+       }
 
        dwmac->pdev = pdev;
        dwmac->phy_mode = of_get_phy_mode(pdev->dev.of_node);
        if (dwmac->phy_mode < 0) {
                dev_err(&pdev->dev, "missing phy-mode property\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_remove_config_dt;
        }
 
        ret = meson8b_init_clk(dwmac);
        if (ret)
-               return ret;
+               goto err_remove_config_dt;
 
        ret = meson8b_init_prg_eth(dwmac);
        if (ret)
-               return ret;
+               goto err_remove_config_dt;
 
        plat_dat->bsp_priv = dwmac;
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               goto err_clk_disable;
+
+       return 0;
+
+err_clk_disable:
+       clk_disable_unprepare(dwmac->m25_div_clk);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
+
+       return ret;
 }
 
 static int meson8b_dwmac_remove(struct platform_device *pdev)
index 3740a44..d80c88b 100644 (file)
@@ -981,14 +981,27 @@ static int rk_gmac_probe(struct platform_device *pdev)
        plat_dat->resume = rk_gmac_resume;
 
        plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
-       if (IS_ERR(plat_dat->bsp_priv))
-               return PTR_ERR(plat_dat->bsp_priv);
+       if (IS_ERR(plat_dat->bsp_priv)) {
+               ret = PTR_ERR(plat_dat->bsp_priv);
+               goto err_remove_config_dt;
+       }
 
        ret = rk_gmac_init(pdev, plat_dat->bsp_priv);
        if (ret)
-               return ret;
+               goto err_remove_config_dt;
+
+       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               goto err_gmac_exit;
+
+       return 0;
+
+err_gmac_exit:
+       rk_gmac_exit(pdev, plat_dat->bsp_priv);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       return ret;
 }
 
 static const struct of_device_id rk_gmac_dwmac_match[] = {
index bec6963..0c420e9 100644 (file)
@@ -304,6 +304,8 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
        struct device           *dev = &pdev->dev;
        int                     ret;
        struct socfpga_dwmac    *dwmac;
+       struct net_device       *ndev;
+       struct stmmac_priv      *stpriv;
 
        ret = stmmac_get_platform_resources(pdev, &stmmac_res);
        if (ret)
@@ -314,32 +316,43 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
                return PTR_ERR(plat_dat);
 
        dwmac = devm_kzalloc(dev, sizeof(*dwmac), GFP_KERNEL);
-       if (!dwmac)
-               return -ENOMEM;
+       if (!dwmac) {
+               ret = -ENOMEM;
+               goto err_remove_config_dt;
+       }
 
        ret = socfpga_dwmac_parse_data(dwmac, dev);
        if (ret) {
                dev_err(dev, "Unable to parse OF data\n");
-               return ret;
+               goto err_remove_config_dt;
        }
 
        plat_dat->bsp_priv = dwmac;
        plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
 
        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               goto err_remove_config_dt;
 
-       if (!ret) {
-               struct net_device *ndev = platform_get_drvdata(pdev);
-               struct stmmac_priv *stpriv = netdev_priv(ndev);
+       ndev = platform_get_drvdata(pdev);
+       stpriv = netdev_priv(ndev);
 
-               /* The socfpga driver needs to control the stmmac reset to
-                * set the phy mode. Create a copy of the core reset handel
-                * so it can be used by the driver later.
-                */
-               dwmac->stmmac_rst = stpriv->stmmac_rst;
+       /* The socfpga driver needs to control the stmmac reset to set the phy
+        * mode. Create a copy of the core reset handle so it can be used by
+        * the driver later.
+        */
+       dwmac->stmmac_rst = stpriv->stmmac_rst;
 
-               ret = socfpga_dwmac_set_phy_mode(dwmac);
-       }
+       ret = socfpga_dwmac_set_phy_mode(dwmac);
+       if (ret)
+               goto err_dvr_remove;
+
+       return 0;
+
+err_dvr_remove:
+       stmmac_dvr_remove(&pdev->dev);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
        return ret;
 }
index 58c05ac..060b98c 100644 (file)
@@ -345,13 +345,15 @@ static int sti_dwmac_probe(struct platform_device *pdev)
                return PTR_ERR(plat_dat);
 
        dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
-       if (!dwmac)
-               return -ENOMEM;
+       if (!dwmac) {
+               ret = -ENOMEM;
+               goto err_remove_config_dt;
+       }
 
        ret = sti_dwmac_parse_data(dwmac, pdev);
        if (ret) {
                dev_err(&pdev->dev, "Unable to parse OF data\n");
-               return ret;
+               goto err_remove_config_dt;
        }
 
        dwmac->fix_retime_src = data->fix_retime_src;
@@ -363,9 +365,20 @@ static int sti_dwmac_probe(struct platform_device *pdev)
 
        ret = sti_dwmac_init(pdev, plat_dat->bsp_priv);
        if (ret)
-               return ret;
+               goto err_remove_config_dt;
+
+       ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       if (ret)
+               goto err_dwmac_exit;
+
+       return 0;
+
+err_dwmac_exit:
+       sti_dwmac_exit(pdev, plat_dat->bsp_priv);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
-       return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
+       return ret;
 }
 
 static const struct sti_dwmac_of_data stih4xx_dwmac_data = {
index e5a926b..61cb248 100644 (file)
@@ -107,24 +107,33 @@ static int stm32_dwmac_probe(struct platform_device *pdev)
                return PTR_ERR(plat_dat);
 
        dwmac = devm_kzalloc(&pdev->dev, sizeof(*dwmac), GFP_KERNEL);
-       if (!dwmac)
-               return -ENOMEM;
+       if (!dwmac) {
+               ret = -ENOMEM;
+               goto err_remove_config_dt;
+       }
 
        ret = stm32_dwmac_parse_data(dwmac, &pdev->dev);
        if (ret) {
                dev_err(&pdev->dev, "Unable to parse OF data\n");
-               return ret;
+               goto err_remove_config_dt;
        }
 
        plat_dat->bsp_priv = dwmac;
 
        ret = stm32_dwmac_init(plat_dat);
        if (ret)
-               return ret;
+               goto err_remove_config_dt;
 
        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
        if (ret)
-               stm32_dwmac_clk_disable(dwmac);
+               goto err_clk_disable;
+
+       return 0;
+
+err_clk_disable:
+       stm32_dwmac_clk_disable(dwmac);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
        return ret;
 }
index adff463..d07520f 100644 (file)
@@ -120,22 +120,27 @@ static int sun7i_gmac_probe(struct platform_device *pdev)
                return PTR_ERR(plat_dat);
 
        gmac = devm_kzalloc(dev, sizeof(*gmac), GFP_KERNEL);
-       if (!gmac)
-               return -ENOMEM;
+       if (!gmac) {
+               ret = -ENOMEM;
+               goto err_remove_config_dt;
+       }
 
        gmac->interface = of_get_phy_mode(dev->of_node);
 
        gmac->tx_clk = devm_clk_get(dev, "allwinner_gmac_tx");
        if (IS_ERR(gmac->tx_clk)) {
                dev_err(dev, "could not get tx clock\n");
-               return PTR_ERR(gmac->tx_clk);
+               ret = PTR_ERR(gmac->tx_clk);
+               goto err_remove_config_dt;
        }
 
        /* Optional regulator for PHY */
        gmac->regulator = devm_regulator_get_optional(dev, "phy");
        if (IS_ERR(gmac->regulator)) {
-               if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER)
-                       return -EPROBE_DEFER;
+               if (PTR_ERR(gmac->regulator) == -EPROBE_DEFER) {
+                       ret = -EPROBE_DEFER;
+                       goto err_remove_config_dt;
+               }
                dev_info(dev, "no regulator found\n");
                gmac->regulator = NULL;
        }
@@ -151,11 +156,18 @@ static int sun7i_gmac_probe(struct platform_device *pdev)
 
        ret = sun7i_gmac_init(pdev, plat_dat->bsp_priv);
        if (ret)
-               return ret;
+               goto err_remove_config_dt;
 
        ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
        if (ret)
-               sun7i_gmac_exit(pdev, plat_dat->bsp_priv);
+               goto err_gmac_exit;
+
+       return 0;
+
+err_gmac_exit:
+       sun7i_gmac_exit(pdev, plat_dat->bsp_priv);
+err_remove_config_dt:
+       stmmac_remove_config_dt(pdev, plat_dat);
 
        return ret;
 }
index 1f9ec02..caf069a 100644 (file)
@@ -3416,7 +3416,6 @@ int stmmac_dvr_remove(struct device *dev)
        stmmac_set_mac(priv->ioaddr, false);
        netif_carrier_off(ndev);
        unregister_netdev(ndev);
-       of_node_put(priv->plat->phy_node);
        if (priv->stmmac_rst)
                reset_control_assert(priv->stmmac_rst);
        clk_disable_unprepare(priv->pclk);
index 0a0d6a8..a840818 100644 (file)
@@ -200,7 +200,6 @@ static int stmmac_dt_phy(struct plat_stmmacenet_data *plat,
 /**
  * stmmac_probe_config_dt - parse device-tree driver parameters
  * @pdev: platform_device structure
- * @plat: driver data platform structure
  * @mac: MAC address to use
  * Description:
  * this function is to read the driver parameters from device-tree and
@@ -306,7 +305,7 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
                dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg),
                                       GFP_KERNEL);
                if (!dma_cfg) {
-                       of_node_put(plat->phy_node);
+                       stmmac_remove_config_dt(pdev, plat);
                        return ERR_PTR(-ENOMEM);
                }
                plat->dma_cfg = dma_cfg;
@@ -329,14 +328,37 @@ stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 
        return plat;
 }
+
+/**
+ * stmmac_remove_config_dt - undo the effects of stmmac_probe_config_dt()
+ * @pdev: platform_device structure
+ * @plat: driver data platform structure
+ *
+ * Release resources claimed by stmmac_probe_config_dt().
+ */
+void stmmac_remove_config_dt(struct platform_device *pdev,
+                            struct plat_stmmacenet_data *plat)
+{
+       struct device_node *np = pdev->dev.of_node;
+
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
+       of_node_put(plat->phy_node);
+}
 #else
 struct plat_stmmacenet_data *
 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac)
 {
        return ERR_PTR(-ENOSYS);
 }
+
+void stmmac_remove_config_dt(struct platform_device *pdev,
+                            struct plat_stmmacenet_data *plat)
+{
+}
 #endif /* CONFIG_OF */
 EXPORT_SYMBOL_GPL(stmmac_probe_config_dt);
+EXPORT_SYMBOL_GPL(stmmac_remove_config_dt);
 
 int stmmac_get_platform_resources(struct platform_device *pdev,
                                  struct stmmac_resources *stmmac_res)
@@ -392,10 +414,13 @@ int stmmac_pltfr_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct stmmac_priv *priv = netdev_priv(ndev);
+       struct plat_stmmacenet_data *plat = priv->plat;
        int ret = stmmac_dvr_remove(&pdev->dev);
 
-       if (priv->plat->exit)
-               priv->plat->exit(pdev, priv->plat->bsp_priv);
+       if (plat->exit)
+               plat->exit(pdev, plat->bsp_priv);
+
+       stmmac_remove_config_dt(pdev, plat);
 
        return ret;
 }
index 64e147f..b72eb0d 100644 (file)
@@ -23,6 +23,8 @@
 
 struct plat_stmmacenet_data *
 stmmac_probe_config_dt(struct platform_device *pdev, const char **mac);
+void stmmac_remove_config_dt(struct platform_device *pdev,
+                            struct plat_stmmacenet_data *plat);
 
 int stmmac_get_platform_resources(struct platform_device *pdev,
                                  struct stmmac_resources *stmmac_res);
index 4ba2421..97d64bf 100644 (file)
@@ -2881,7 +2881,7 @@ static int dwceqos_probe(struct platform_device *pdev)
        ret = of_get_phy_mode(lp->pdev->dev.of_node);
        if (ret < 0) {
                dev_err(&lp->pdev->dev, "error in getting phy i/f\n");
-               goto err_out_clk_dis_phy;
+               goto err_out_deregister_fixed_link;
        }
 
        lp->phy_interface = ret;
@@ -2889,14 +2889,14 @@ static int dwceqos_probe(struct platform_device *pdev)
        ret = dwceqos_mii_init(lp);
        if (ret) {
                dev_err(&lp->pdev->dev, "error in dwceqos_mii_init\n");
-               goto err_out_clk_dis_phy;
+               goto err_out_deregister_fixed_link;
        }
 
        ret = dwceqos_mii_probe(ndev);
        if (ret != 0) {
                netdev_err(ndev, "mii_probe fail.\n");
                ret = -ENXIO;
-               goto err_out_clk_dis_phy;
+               goto err_out_deregister_fixed_link;
        }
 
        dwceqos_set_umac_addr(lp, lp->ndev->dev_addr, 0);
@@ -2914,7 +2914,7 @@ static int dwceqos_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(&lp->pdev->dev, "Unable to retrieve DT, error %d\n",
                        ret);
-               goto err_out_clk_dis_phy;
+               goto err_out_deregister_fixed_link;
        }
        dev_info(&lp->pdev->dev, "pdev->id %d, baseaddr 0x%08lx, irq %d\n",
                 pdev->id, ndev->base_addr, ndev->irq);
@@ -2924,7 +2924,7 @@ static int dwceqos_probe(struct platform_device *pdev)
        if (ret) {
                dev_err(&lp->pdev->dev, "Unable to request IRQ %d, error %d\n",
                        ndev->irq, ret);
-               goto err_out_clk_dis_phy;
+               goto err_out_deregister_fixed_link;
        }
 
        if (netif_msg_probe(lp))
@@ -2935,11 +2935,14 @@ static int dwceqos_probe(struct platform_device *pdev)
        ret = register_netdev(ndev);
        if (ret) {
                dev_err(&pdev->dev, "Cannot register net device, aborting.\n");
-                       goto err_out_clk_dis_phy;
+               goto err_out_deregister_fixed_link;
        }
 
        return 0;
 
+err_out_deregister_fixed_link:
+       if (of_phy_is_fixed_link(pdev->dev.of_node))
+               of_phy_deregister_fixed_link(pdev->dev.of_node);
 err_out_clk_dis_phy:
        clk_disable_unprepare(lp->phy_ref_clk);
 err_out_clk_dis_aper:
@@ -2959,8 +2962,11 @@ static int dwceqos_remove(struct platform_device *pdev)
        if (ndev) {
                lp = netdev_priv(ndev);
 
-               if (ndev->phydev)
+               if (ndev->phydev) {
                        phy_disconnect(ndev->phydev);
+                       if (of_phy_is_fixed_link(pdev->dev.of_node))
+                               of_phy_deregister_fixed_link(pdev->dev.of_node);
+               }
                mdiobus_unregister(lp->mii_bus);
                mdiobus_free(lp->mii_bus);
 
index 58947aa..b9087b8 100644 (file)
@@ -2459,20 +2459,8 @@ static void cpsw_remove_dt(struct platform_device *pdev)
                if (strcmp(slave_node->name, "slave"))
                        continue;
 
-               if (of_phy_is_fixed_link(slave_node)) {
-                       struct phy_device *phydev;
-
-                       phydev = of_phy_find_device(slave_node);
-                       if (phydev) {
-                               fixed_phy_unregister(phydev);
-                               /* Put references taken by
-                                * of_phy_find_device() and
-                                * of_phy_register_fixed_link().
-                                */
-                               phy_device_free(phydev);
-                               phy_device_free(phydev);
-                       }
-               }
+               if (of_phy_is_fixed_link(slave_node))
+                       of_phy_deregister_fixed_link(slave_node);
 
                of_node_put(slave_data->phy_node);
 
@@ -2942,6 +2930,8 @@ static int cpsw_resume(struct device *dev)
        /* Select default pin state */
        pinctrl_pm_select_default_state(dev);
 
+       /* shut up ASSERT_RTNL() warning in netif_set_real_num_tx/rx_queues */
+       rtnl_lock();
        if (cpsw->data.dual_emac) {
                int i;
 
@@ -2953,6 +2943,8 @@ static int cpsw_resume(struct device *dev)
                if (netif_running(ndev))
                        cpsw_ndo_open(ndev);
        }
+       rtnl_unlock();
+
        return 0;
 }
 #endif
index 84fbe57..481c7bf 100644 (file)
@@ -1767,6 +1767,7 @@ static int davinci_emac_try_get_mac(struct platform_device *pdev,
  */
 static int davinci_emac_probe(struct platform_device *pdev)
 {
+       struct device_node *np = pdev->dev.of_node;
        int rc = 0;
        struct resource *res, *res_ctrl;
        struct net_device *ndev;
@@ -1805,7 +1806,7 @@ static int davinci_emac_probe(struct platform_device *pdev)
        if (!pdata) {
                dev_err(&pdev->dev, "no platform data\n");
                rc = -ENODEV;
-               goto no_pdata;
+               goto err_free_netdev;
        }
 
        /* MAC addr and PHY mask , RMII enable info from platform_data */
@@ -1941,6 +1942,10 @@ no_cpdma_chan:
                cpdma_chan_destroy(priv->rxchan);
        cpdma_ctlr_destroy(priv->dma);
 no_pdata:
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
+       of_node_put(priv->phy_node);
+err_free_netdev:
        free_netdev(ndev);
        return rc;
 }
@@ -1956,6 +1961,7 @@ static int davinci_emac_remove(struct platform_device *pdev)
 {
        struct net_device *ndev = platform_get_drvdata(pdev);
        struct emac_priv *priv = netdev_priv(ndev);
+       struct device_node *np = pdev->dev.of_node;
 
        dev_notice(&ndev->dev, "DaVinci EMAC: davinci_emac_remove()\n");
 
@@ -1968,6 +1974,8 @@ static int davinci_emac_remove(struct platform_device *pdev)
        unregister_netdev(ndev);
        of_node_put(priv->phy_node);
        pm_runtime_disable(&pdev->dev);
+       if (of_phy_is_fixed_link(np))
+               of_phy_deregister_fixed_link(np);
        free_netdev(ndev);
 
        return 0;
index 42edd7b..8b4822a 100644 (file)
@@ -859,7 +859,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        struct geneve_dev *geneve = netdev_priv(dev);
        struct geneve_sock *gs4;
        struct rtable *rt = NULL;
-       const struct iphdr *iip; /* interior IP header */
        int err = -EINVAL;
        struct flowi4 fl4;
        __u8 tos, ttl;
@@ -890,8 +889,6 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        skb_reset_mac_header(skb);
 
-       iip = ip_hdr(skb);
-
        if (info) {
                const struct ip_tunnel_key *key = &info->key;
                u8 *opts = NULL;
@@ -911,7 +908,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto tx_error;
 
-               tos = ip_tunnel_ecn_encap(key->tos, iip, skb);
+               tos = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
                df = key->tun_flags & TUNNEL_DONT_FRAGMENT ? htons(IP_DF) : 0;
        } else {
@@ -920,7 +917,7 @@ static netdev_tx_t geneve_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto tx_error;
 
-               tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, iip, skb);
+               tos = ip_tunnel_ecn_encap(fl4.flowi4_tos, ip_hdr(skb), skb);
                ttl = geneve->ttl;
                if (!ttl && IN_MULTICAST(ntohl(fl4.daddr)))
                        ttl = 1;
@@ -952,7 +949,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
 {
        struct geneve_dev *geneve = netdev_priv(dev);
        struct dst_entry *dst = NULL;
-       const struct iphdr *iip; /* interior IP header */
        struct geneve_sock *gs6;
        int err = -EINVAL;
        struct flowi6 fl6;
@@ -982,8 +978,6 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
        sport = udp_flow_src_port(geneve->net, skb, 1, USHRT_MAX, true);
        skb_reset_mac_header(skb);
 
-       iip = ip_hdr(skb);
-
        if (info) {
                const struct ip_tunnel_key *key = &info->key;
                u8 *opts = NULL;
@@ -1004,7 +998,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                if (unlikely(err))
                        goto tx_error;
 
-               prio = ip_tunnel_ecn_encap(key->tos, iip, skb);
+               prio = ip_tunnel_ecn_encap(key->tos, ip_hdr(skb), skb);
                ttl = key->ttl;
                label = info->key.label;
        } else {
@@ -1014,7 +1008,7 @@ static netdev_tx_t geneve6_xmit_skb(struct sk_buff *skb, struct net_device *dev,
                        goto tx_error;
 
                prio = ip_tunnel_ecn_encap(ip6_tclass(fl6.flowlabel),
-                                          iip, skb);
+                                          ip_hdr(skb), skb);
                ttl = geneve->ttl;
                if (!ttl && ipv6_addr_is_multicast(&fl6.daddr))
                        ttl = 1;
index f442eb3..0fef178 100644 (file)
@@ -497,6 +497,7 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
        struct net_device *phy_dev;
        int err;
        u16 mode = IPVLAN_MODE_L3;
+       bool create = false;
 
        if (!tb[IFLA_LINK])
                return -EINVAL;
@@ -513,6 +514,7 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
                err = ipvlan_port_create(phy_dev);
                if (err < 0)
                        return err;
+               create = true;
        }
 
        if (data && data[IFLA_IPVLAN_MODE])
@@ -536,22 +538,27 @@ static int ipvlan_link_new(struct net *src_net, struct net_device *dev,
 
        err = register_netdevice(dev);
        if (err < 0)
-               return err;
+               goto destroy_ipvlan_port;
 
        err = netdev_upper_dev_link(phy_dev, dev);
        if (err) {
-               unregister_netdevice(dev);
-               return err;
+               goto unregister_netdev;
        }
        err = ipvlan_set_port_mode(port, mode);
        if (err) {
-               unregister_netdevice(dev);
-               return err;
+               goto unregister_netdev;
        }
 
        list_add_tail_rcu(&ipvlan->pnode, &port->ipvlans);
        netif_stacked_transfer_operstate(phy_dev, dev);
        return 0;
+
+unregister_netdev:
+       unregister_netdevice(dev);
+destroy_ipvlan_port:
+       if (create)
+               ipvlan_port_destroy(phy_dev);
+       return err;
 }
 
 static void ipvlan_link_delete(struct net_device *dev, struct list_head *head)
index 4e3d2e7..e8c3a8c 100644 (file)
@@ -518,7 +518,9 @@ static netdev_tx_t w83977af_hard_xmit(struct sk_buff *skb,
                
                mtt = irda_get_mtt(skb);
                pr_debug("%s(%ld), mtt=%d\n", __func__ , jiffies, mtt);
-                       if (mtt)
+                       if (mtt > 1000)
+                               mdelay(mtt/1000);
+                       else if (mtt)
                                udelay(mtt);
 
                        /* Enable DMA interrupt */
index 070e329..7869b06 100644 (file)
@@ -491,7 +491,13 @@ static int macvtap_newlink(struct net *src_net,
        /* Don't put anything that may fail after macvlan_common_newlink
         * because we can't undo what it does.
         */
-       return macvlan_common_newlink(src_net, dev, tb, data);
+       err = macvlan_common_newlink(src_net, dev, tb, data);
+       if (err) {
+               netdev_rx_handler_unregister(dev);
+               return err;
+       }
+
+       return 0;
 }
 
 static void macvtap_dellink(struct net_device *dev,
@@ -736,13 +742,8 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
 
        if (zerocopy)
                err = zerocopy_sg_from_iter(skb, from);
-       else {
+       else
                err = skb_copy_datagram_from_iter(skb, 0, from, len);
-               if (!err && m && m->msg_control) {
-                       struct ubuf_info *uarg = m->msg_control;
-                       uarg->callback(uarg, false);
-               }
-       }
 
        if (err)
                goto err_kfree;
@@ -773,7 +774,11 @@ static ssize_t macvtap_get_user(struct macvtap_queue *q, struct msghdr *m,
                skb_shinfo(skb)->destructor_arg = m->msg_control;
                skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
                skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
+       } else if (m && m->msg_control) {
+               struct ubuf_info *uarg = m->msg_control;
+               uarg->callback(uarg, false);
        }
+
        if (vlan) {
                skb->dev = vlan->dev;
                dev_queue_xmit(skb);
index aadd6e9..9cbe645 100644 (file)
@@ -102,15 +102,19 @@ static int rtl8211f_config_init(struct phy_device *phydev)
        if (ret < 0)
                return ret;
 
-       if (phydev->interface == PHY_INTERFACE_MODE_RGMII) {
-               /* enable TXDLY */
-               phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08);
-               reg = phy_read(phydev, 0x11);
+       phy_write(phydev, RTL8211F_PAGE_SELECT, 0xd08);
+       reg = phy_read(phydev, 0x11);
+
+       /* enable TX-delay for rgmii-id and rgmii-txid, otherwise disable it */
+       if (phydev->interface == PHY_INTERFACE_MODE_RGMII_ID ||
+           phydev->interface == PHY_INTERFACE_MODE_RGMII_TXID)
                reg |= RTL8211F_TX_DELAY;
-               phy_write(phydev, 0x11, reg);
-               /* restore to default page 0 */
-               phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0);
-       }
+       else
+               reg &= ~RTL8211F_TX_DELAY;
+
+       phy_write(phydev, 0x11, reg);
+       /* restore to default page 0 */
+       phy_write(phydev, RTL8211F_PAGE_SELECT, 0x0);
 
        return 0;
 }
index 8093e39..db6acec 100644 (file)
@@ -1246,13 +1246,8 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
 
        if (zerocopy)
                err = zerocopy_sg_from_iter(skb, from);
-       else {
+       else
                err = skb_copy_datagram_from_iter(skb, 0, from, len);
-               if (!err && msg_control) {
-                       struct ubuf_info *uarg = msg_control;
-                       uarg->callback(uarg, false);
-               }
-       }
 
        if (err) {
                this_cpu_inc(tun->pcpu_stats->rx_dropped);
@@ -1298,6 +1293,9 @@ static ssize_t tun_get_user(struct tun_struct *tun, struct tun_file *tfile,
                skb_shinfo(skb)->destructor_arg = msg_control;
                skb_shinfo(skb)->tx_flags |= SKBTX_DEV_ZEROCOPY;
                skb_shinfo(skb)->tx_flags |= SKBTX_SHARED_FRAG;
+       } else if (msg_control) {
+               struct ubuf_info *uarg = msg_control;
+               uarg->callback(uarg, false);
        }
 
        skb_reset_network_header(skb);
index cce2495..dc7b639 100644 (file)
@@ -603,12 +603,12 @@ static void ax88772_suspend(struct usbnet *dev)
        u16 medium;
 
        /* Stop MAC operation */
-       medium = asix_read_medium_status(dev, 0);
+       medium = asix_read_medium_status(dev, 1);
        medium &= ~AX_MEDIUM_RE;
-       asix_write_medium_mode(dev, medium, 0);
+       asix_write_medium_mode(dev, medium, 1);
 
        netdev_dbg(dev->net, "ax88772_suspend: medium=0x%04x\n",
-                  asix_read_medium_status(dev, 0));
+                  asix_read_medium_status(dev, 1));
 
        /* Preserve BMCR for restoring */
        priv->presvd_phy_bmcr =
index c47ec0a..dd623f6 100644 (file)
@@ -388,12 +388,6 @@ void usbnet_cdc_status(struct usbnet *dev, struct urb *urb)
        case USB_CDC_NOTIFY_NETWORK_CONNECTION:
                netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
                          event->wValue ? "on" : "off");
-
-               /* Work-around for devices with broken off-notifications */
-               if (event->wValue &&
-                   !test_bit(__LINK_STATE_NOCARRIER, &dev->net->state))
-                       usbnet_link_change(dev, 0, 0);
-
                usbnet_link_change(dev, !!event->wValue, 0);
                break;
        case USB_CDC_NOTIFY_SPEED_CHANGE:       /* tx/rx rates */
@@ -466,6 +460,36 @@ static int usbnet_cdc_zte_rx_fixup(struct usbnet *dev, struct sk_buff *skb)
        return 1;
 }
 
+/* Ensure correct link state
+ *
+ * Some devices (ZTE MF823/831/910) export two carrier on notifications when
+ * connected. This causes the link state to be incorrect. Work around this by
+ * always setting the state to off, then on.
+ */
+void usbnet_cdc_zte_status(struct usbnet *dev, struct urb *urb)
+{
+       struct usb_cdc_notification *event;
+
+       if (urb->actual_length < sizeof(*event))
+               return;
+
+       event = urb->transfer_buffer;
+
+       if (event->bNotificationType != USB_CDC_NOTIFY_NETWORK_CONNECTION) {
+               usbnet_cdc_status(dev, urb);
+               return;
+       }
+
+       netif_dbg(dev, timer, dev->net, "CDC: carrier %s\n",
+                 event->wValue ? "on" : "off");
+
+       if (event->wValue &&
+           netif_carrier_ok(dev->net))
+               netif_carrier_off(dev->net);
+
+       usbnet_link_change(dev, !!event->wValue, 0);
+}
+
 static const struct driver_info        cdc_info = {
        .description =  "CDC Ethernet Device",
        .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
@@ -481,7 +505,7 @@ static const struct driver_info     zte_cdc_info = {
        .flags =        FLAG_ETHER | FLAG_POINTTOPOINT,
        .bind =         usbnet_cdc_zte_bind,
        .unbind =       usbnet_cdc_unbind,
-       .status =       usbnet_cdc_status,
+       .status =       usbnet_cdc_zte_status,
        .set_rx_mode =  usbnet_cdc_update_filter,
        .manage_power = usbnet_manage_power,
        .rx_fixup = usbnet_cdc_zte_rx_fixup,
index 3ff76c6..6fe1cdb 100644 (file)
@@ -894,6 +894,7 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x1bbb, 0x0203, 2)},    /* Alcatel L800MA */
        {QMI_FIXED_INTF(0x2357, 0x0201, 4)},    /* TP-LINK HSUPA Modem MA180 */
        {QMI_FIXED_INTF(0x2357, 0x9000, 4)},    /* TP-LINK MA260 */
+       {QMI_QUIRK_SET_DTR(0x1bc7, 0x1040, 2)}, /* Telit LE922A */
        {QMI_FIXED_INTF(0x1bc7, 0x1200, 5)},    /* Telit LE920 */
        {QMI_FIXED_INTF(0x1bc7, 0x1201, 2)},    /* Telit LE920 */
        {QMI_FIXED_INTF(0x1c9e, 0x9b01, 3)},    /* XS Stick W100-2 from 4G Systems */
index 24532cd..2ba01ca 100644 (file)
@@ -611,6 +611,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
        struct vxlan_rdst *rd = NULL;
        struct vxlan_fdb *f;
        int notify = 0;
+       int rc;
 
        f = __vxlan_find_mac(vxlan, mac);
        if (f) {
@@ -641,8 +642,7 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
                if ((flags & NLM_F_APPEND) &&
                    (is_multicast_ether_addr(f->eth_addr) ||
                     is_zero_ether_addr(f->eth_addr))) {
-                       int rc = vxlan_fdb_append(f, ip, port, vni, ifindex,
-                                                 &rd);
+                       rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
 
                        if (rc < 0)
                                return rc;
@@ -673,7 +673,11 @@ static int vxlan_fdb_create(struct vxlan_dev *vxlan,
                INIT_LIST_HEAD(&f->remotes);
                memcpy(f->eth_addr, mac, ETH_ALEN);
 
-               vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
+               rc = vxlan_fdb_append(f, ip, port, vni, ifindex, &rd);
+               if (rc < 0) {
+                       kfree(f);
+                       return rc;
+               }
 
                ++vxlan->addrcnt;
                hlist_add_head_rcu(&f->hlist,
index 39ce76a..16241d2 100644 (file)
@@ -2222,8 +2222,9 @@ done:
                        is_scanning_required = 1;
                } else {
                        mwifiex_dbg(priv->adapter, MSG,
-                                   "info: trying to associate to '%s' bssid %pM\n",
-                                   (char *)req_ssid.ssid, bss->bssid);
+                                   "info: trying to associate to '%.*s' bssid %pM\n",
+                                   req_ssid.ssid_len, (char *)req_ssid.ssid,
+                                   bss->bssid);
                        memcpy(&priv->cfg_bssid, bss->bssid, ETH_ALEN);
                        break;
                }
@@ -2283,8 +2284,8 @@ mwifiex_cfg80211_connect(struct wiphy *wiphy, struct net_device *dev,
        }
 
        mwifiex_dbg(adapter, INFO,
-                   "info: Trying to associate to %s and bssid %pM\n",
-                   (char *)sme->ssid, sme->bssid);
+                   "info: Trying to associate to %.*s and bssid %pM\n",
+                   (int)sme->ssid_len, (char *)sme->ssid, sme->bssid);
 
        if (!mwifiex_stop_bg_scan(priv))
                cfg80211_sched_scan_stopped_rtnl(priv->wdev.wiphy);
@@ -2417,8 +2418,8 @@ mwifiex_cfg80211_join_ibss(struct wiphy *wiphy, struct net_device *dev,
        }
 
        mwifiex_dbg(priv->adapter, MSG,
-                   "info: trying to join to %s and bssid %pM\n",
-                   (char *)params->ssid, params->bssid);
+                   "info: trying to join to %.*s and bssid %pM\n",
+                   params->ssid_len, (char *)params->ssid, params->bssid);
 
        mwifiex_set_ibss_params(priv, params);
 
index 5a3145a..262281b 100644 (file)
@@ -490,3 +490,18 @@ int of_phy_register_fixed_link(struct device_node *np)
        return -ENODEV;
 }
 EXPORT_SYMBOL(of_phy_register_fixed_link);
+
+void of_phy_deregister_fixed_link(struct device_node *np)
+{
+       struct phy_device *phydev;
+
+       phydev = of_phy_find_device(np);
+       if (!phydev)
+               return;
+
+       fixed_phy_unregister(phydev);
+
+       put_device(&phydev->mdio.dev);  /* of_phy_find_device() */
+       phy_device_free(phydev);        /* fixed_phy_register() */
+}
+EXPORT_SYMBOL(of_phy_deregister_fixed_link);
index 8df6312..1a02038 100644 (file)
@@ -3,7 +3,7 @@
  *
  * Copyright (C) 2015-2016 Synopsys, Inc. (www.synopsys.com)
  *
- * Authors: Joao Pinto <jpmpinto@gmail.com>
+ * Authors: Joao Pinto <Joao.Pinto@synopsys.com>
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
index db553dc..2b6a592 100644 (file)
@@ -307,20 +307,6 @@ out:
        return 0;
 }
 
-static struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
-{
-       while (1) {
-               if (!pci_is_pcie(dev))
-                       break;
-               if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
-                       return dev;
-               if (!dev->bus->self)
-                       break;
-               dev = dev->bus->self;
-       }
-       return NULL;
-}
-
 static int find_aer_device_iter(struct device *device, void *data)
 {
        struct pcie_device **result = data;
index ab00267..104c46d 100644 (file)
@@ -1439,6 +1439,21 @@ static void program_hpp_type1(struct pci_dev *dev, struct hpp_type1 *hpp)
                dev_warn(&dev->dev, "PCI-X settings not supported\n");
 }
 
+static bool pcie_root_rcb_set(struct pci_dev *dev)
+{
+       struct pci_dev *rp = pcie_find_root_port(dev);
+       u16 lnkctl;
+
+       if (!rp)
+               return false;
+
+       pcie_capability_read_word(rp, PCI_EXP_LNKCTL, &lnkctl);
+       if (lnkctl & PCI_EXP_LNKCTL_RCB)
+               return true;
+
+       return false;
+}
+
 static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
 {
        int pos;
@@ -1468,9 +1483,20 @@ static void program_hpp_type2(struct pci_dev *dev, struct hpp_type2 *hpp)
                        ~hpp->pci_exp_devctl_and, hpp->pci_exp_devctl_or);
 
        /* Initialize Link Control Register */
-       if (pcie_cap_has_lnkctl(dev))
+       if (pcie_cap_has_lnkctl(dev)) {
+
+               /*
+                * If the Root Port supports Read Completion Boundary of
+                * 128, set RCB to 128.  Otherwise, clear it.
+                */
+               hpp->pci_exp_lnkctl_and |= PCI_EXP_LNKCTL_RCB;
+               hpp->pci_exp_lnkctl_or &= ~PCI_EXP_LNKCTL_RCB;
+               if (pcie_root_rcb_set(dev))
+                       hpp->pci_exp_lnkctl_or |= PCI_EXP_LNKCTL_RCB;
+
                pcie_capability_clear_and_set_word(dev, PCI_EXP_LNKCTL,
                        ~hpp->pci_exp_lnkctl_and, hpp->pci_exp_lnkctl_or);
+       }
 
        /* Find Advanced Error Reporting Enhanced Capability */
        pos = pci_find_ext_capability(dev, PCI_EXT_CAP_ID_ERR);
index 381871b..9d5bd7d 100644 (file)
@@ -474,6 +474,7 @@ static int meson_pwm_probe(struct platform_device *pdev)
        if (IS_ERR(meson->base))
                return PTR_ERR(meson->base);
 
+       spin_lock_init(&meson->lock);
        meson->chip.dev = &pdev->dev;
        meson->chip.ops = &meson_pwm_ops;
        meson->chip.base = -1;
index 0296d81..a813239 100644 (file)
@@ -425,6 +425,8 @@ void pwmchip_sysfs_unexport_children(struct pwm_chip *chip)
                if (test_bit(PWMF_EXPORTED, &pwm->flags))
                        pwm_unexport_child(parent, pwm);
        }
+
+       put_device(parent);
 }
 
 static int __init pwm_sysfs_init(void)
index aebc4dd..ac05317 100644 (file)
@@ -1083,7 +1083,7 @@ unsigned int beiscsi_boot_get_sinfo(struct beiscsi_hba *phba)
        nonemb_cmd = &phba->boot_struct.nonemb_cmd;
        nonemb_cmd->size = sizeof(*resp);
        nonemb_cmd->va = pci_alloc_consistent(phba->ctrl.pdev,
-                                             sizeof(nonemb_cmd->size),
+                                             nonemb_cmd->size,
                                              &nonemb_cmd->dma);
        if (!nonemb_cmd->va) {
                mutex_unlock(&ctrl->mbox_lock);
index d007ec1..a1d6ab7 100644 (file)
@@ -2009,7 +2009,7 @@ static struct hpsa_scsi_dev_t *lookup_hpsa_scsi_dev(struct ctlr_info *h,
 
 static int hpsa_slave_alloc(struct scsi_device *sdev)
 {
-       struct hpsa_scsi_dev_t *sd;
+       struct hpsa_scsi_dev_t *sd = NULL;
        unsigned long flags;
        struct ctlr_info *h;
 
@@ -2026,7 +2026,8 @@ static int hpsa_slave_alloc(struct scsi_device *sdev)
                        sd->target = sdev_id(sdev);
                        sd->lun = sdev->lun;
                }
-       } else
+       }
+       if (!sd)
                sd = lookup_hpsa_scsi_dev(h, sdev_channel(sdev),
                                        sdev_id(sdev), sdev->lun);
 
@@ -3840,6 +3841,7 @@ static int hpsa_update_device_info(struct ctlr_info *h,
                sizeof(this_device->vendor));
        memcpy(this_device->model, &inq_buff[16],
                sizeof(this_device->model));
+       this_device->rev = inq_buff[2];
        memset(this_device->device_id, 0,
                sizeof(this_device->device_id));
        if (hpsa_get_device_id(h, scsi3addr, this_device->device_id, 8,
@@ -3929,10 +3931,14 @@ static void figure_bus_target_lun(struct ctlr_info *h,
 
        if (!is_logical_dev_addr_mode(lunaddrbytes)) {
                /* physical device, target and lun filled in later */
-               if (is_hba_lunid(lunaddrbytes))
+               if (is_hba_lunid(lunaddrbytes)) {
+                       int bus = HPSA_HBA_BUS;
+
+                       if (!device->rev)
+                               bus = HPSA_LEGACY_HBA_BUS;
                        hpsa_set_bus_target_lun(device,
-                                       HPSA_HBA_BUS, 0, lunid & 0x3fff);
-               else
+                                       bus, 0, lunid & 0x3fff);
+               else
                        /* defer target, lun assignment for physical devices */
                        hpsa_set_bus_target_lun(device,
                                        HPSA_PHYSICAL_DEVICE_BUS, -1, -1);
index 82cdfad..9ea162d 100644 (file)
@@ -69,6 +69,7 @@ struct hpsa_scsi_dev_t {
        u64 sas_address;
        unsigned char vendor[8];        /* bytes 8-15 of inquiry data */
        unsigned char model[16];        /* bytes 16-31 of inquiry data */
+       unsigned char rev;              /* byte 2 of inquiry data */
        unsigned char raid_level;       /* from inquiry page 0xC1 */
        unsigned char volume_offline;   /* discovered via TUR or VPD */
        u16 queue_depth;                /* max queue_depth for this device */
@@ -402,6 +403,7 @@ struct offline_device_entry {
 #define HPSA_RAID_VOLUME_BUS           1
 #define HPSA_EXTERNAL_RAID_VOLUME_BUS  2
 #define HPSA_HBA_BUS                   0
+#define HPSA_LEGACY_HBA_BUS            3
 
 /*
        Send the command to the hardware
index 04ce7cf..50c7167 100644 (file)
@@ -308,7 +308,7 @@ struct fc_host_statistics *fc_get_host_stats(struct Scsi_Host *shost)
        fc_stats = &lport->host_stats;
        memset(fc_stats, 0, sizeof(struct fc_host_statistics));
 
-       fc_stats->seconds_since_last_reset = (lport->boot_time - jiffies) / HZ;
+       fc_stats->seconds_since_last_reset = (jiffies - lport->boot_time) / HZ;
 
        for_each_possible_cpu(cpu) {
                struct fc_stats *stats;
index 91b70bc..1c4744e 100644 (file)
@@ -3885,6 +3885,11 @@ _scsih_temp_threshold_events(struct MPT3SAS_ADAPTER *ioc,
        }
 }
 
+static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd)
+{
+       return (scmd->cmnd[0] == ATA_12 || scmd->cmnd[0] == ATA_16);
+}
+
 /**
  * _scsih_flush_running_cmds - completing outstanding commands.
  * @ioc: per adapter object
@@ -3906,6 +3911,9 @@ _scsih_flush_running_cmds(struct MPT3SAS_ADAPTER *ioc)
                if (!scmd)
                        continue;
                count++;
+               if (ata_12_16_cmd(scmd))
+                       scsi_internal_device_unblock(scmd->device,
+                                                       SDEV_RUNNING);
                mpt3sas_base_free_smid(ioc, smid);
                scsi_dma_unmap(scmd);
                if (ioc->pci_error_recovery)
@@ -4010,11 +4018,6 @@ _scsih_eedp_error_handling(struct scsi_cmnd *scmd, u16 ioc_status)
            SAM_STAT_CHECK_CONDITION;
 }
 
-static inline bool ata_12_16_cmd(struct scsi_cmnd *scmd)
-{
-       return (scmd->cmnd[0] == ATA_12 || scmd->cmnd[0] == ATA_16);
-}
-
 /**
  * scsih_qcmd - main scsi request entry point
  * @scmd: pointer to scsi command object
index 86eb199..c7cc803 100644 (file)
@@ -791,8 +791,10 @@ static int mvs_task_prep(struct sas_task *task, struct mvs_info *mvi, int is_tmf
        slot->slot_tag = tag;
 
        slot->buf = pci_pool_alloc(mvi->dma_pool, GFP_ATOMIC, &slot->buf_dma);
-       if (!slot->buf)
+       if (!slot->buf) {
+               rc = -ENOMEM;
                goto err_out_tag;
+       }
        memset(slot->buf, 0, MVS_SLOT_BUF_SZ);
 
        tei.task = task;
index 4377e87..892a0b0 100644 (file)
@@ -356,8 +356,8 @@ struct qlogicpti {
 
        /* The rest of the elements are unimportant for performance. */
        struct qlogicpti         *next;
-       __u32                     res_dvma;             /* Ptr to RESPONSE bufs (DVMA)*/
-       __u32                     req_dvma;             /* Ptr to REQUEST bufs (DVMA) */
+       dma_addr_t                res_dvma;             /* Ptr to RESPONSE bufs (DVMA)*/
+       dma_addr_t                req_dvma;             /* Ptr to REQUEST bufs (DVMA) */
        u_char                    fware_majrev, fware_minrev, fware_micrev;
        struct Scsi_Host         *qhost;
        int                       qpti_id;
index 0b8ce2b..05f75a9 100644 (file)
@@ -3232,9 +3232,6 @@ int btrfs_dirty_pages(struct btrfs_root *root, struct inode *inode,
                      loff_t pos, size_t write_bytes,
                      struct extent_state **cached);
 int btrfs_fdatawrite_range(struct inode *inode, loff_t start, loff_t end);
-ssize_t btrfs_copy_file_range(struct file *file_in, loff_t pos_in,
-                             struct file *file_out, loff_t pos_out,
-                             size_t len, unsigned int flags);
 int btrfs_clone_file_range(struct file *file_in, loff_t pos_in,
                           struct file *file_out, loff_t pos_out, u64 len);
 
index 3a14c87..991cc99 100644 (file)
@@ -2998,7 +2998,6 @@ const struct file_operations btrfs_file_operations = {
 #ifdef CONFIG_COMPAT
        .compat_ioctl   = btrfs_compat_ioctl,
 #endif
-       .copy_file_range = btrfs_copy_file_range,
        .clone_file_range = btrfs_clone_file_range,
        .dedupe_file_range = btrfs_dedupe_file_range,
 };
index 8270f43..70eebc6 100644 (file)
@@ -3980,18 +3980,6 @@ out_unlock:
        return ret;
 }
 
-ssize_t btrfs_copy_file_range(struct file *file_in, loff_t pos_in,
-                             struct file *file_out, loff_t pos_out,
-                             size_t len, unsigned int flags)
-{
-       ssize_t ret;
-
-       ret = btrfs_clone_files(file_out, file_in, pos_in, len, pos_out);
-       if (ret == 0)
-               ret = len;
-       return ret;
-}
-
 int btrfs_clone_file_range(struct file *src_file, loff_t off,
                struct file *dst_file, loff_t destoff, u64 len)
 {
index 8347c90..5eb0412 100644 (file)
@@ -808,7 +808,11 @@ calc_seckey(struct cifs_ses *ses)
        struct crypto_skcipher *tfm_arc4;
        struct scatterlist sgin, sgout;
        struct skcipher_request *req;
-       unsigned char sec_key[CIFS_SESS_KEY_SIZE]; /* a nonce */
+       unsigned char *sec_key;
+
+       sec_key = kmalloc(CIFS_SESS_KEY_SIZE, GFP_KERNEL);
+       if (sec_key == NULL)
+               return -ENOMEM;
 
        get_random_bytes(sec_key, CIFS_SESS_KEY_SIZE);
 
@@ -816,7 +820,7 @@ calc_seckey(struct cifs_ses *ses)
        if (IS_ERR(tfm_arc4)) {
                rc = PTR_ERR(tfm_arc4);
                cifs_dbg(VFS, "could not allocate crypto API arc4\n");
-               return rc;
+               goto out;
        }
 
        rc = crypto_skcipher_setkey(tfm_arc4, ses->auth_key.response,
@@ -854,7 +858,8 @@ calc_seckey(struct cifs_ses *ses)
 
 out_free_cipher:
        crypto_free_skcipher(tfm_arc4);
-
+out:
+       kfree(sec_key);
        return rc;
 }
 
index 3f3185f..e3fed92 100644 (file)
@@ -3427,6 +3427,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
        __u16 rc = 0;
        struct cifs_posix_acl *cifs_acl = (struct cifs_posix_acl *)parm_data;
        struct posix_acl_xattr_header *local_acl = (void *)pACL;
+       struct posix_acl_xattr_entry *ace = (void *)(local_acl + 1);
        int count;
        int i;
 
@@ -3453,8 +3454,7 @@ static __u16 ACL_to_cifs_posix(char *parm_data, const char *pACL,
                return 0;
        }
        for (i = 0; i < count; i++) {
-               rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i],
-                       (struct posix_acl_xattr_entry *)(local_acl + 1));
+               rc = convert_ace_to_cifs_ace(&cifs_acl->ace_array[i], &ace[i]);
                if (rc != 0) {
                        /* ACE not converted */
                        break;
index aab5227..4547aed 100644 (file)
@@ -412,6 +412,9 @@ cifs_reconnect(struct TCP_Server_Info *server)
                }
        } while (server->tcpStatus == CifsNeedReconnect);
 
+       if (server->tcpStatus == CifsNeedNegotiate)
+               mod_delayed_work(cifsiod_wq, &server->echo, 0);
+
        return rc;
 }
 
@@ -421,17 +424,25 @@ cifs_echo_request(struct work_struct *work)
        int rc;
        struct TCP_Server_Info *server = container_of(work,
                                        struct TCP_Server_Info, echo.work);
-       unsigned long echo_interval = server->echo_interval;
+       unsigned long echo_interval;
+
+       /*
+        * If we need to renegotiate, set echo interval to zero to
+        * immediately call echo service where we can renegotiate.
+        */
+       if (server->tcpStatus == CifsNeedNegotiate)
+               echo_interval = 0;
+       else
+               echo_interval = server->echo_interval;
 
        /*
-        * We cannot send an echo if it is disabled or until the
-        * NEGOTIATE_PROTOCOL request is done, which is indicated by
-        * server->ops->need_neg() == true. Also, no need to ping if
-        * we got a response recently.
+        * We cannot send an echo if it is disabled.
+        * Also, no need to ping if we got a response recently.
         */
 
        if (server->tcpStatus == CifsNeedReconnect ||
-           server->tcpStatus == CifsExiting || server->tcpStatus == CifsNew ||
+           server->tcpStatus == CifsExiting ||
+           server->tcpStatus == CifsNew ||
            (server->ops->can_echo && !server->ops->can_echo(server)) ||
            time_before(jiffies, server->lstrp + echo_interval - HZ))
                goto requeue_echo;
@@ -442,7 +453,7 @@ cifs_echo_request(struct work_struct *work)
                         server->hostname);
 
 requeue_echo:
-       queue_delayed_work(cifsiod_wq, &server->echo, echo_interval);
+       queue_delayed_work(cifsiod_wq, &server->echo, server->echo_interval);
 }
 
 static bool
index 98b3eb7..0ec1373 100644 (file)
@@ -377,9 +377,9 @@ repeat:
                        {
                                int p;
                                for (p = 0; p < rr->u.ER.len_id; p++)
-                                       printk("%c", rr->u.ER.data[p]);
+                                       printk(KERN_CONT "%c", rr->u.ER.data[p]);
                        }
-                       printk("\n");
+                       printk(KERN_CONT "\n");
                        break;
                case SIG('P', 'X'):
                        inode->i_mode = isonum_733(rr->u.PX.mode);
index f72712f..d4ec0d8 100644 (file)
@@ -5194,7 +5194,7 @@ int ocfs2_change_extent_flag(handle_t *handle,
        rec = &el->l_recs[index];
        if (new_flags && (rec->e_flags & new_flags)) {
                mlog(ML_ERROR, "Owner %llu tried to set %d flags on an "
-                    "extent that already had them",
+                    "extent that already had them\n",
                     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                     new_flags);
                goto out;
@@ -5202,7 +5202,7 @@ int ocfs2_change_extent_flag(handle_t *handle,
 
        if (clear_flags && !(rec->e_flags & clear_flags)) {
                mlog(ML_ERROR, "Owner %llu tried to clear %d flags on an "
-                    "extent that didn't have them",
+                    "extent that didn't have them\n",
                     (unsigned long long)ocfs2_metadata_cache_owner(et->et_ci),
                     clear_flags);
                goto out;
@@ -5713,8 +5713,7 @@ int ocfs2_remove_btree_range(struct inode *inode,
        struct ocfs2_refcount_tree *ref_tree = NULL;
 
        if ((flags & OCFS2_EXT_REFCOUNTED) && len) {
-               BUG_ON(!(OCFS2_I(inode)->ip_dyn_features &
-                        OCFS2_HAS_REFCOUNT_FL));
+               BUG_ON(!ocfs2_is_refcount_inode(inode));
 
                if (!refcount_tree_locked) {
                        ret = ocfs2_lock_refcount_tree(osb, refcount_loc, 1,
index c5c5b97..3372d82 100644 (file)
@@ -464,6 +464,15 @@ static sector_t ocfs2_bmap(struct address_space *mapping, sector_t block)
        trace_ocfs2_bmap((unsigned long long)OCFS2_I(inode)->ip_blkno,
                         (unsigned long long)block);
 
+       /*
+        * The swap code (ab-)uses ->bmap to get a block mapping and then
+        * bypasseÑ• the file system for actual I/O.  We really can't allow
+        * that on refcounted inodes, so we have to skip out here.  And yes,
+        * 0 is the magic code for a bmap error..
+        */
+       if (ocfs2_is_refcount_inode(inode))
+               return 0;
+
        /* We don't need to lock journal system files, since they aren't
         * accessed concurrently from multiple nodes.
         */
@@ -2254,10 +2263,10 @@ out:
        return ret;
 }
 
-static void ocfs2_dio_end_io_write(struct inode *inode,
-                                  struct ocfs2_dio_write_ctxt *dwc,
-                                  loff_t offset,
-                                  ssize_t bytes)
+static int ocfs2_dio_end_io_write(struct inode *inode,
+                                 struct ocfs2_dio_write_ctxt *dwc,
+                                 loff_t offset,
+                                 ssize_t bytes)
 {
        struct ocfs2_cached_dealloc_ctxt dealloc;
        struct ocfs2_extent_tree et;
@@ -2308,7 +2317,7 @@ static void ocfs2_dio_end_io_write(struct inode *inode,
                        mlog_errno(ret);
        }
 
-       di = (struct ocfs2_dinode *)di_bh;
+       di = (struct ocfs2_dinode *)di_bh->b_data;
 
        ocfs2_init_dinode_extent_tree(&et, INODE_CACHE(inode), di_bh);
 
@@ -2365,6 +2374,8 @@ out:
        if (locked)
                inode_unlock(inode);
        ocfs2_dio_free_write_ctx(inode, dwc);
+
+       return ret;
 }
 
 /*
@@ -2379,21 +2390,19 @@ static int ocfs2_dio_end_io(struct kiocb *iocb,
 {
        struct inode *inode = file_inode(iocb->ki_filp);
        int level;
-
-       if (bytes <= 0)
-               return 0;
+       int ret = 0;
 
        /* this io's submitter should not have unlocked this before we could */
        BUG_ON(!ocfs2_iocb_is_rw_locked(iocb));
 
-       if (private)
-               ocfs2_dio_end_io_write(inode, private, offset, bytes);
+       if (bytes > 0 && private)
+               ret = ocfs2_dio_end_io_write(inode, private, offset, bytes);
 
        ocfs2_iocb_clear_rw_locked(iocb);
 
        level = ocfs2_iocb_rw_locked_level(iocb);
        ocfs2_rw_unlock(inode, level);
-       return 0;
+       return ret;
 }
 
 static ssize_t ocfs2_direct_IO(struct kiocb *iocb, struct iov_iter *iter)
index 000c234..c488965 100644 (file)
@@ -1030,7 +1030,7 @@ int ocfs2_extend_no_holes(struct inode *inode, struct buffer_head *di_bh,
         * Only quota files call this without a bh, and they can't be
         * refcounted.
         */
-       BUG_ON(!di_bh && (oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
+       BUG_ON(!di_bh && ocfs2_is_refcount_inode(inode));
        BUG_ON(!di_bh && !(oi->ip_flags & OCFS2_INODE_SYSTEM_FILE));
 
        clusters_to_add = ocfs2_clusters_for_bytes(inode->i_sb, new_i_size);
@@ -1667,9 +1667,9 @@ static void ocfs2_calc_trunc_pos(struct inode *inode,
        *done = ret;
 }
 
-static int ocfs2_remove_inode_range(struct inode *inode,
-                                   struct buffer_head *di_bh, u64 byte_start,
-                                   u64 byte_len)
+int ocfs2_remove_inode_range(struct inode *inode,
+                            struct buffer_head *di_bh, u64 byte_start,
+                            u64 byte_len)
 {
        int ret = 0, flags = 0, done = 0, i;
        u32 trunc_start, trunc_len, trunc_end, trunc_cpos, phys_cpos;
@@ -1719,8 +1719,7 @@ static int ocfs2_remove_inode_range(struct inode *inode,
         * within one cluster(means is not exactly aligned to clustersize).
         */
 
-       if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) {
-
+       if (ocfs2_is_refcount_inode(inode)) {
                ret = ocfs2_cow_file_pos(inode, di_bh, byte_start);
                if (ret) {
                        mlog_errno(ret);
@@ -2036,7 +2035,7 @@ int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
        struct super_block *sb = inode->i_sb;
 
        if (!ocfs2_refcount_tree(OCFS2_SB(inode->i_sb)) ||
-           !(OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) ||
+           !ocfs2_is_refcount_inode(inode) ||
            OCFS2_I(inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)
                return 0;
 
@@ -2440,6 +2439,31 @@ out:
        return offset;
 }
 
+static int ocfs2_file_clone_range(struct file *file_in,
+                                 loff_t pos_in,
+                                 struct file *file_out,
+                                 loff_t pos_out,
+                                 u64 len)
+{
+       return ocfs2_reflink_remap_range(file_in, pos_in, file_out, pos_out,
+                                        len, false);
+}
+
+static ssize_t ocfs2_file_dedupe_range(struct file *src_file,
+                                      u64 loff,
+                                      u64 len,
+                                      struct file *dst_file,
+                                      u64 dst_loff)
+{
+       int error;
+
+       error = ocfs2_reflink_remap_range(src_file, loff, dst_file, dst_loff,
+                                         len, true);
+       if (error)
+               return error;
+       return len;
+}
+
 const struct inode_operations ocfs2_file_iops = {
        .setattr        = ocfs2_setattr,
        .getattr        = ocfs2_getattr,
@@ -2479,6 +2503,8 @@ const struct file_operations ocfs2_fops = {
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .fallocate      = ocfs2_fallocate,
+       .clone_file_range = ocfs2_file_clone_range,
+       .dedupe_file_range = ocfs2_file_dedupe_range,
 };
 
 const struct file_operations ocfs2_dops = {
@@ -2524,6 +2550,8 @@ const struct file_operations ocfs2_fops_no_plocks = {
        .splice_read    = generic_file_splice_read,
        .splice_write   = iter_file_splice_write,
        .fallocate      = ocfs2_fallocate,
+       .clone_file_range = ocfs2_file_clone_range,
+       .dedupe_file_range = ocfs2_file_dedupe_range,
 };
 
 const struct file_operations ocfs2_dops_no_plocks = {
index e8c62f2..897fd9a 100644 (file)
@@ -82,4 +82,7 @@ int ocfs2_change_file_space(struct file *file, unsigned int cmd,
 
 int ocfs2_check_range_for_refcount(struct inode *inode, loff_t pos,
                                   size_t count);
+int ocfs2_remove_inode_range(struct inode *inode,
+                            struct buffer_head *di_bh, u64 byte_start,
+                            u64 byte_len);
 #endif /* OCFS2_FILE_H */
index 5af68fc..9b955f7 100644 (file)
@@ -181,4 +181,10 @@ static inline struct ocfs2_inode_info *cache_info_to_inode(struct ocfs2_caching_
        return container_of(ci, struct ocfs2_inode_info, ip_metadata_cache);
 }
 
+/* Does this inode have the reflink flag set? */
+static inline bool ocfs2_is_refcount_inode(struct inode *inode)
+{
+       return (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL);
+}
+
 #endif /* OCFS2_INODE_H */
index 4e8f32e..e52a285 100644 (file)
@@ -235,10 +235,7 @@ static int ocfs2_defrag_extent(struct ocfs2_move_extents_context *context,
        u64 phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
 
        if ((ext_flags & OCFS2_EXT_REFCOUNTED) && *len) {
-
-               BUG_ON(!(OCFS2_I(inode)->ip_dyn_features &
-                        OCFS2_HAS_REFCOUNT_FL));
-
+               BUG_ON(!ocfs2_is_refcount_inode(inode));
                BUG_ON(!context->refcount_loc);
 
                ret = ocfs2_lock_refcount_tree(osb, context->refcount_loc, 1,
@@ -581,10 +578,7 @@ static int ocfs2_move_extent(struct ocfs2_move_extents_context *context,
        phys_blkno = ocfs2_clusters_to_blocks(inode->i_sb, phys_cpos);
 
        if ((ext_flags & OCFS2_EXT_REFCOUNTED) && len) {
-
-               BUG_ON(!(OCFS2_I(inode)->ip_dyn_features &
-                        OCFS2_HAS_REFCOUNT_FL));
-
+               BUG_ON(!ocfs2_is_refcount_inode(inode));
                BUG_ON(!context->refcount_loc);
 
                ret = ocfs2_lock_refcount_tree(osb, context->refcount_loc, 1,
index 1923851..b18465e 100644 (file)
@@ -34,6 +34,7 @@
 #include "xattr.h"
 #include "namei.h"
 #include "ocfs2_trace.h"
+#include "file.h"
 
 #include <linux/bio.h>
 #include <linux/blkdev.h>
@@ -410,7 +411,7 @@ static int ocfs2_get_refcount_block(struct inode *inode, u64 *ref_blkno)
                goto out;
        }
 
-       BUG_ON(!(OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
+       BUG_ON(!ocfs2_is_refcount_inode(inode));
 
        di = (struct ocfs2_dinode *)di_bh->b_data;
        *ref_blkno = le64_to_cpu(di->i_refcount_loc);
@@ -570,7 +571,7 @@ static int ocfs2_create_refcount_tree(struct inode *inode,
        u32 num_got;
        u64 suballoc_loc, first_blkno;
 
-       BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL);
+       BUG_ON(ocfs2_is_refcount_inode(inode));
 
        trace_ocfs2_create_refcount_tree(
                (unsigned long long)OCFS2_I(inode)->ip_blkno);
@@ -708,7 +709,7 @@ static int ocfs2_set_refcount_tree(struct inode *inode,
        struct ocfs2_refcount_block *rb;
        struct ocfs2_refcount_tree *ref_tree;
 
-       BUG_ON(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL);
+       BUG_ON(ocfs2_is_refcount_inode(inode));
 
        ret = ocfs2_lock_refcount_tree(osb, refcount_loc, 1,
                                       &ref_tree, &ref_root_bh);
@@ -775,7 +776,7 @@ int ocfs2_remove_refcount_tree(struct inode *inode, struct buffer_head *di_bh)
        u64 blk = 0, bg_blkno = 0, ref_blkno = le64_to_cpu(di->i_refcount_loc);
        u16 bit = 0;
 
-       if (!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL))
+       if (!ocfs2_is_refcount_inode(inode))
                return 0;
 
        BUG_ON(!ref_blkno);
@@ -2299,11 +2300,10 @@ int ocfs2_decrease_refcount(struct inode *inode,
 {
        int ret;
        u64 ref_blkno;
-       struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct buffer_head *ref_root_bh = NULL;
        struct ocfs2_refcount_tree *tree;
 
-       BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
+       BUG_ON(!ocfs2_is_refcount_inode(inode));
 
        ret = ocfs2_get_refcount_block(inode, &ref_blkno);
        if (ret) {
@@ -2533,7 +2533,6 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
                                          int *ref_blocks)
 {
        int ret;
-       struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct buffer_head *ref_root_bh = NULL;
        struct ocfs2_refcount_tree *tree;
        u64 start_cpos = ocfs2_blocks_to_clusters(inode->i_sb, phys_blkno);
@@ -2544,7 +2543,7 @@ int ocfs2_prepare_refcount_change_for_del(struct inode *inode,
                goto out;
        }
 
-       BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
+       BUG_ON(!ocfs2_is_refcount_inode(inode));
 
        ret = ocfs2_get_refcount_tree(OCFS2_SB(inode->i_sb),
                                      refcount_loc, &tree);
@@ -3412,14 +3411,13 @@ static int ocfs2_refcount_cow_hunk(struct inode *inode,
 {
        int ret;
        u32 cow_start = 0, cow_len = 0;
-       struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_dinode *di = (struct ocfs2_dinode *)di_bh->b_data;
        struct buffer_head *ref_root_bh = NULL;
        struct ocfs2_refcount_tree *ref_tree;
        struct ocfs2_cow_context *context = NULL;
 
-       BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
+       BUG_ON(!ocfs2_is_refcount_inode(inode));
 
        ret = ocfs2_refcount_cal_cow_clusters(inode, &di->id2.i_list,
                                              cpos, write_len, max_cpos,
@@ -3629,11 +3627,10 @@ int ocfs2_refcount_cow_xattr(struct inode *inode,
 {
        int ret;
        struct ocfs2_xattr_value_root *xv = vb->vb_xv;
-       struct ocfs2_inode_info *oi = OCFS2_I(inode);
        struct ocfs2_cow_context *context = NULL;
        u32 cow_start, cow_len;
 
-       BUG_ON(!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL));
+       BUG_ON(!ocfs2_is_refcount_inode(inode));
 
        ret = ocfs2_refcount_cal_cow_clusters(inode, &xv->xr_list,
                                              cpos, write_len, UINT_MAX,
@@ -3696,6 +3693,9 @@ int ocfs2_add_refcount_flag(struct inode *inode,
        struct ocfs2_super *osb = OCFS2_SB(inode->i_sb);
        struct ocfs2_alloc_context *meta_ac = NULL;
 
+       /* We need to be able to handle at least an extent tree split. */
+       ref_blocks = ocfs2_extend_meta_needed(data_et->et_root_el);
+
        ret = ocfs2_calc_refcount_meta_credits(inode->i_sb,
                                               ref_ci, ref_root_bh,
                                               p_cluster, num_clusters,
@@ -3807,7 +3807,7 @@ static int ocfs2_attach_refcount_tree(struct inode *inode,
 
        ocfs2_init_dealloc_ctxt(&dealloc);
 
-       if (!(oi->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL)) {
+       if (!ocfs2_is_refcount_inode(inode)) {
                ret = ocfs2_create_refcount_tree(inode, di_bh);
                if (ret) {
                        mlog_errno(ret);
@@ -3934,6 +3934,13 @@ static int ocfs2_add_refcounted_extent(struct inode *inode,
        ret = ocfs2_increase_refcount(handle, ref_ci, ref_root_bh,
                                      p_cluster, num_clusters,
                                      meta_ac, dealloc);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+       ret = dquot_alloc_space_nodirty(inode,
+               ocfs2_clusters_to_bytes(osb->sb, num_clusters));
        if (ret)
                mlog_errno(ret);
 
@@ -4442,3 +4449,434 @@ out:
 
        return error;
 }
+
+/* Update destination inode size, if necessary. */
+static int ocfs2_reflink_update_dest(struct inode *dest,
+                                    struct buffer_head *d_bh,
+                                    loff_t newlen)
+{
+       handle_t *handle;
+       int ret;
+
+       dest->i_blocks = ocfs2_inode_sector_count(dest);
+
+       if (newlen <= i_size_read(dest))
+               return 0;
+
+       handle = ocfs2_start_trans(OCFS2_SB(dest->i_sb),
+                                  OCFS2_INODE_UPDATE_CREDITS);
+       if (IS_ERR(handle)) {
+               ret = PTR_ERR(handle);
+               mlog_errno(ret);
+               return ret;
+       }
+
+       /* Extend i_size if needed. */
+       spin_lock(&OCFS2_I(dest)->ip_lock);
+       if (newlen > i_size_read(dest))
+               i_size_write(dest, newlen);
+       spin_unlock(&OCFS2_I(dest)->ip_lock);
+       dest->i_ctime = dest->i_mtime = current_time(dest);
+
+       ret = ocfs2_mark_inode_dirty(handle, dest, d_bh);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_commit;
+       }
+
+out_commit:
+       ocfs2_commit_trans(OCFS2_SB(dest->i_sb), handle);
+       return ret;
+}
+
+/* Remap the range pos_in:len in s_inode to pos_out:len in t_inode. */
+static int ocfs2_reflink_remap_extent(struct inode *s_inode,
+                                     struct buffer_head *s_bh,
+                                     loff_t pos_in,
+                                     struct inode *t_inode,
+                                     struct buffer_head *t_bh,
+                                     loff_t pos_out,
+                                     loff_t len,
+                                     struct ocfs2_cached_dealloc_ctxt *dealloc)
+{
+       struct ocfs2_extent_tree s_et;
+       struct ocfs2_extent_tree t_et;
+       struct ocfs2_dinode *dis;
+       struct buffer_head *ref_root_bh = NULL;
+       struct ocfs2_refcount_tree *ref_tree;
+       struct ocfs2_super *osb;
+       loff_t pstart, plen;
+       u32 p_cluster, num_clusters, slast, spos, tpos;
+       unsigned int ext_flags;
+       int ret = 0;
+
+       osb = OCFS2_SB(s_inode->i_sb);
+       dis = (struct ocfs2_dinode *)s_bh->b_data;
+       ocfs2_init_dinode_extent_tree(&s_et, INODE_CACHE(s_inode), s_bh);
+       ocfs2_init_dinode_extent_tree(&t_et, INODE_CACHE(t_inode), t_bh);
+
+       spos = ocfs2_bytes_to_clusters(s_inode->i_sb, pos_in);
+       tpos = ocfs2_bytes_to_clusters(t_inode->i_sb, pos_out);
+       slast = ocfs2_clusters_for_bytes(s_inode->i_sb, pos_in + len);
+
+       while (spos < slast) {
+               if (fatal_signal_pending(current)) {
+                       ret = -EINTR;
+                       goto out;
+               }
+
+               /* Look up the extent. */
+               ret = ocfs2_get_clusters(s_inode, spos, &p_cluster,
+                                        &num_clusters, &ext_flags);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               num_clusters = min_t(u32, num_clusters, slast - spos);
+
+               /* Punch out the dest range. */
+               pstart = ocfs2_clusters_to_bytes(t_inode->i_sb, tpos);
+               plen = ocfs2_clusters_to_bytes(t_inode->i_sb, num_clusters);
+               ret = ocfs2_remove_inode_range(t_inode, t_bh, pstart, plen);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               if (p_cluster == 0)
+                       goto next_loop;
+
+               /* Lock the refcount btree... */
+               ret = ocfs2_lock_refcount_tree(osb,
+                                              le64_to_cpu(dis->i_refcount_loc),
+                                              1, &ref_tree, &ref_root_bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+
+               /* Mark s_inode's extent as refcounted. */
+               if (!(ext_flags & OCFS2_EXT_REFCOUNTED)) {
+                       ret = ocfs2_add_refcount_flag(s_inode, &s_et,
+                                                     &ref_tree->rf_ci,
+                                                     ref_root_bh, spos,
+                                                     p_cluster, num_clusters,
+                                                     dealloc, NULL);
+                       if (ret) {
+                               mlog_errno(ret);
+                               goto out_unlock_refcount;
+                       }
+               }
+
+               /* Map in the new extent. */
+               ext_flags |= OCFS2_EXT_REFCOUNTED;
+               ret = ocfs2_add_refcounted_extent(t_inode, &t_et,
+                                                 &ref_tree->rf_ci,
+                                                 ref_root_bh,
+                                                 tpos, p_cluster,
+                                                 num_clusters,
+                                                 ext_flags,
+                                                 dealloc);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out_unlock_refcount;
+               }
+
+               ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
+               brelse(ref_root_bh);
+next_loop:
+               spos += num_clusters;
+               tpos += num_clusters;
+       }
+
+out:
+       return ret;
+out_unlock_refcount:
+       ocfs2_unlock_refcount_tree(osb, ref_tree, 1);
+       brelse(ref_root_bh);
+       return ret;
+}
+
+/* Set up refcount tree and remap s_inode to t_inode. */
+static int ocfs2_reflink_remap_blocks(struct inode *s_inode,
+                                     struct buffer_head *s_bh,
+                                     loff_t pos_in,
+                                     struct inode *t_inode,
+                                     struct buffer_head *t_bh,
+                                     loff_t pos_out,
+                                     loff_t len)
+{
+       struct ocfs2_cached_dealloc_ctxt dealloc;
+       struct ocfs2_super *osb;
+       struct ocfs2_dinode *dis;
+       struct ocfs2_dinode *dit;
+       int ret;
+
+       osb = OCFS2_SB(s_inode->i_sb);
+       dis = (struct ocfs2_dinode *)s_bh->b_data;
+       dit = (struct ocfs2_dinode *)t_bh->b_data;
+       ocfs2_init_dealloc_ctxt(&dealloc);
+
+       /*
+        * If we're reflinking the entire file and the source is inline
+        * data, just copy the contents.
+        */
+       if (pos_in == pos_out && pos_in == 0 && len == i_size_read(s_inode) &&
+           i_size_read(t_inode) <= len &&
+           (OCFS2_I(s_inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL)) {
+               ret = ocfs2_duplicate_inline_data(s_inode, s_bh, t_inode, t_bh);
+               if (ret)
+                       mlog_errno(ret);
+               goto out;
+       }
+
+       /*
+        * If both inodes belong to two different refcount groups then
+        * forget it because we don't know how (or want) to go merging
+        * refcount trees.
+        */
+       ret = -EOPNOTSUPP;
+       if (ocfs2_is_refcount_inode(s_inode) &&
+           ocfs2_is_refcount_inode(t_inode) &&
+           le64_to_cpu(dis->i_refcount_loc) !=
+           le64_to_cpu(dit->i_refcount_loc))
+               goto out;
+
+       /* Neither inode has a refcount tree.  Add one to s_inode. */
+       if (!ocfs2_is_refcount_inode(s_inode) &&
+           !ocfs2_is_refcount_inode(t_inode)) {
+               ret = ocfs2_create_refcount_tree(s_inode, s_bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       /* Ensure that both inodes end up with the same refcount tree. */
+       if (!ocfs2_is_refcount_inode(s_inode)) {
+               ret = ocfs2_set_refcount_tree(s_inode, s_bh,
+                                             le64_to_cpu(dit->i_refcount_loc));
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+       if (!ocfs2_is_refcount_inode(t_inode)) {
+               ret = ocfs2_set_refcount_tree(t_inode, t_bh,
+                                             le64_to_cpu(dis->i_refcount_loc));
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       /* Turn off inline data in the dest file. */
+       if (OCFS2_I(t_inode)->ip_dyn_features & OCFS2_INLINE_DATA_FL) {
+               ret = ocfs2_convert_inline_data_to_extents(t_inode, t_bh);
+               if (ret) {
+                       mlog_errno(ret);
+                       goto out;
+               }
+       }
+
+       /* Actually remap extents now. */
+       ret = ocfs2_reflink_remap_extent(s_inode, s_bh, pos_in, t_inode, t_bh,
+                                        pos_out, len, &dealloc);
+       if (ret) {
+               mlog_errno(ret);
+               goto out;
+       }
+
+out:
+       if (ocfs2_dealloc_has_cluster(&dealloc)) {
+               ocfs2_schedule_truncate_log_flush(osb, 1);
+               ocfs2_run_deallocs(osb, &dealloc);
+       }
+
+       return ret;
+}
+
+/* Lock an inode and grab a bh pointing to the inode. */
+static int ocfs2_reflink_inodes_lock(struct inode *s_inode,
+                                    struct buffer_head **bh1,
+                                    struct inode *t_inode,
+                                    struct buffer_head **bh2)
+{
+       struct inode *inode1;
+       struct inode *inode2;
+       struct ocfs2_inode_info *oi1;
+       struct ocfs2_inode_info *oi2;
+       bool same_inode = (s_inode == t_inode);
+       int status;
+
+       /* First grab the VFS and rw locks. */
+       lock_two_nondirectories(s_inode, t_inode);
+       inode1 = s_inode;
+       inode2 = t_inode;
+       if (inode1->i_ino > inode2->i_ino)
+               swap(inode1, inode2);
+
+       status = ocfs2_rw_lock(inode1, 1);
+       if (status) {
+               mlog_errno(status);
+               goto out_i1;
+       }
+       if (!same_inode) {
+               status = ocfs2_rw_lock(inode2, 1);
+               if (status) {
+                       mlog_errno(status);
+                       goto out_i2;
+               }
+       }
+
+       /* Now go for the cluster locks */
+       oi1 = OCFS2_I(inode1);
+       oi2 = OCFS2_I(inode2);
+
+       trace_ocfs2_double_lock((unsigned long long)oi1->ip_blkno,
+                               (unsigned long long)oi2->ip_blkno);
+
+       if (*bh1)
+               *bh1 = NULL;
+       if (*bh2)
+               *bh2 = NULL;
+
+       /* We always want to lock the one with the lower lockid first. */
+       if (oi1->ip_blkno > oi2->ip_blkno)
+               mlog_errno(-ENOLCK);
+
+       /* lock id1 */
+       status = ocfs2_inode_lock_nested(inode1, bh1, 1, OI_LS_REFLINK_TARGET);
+       if (status < 0) {
+               if (status != -ENOENT)
+                       mlog_errno(status);
+               goto out_rw2;
+       }
+
+       /* lock id2 */
+       if (!same_inode) {
+               status = ocfs2_inode_lock_nested(inode2, bh2, 1,
+                                                OI_LS_REFLINK_TARGET);
+               if (status < 0) {
+                       if (status != -ENOENT)
+                               mlog_errno(status);
+                       goto out_cl1;
+               }
+       } else
+               *bh2 = *bh1;
+
+       trace_ocfs2_double_lock_end(
+                       (unsigned long long)OCFS2_I(inode1)->ip_blkno,
+                       (unsigned long long)OCFS2_I(inode2)->ip_blkno);
+
+       return 0;
+
+out_cl1:
+       ocfs2_inode_unlock(inode1, 1);
+       brelse(*bh1);
+       *bh1 = NULL;
+out_rw2:
+       ocfs2_rw_unlock(inode2, 1);
+out_i2:
+       ocfs2_rw_unlock(inode1, 1);
+out_i1:
+       unlock_two_nondirectories(s_inode, t_inode);
+       return status;
+}
+
+/* Unlock both inodes and release buffers. */
+static void ocfs2_reflink_inodes_unlock(struct inode *s_inode,
+                                       struct buffer_head *s_bh,
+                                       struct inode *t_inode,
+                                       struct buffer_head *t_bh)
+{
+       ocfs2_inode_unlock(s_inode, 1);
+       ocfs2_rw_unlock(s_inode, 1);
+       brelse(s_bh);
+       if (s_inode != t_inode) {
+               ocfs2_inode_unlock(t_inode, 1);
+               ocfs2_rw_unlock(t_inode, 1);
+               brelse(t_bh);
+       }
+       unlock_two_nondirectories(s_inode, t_inode);
+}
+
+/* Link a range of blocks from one file to another. */
+int ocfs2_reflink_remap_range(struct file *file_in,
+                             loff_t pos_in,
+                             struct file *file_out,
+                             loff_t pos_out,
+                             u64 len,
+                             bool is_dedupe)
+{
+       struct inode *inode_in = file_inode(file_in);
+       struct inode *inode_out = file_inode(file_out);
+       struct ocfs2_super *osb = OCFS2_SB(inode_in->i_sb);
+       struct buffer_head *in_bh = NULL, *out_bh = NULL;
+       bool same_inode = (inode_in == inode_out);
+       ssize_t ret;
+
+       if (!ocfs2_refcount_tree(osb))
+               return -EOPNOTSUPP;
+       if (ocfs2_is_hard_readonly(osb) || ocfs2_is_soft_readonly(osb))
+               return -EROFS;
+
+       /* Lock both files against IO */
+       ret = ocfs2_reflink_inodes_lock(inode_in, &in_bh, inode_out, &out_bh);
+       if (ret)
+               return ret;
+
+       /* Check file eligibility and prepare for block sharing. */
+       ret = -EINVAL;
+       if ((OCFS2_I(inode_in)->ip_flags & OCFS2_INODE_SYSTEM_FILE) ||
+           (OCFS2_I(inode_out)->ip_flags & OCFS2_INODE_SYSTEM_FILE))
+               goto out_unlock;
+
+       ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
+                       &len, is_dedupe);
+       if (ret || len == 0)
+               goto out_unlock;
+
+       /* Lock out changes to the allocation maps and remap. */
+       down_write(&OCFS2_I(inode_in)->ip_alloc_sem);
+       if (!same_inode)
+               down_write_nested(&OCFS2_I(inode_out)->ip_alloc_sem,
+                                 SINGLE_DEPTH_NESTING);
+
+       ret = ocfs2_reflink_remap_blocks(inode_in, in_bh, pos_in, inode_out,
+                                        out_bh, pos_out, len);
+
+       /* Zap any page cache for the destination file's range. */
+       if (!ret)
+               truncate_inode_pages_range(&inode_out->i_data, pos_out,
+                                          PAGE_ALIGN(pos_out + len) - 1);
+
+       up_write(&OCFS2_I(inode_in)->ip_alloc_sem);
+       if (!same_inode)
+               up_write(&OCFS2_I(inode_out)->ip_alloc_sem);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_unlock;
+       }
+
+       /*
+        * Empty the extent map so that we may get the right extent
+        * record from the disk.
+        */
+       ocfs2_extent_map_trunc(inode_in, 0);
+       ocfs2_extent_map_trunc(inode_out, 0);
+
+       ret = ocfs2_reflink_update_dest(inode_out, out_bh, pos_out + len);
+       if (ret) {
+               mlog_errno(ret);
+               goto out_unlock;
+       }
+
+       ocfs2_reflink_inodes_unlock(inode_in, in_bh, inode_out, out_bh);
+       return 0;
+
+out_unlock:
+       ocfs2_reflink_inodes_unlock(inode_in, in_bh, inode_out, out_bh);
+       return ret;
+}
index 6422bbc..4af55bf 100644 (file)
@@ -115,4 +115,11 @@ int ocfs2_reflink_ioctl(struct inode *inode,
                        const char __user *oldname,
                        const char __user *newname,
                        bool preserve);
+int ocfs2_reflink_remap_range(struct file *file_in,
+                             loff_t pos_in,
+                             struct file *file_out,
+                             loff_t pos_out,
+                             u64 len,
+                             bool is_dedupe);
+
 #endif /* OCFS2_REFCOUNTTREE_H */
index cb157a3..3c5384d 100644 (file)
@@ -2577,7 +2577,7 @@ int ocfs2_xattr_remove(struct inode *inode, struct buffer_head *di_bh)
        if (!(oi->ip_dyn_features & OCFS2_HAS_XATTR_FL))
                return 0;
 
-       if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL) {
+       if (ocfs2_is_refcount_inode(inode)) {
                ret = ocfs2_lock_refcount_tree(OCFS2_SB(inode->i_sb),
                                               le64_to_cpu(di->i_refcount_loc),
                                               1, &ref_tree, &ref_root_bh);
@@ -3608,7 +3608,7 @@ int ocfs2_xattr_set(struct inode *inode,
        }
 
        /* Check whether the value is refcounted and do some preparation. */
-       if (OCFS2_I(inode)->ip_dyn_features & OCFS2_HAS_REFCOUNT_FL &&
+       if (ocfs2_is_refcount_inode(inode) &&
            (!xis.not_found || !xbs.not_found)) {
                ret = ocfs2_prepare_refcount_xattr(inode, di, &xi,
                                                   &xis, &xbs, &ref_tree,
index edd46a0..0e10085 100644 (file)
@@ -328,11 +328,11 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
        if (!real)
                goto bug;
 
+       /* Handle recursion */
+       real = d_real(real, inode, open_flags);
+
        if (!inode || inode == d_inode(real))
                return real;
-
-       /* Handle recursion */
-       return d_real(real, inode, open_flags);
 bug:
        WARN(1, "ovl_d_real(%pd4, %s:%lu): real dentry not found\n", dentry,
             inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
index 190e0d3..dbf3f7f 100644 (file)
@@ -1542,20 +1542,37 @@ ssize_t vfs_copy_file_range(struct file *file_in, loff_t pos_in,
        if (ret)
                return ret;
 
-       ret = -EOPNOTSUPP;
-       if (file_out->f_op->copy_file_range)
+       /*
+        * Try cloning first, this is supported by more file systems, and
+        * more efficient if both clone and copy are supported (e.g. NFS).
+        */
+       if (file_in->f_op->clone_file_range) {
+               ret = file_in->f_op->clone_file_range(file_in, pos_in,
+                               file_out, pos_out, len);
+               if (ret == 0) {
+                       ret = len;
+                       goto done;
+               }
+       }
+
+       if (file_out->f_op->copy_file_range) {
                ret = file_out->f_op->copy_file_range(file_in, pos_in, file_out,
                                                      pos_out, len, flags);
-       if (ret == -EOPNOTSUPP)
-               ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
-                               len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
+               if (ret != -EOPNOTSUPP)
+                       goto done;
+       }
+
+       ret = do_splice_direct(file_in, &pos_in, file_out, &pos_out,
+                       len > MAX_RW_COUNT ? MAX_RW_COUNT : len, 0);
 
+done:
        if (ret > 0) {
                fsnotify_access(file_in);
                add_rchar(current, ret);
                fsnotify_modify(file_out);
                add_wchar(current, ret);
        }
+
        inc_syscr(current);
        inc_syscw(current);
 
@@ -1650,6 +1667,114 @@ static int clone_verify_area(struct file *file, loff_t pos, u64 len, bool write)
        return security_file_permission(file, write ? MAY_WRITE : MAY_READ);
 }
 
+/*
+ * Check that the two inodes are eligible for cloning, the ranges make
+ * sense, and then flush all dirty data.  Caller must ensure that the
+ * inodes have been locked against any other modifications.
+ */
+int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
+                              struct inode *inode_out, loff_t pos_out,
+                              u64 *len, bool is_dedupe)
+{
+       loff_t bs = inode_out->i_sb->s_blocksize;
+       loff_t blen;
+       loff_t isize;
+       bool same_inode = (inode_in == inode_out);
+       int ret;
+
+       /* Don't touch certain kinds of inodes */
+       if (IS_IMMUTABLE(inode_out))
+               return -EPERM;
+
+       if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out))
+               return -ETXTBSY;
+
+       /* Don't reflink dirs, pipes, sockets... */
+       if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
+               return -EISDIR;
+       if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
+               return -EINVAL;
+
+       /* Are we going all the way to the end? */
+       isize = i_size_read(inode_in);
+       if (isize == 0) {
+               *len = 0;
+               return 0;
+       }
+
+       /* Zero length dedupe exits immediately; reflink goes to EOF. */
+       if (*len == 0) {
+               if (is_dedupe) {
+                       *len = 0;
+                       return 0;
+               }
+               *len = isize - pos_in;
+       }
+
+       /* Ensure offsets don't wrap and the input is inside i_size */
+       if (pos_in + *len < pos_in || pos_out + *len < pos_out ||
+           pos_in + *len > isize)
+               return -EINVAL;
+
+       /* Don't allow dedupe past EOF in the dest file */
+       if (is_dedupe) {
+               loff_t  disize;
+
+               disize = i_size_read(inode_out);
+               if (pos_out >= disize || pos_out + *len > disize)
+                       return -EINVAL;
+       }
+
+       /* If we're linking to EOF, continue to the block boundary. */
+       if (pos_in + *len == isize)
+               blen = ALIGN(isize, bs) - pos_in;
+       else
+               blen = *len;
+
+       /* Only reflink if we're aligned to block boundaries */
+       if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_in + blen, bs) ||
+           !IS_ALIGNED(pos_out, bs) || !IS_ALIGNED(pos_out + blen, bs))
+               return -EINVAL;
+
+       /* Don't allow overlapped reflink within the same file */
+       if (same_inode) {
+               if (pos_out + blen > pos_in && pos_out < pos_in + blen)
+                       return -EINVAL;
+       }
+
+       /* Wait for the completion of any pending IOs on both files */
+       inode_dio_wait(inode_in);
+       if (!same_inode)
+               inode_dio_wait(inode_out);
+
+       ret = filemap_write_and_wait_range(inode_in->i_mapping,
+                       pos_in, pos_in + *len - 1);
+       if (ret)
+               return ret;
+
+       ret = filemap_write_and_wait_range(inode_out->i_mapping,
+                       pos_out, pos_out + *len - 1);
+       if (ret)
+               return ret;
+
+       /*
+        * Check that the extents are the same.
+        */
+       if (is_dedupe) {
+               bool            is_same = false;
+
+               ret = vfs_dedupe_file_range_compare(inode_in, pos_in,
+                               inode_out, pos_out, *len, &is_same);
+               if (ret)
+                       return ret;
+               if (!is_same)
+                       return -EBADE;
+       }
+
+       return 0;
+}
+EXPORT_SYMBOL(vfs_clone_file_prep_inodes);
+
 int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
                struct file *file_out, loff_t pos_out, u64 len)
 {
@@ -1701,6 +1826,102 @@ int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
 }
 EXPORT_SYMBOL(vfs_clone_file_range);
 
+/*
+ * Read a page's worth of file data into the page cache.  Return the page
+ * locked.
+ */
+static struct page *vfs_dedupe_get_page(struct inode *inode, loff_t offset)
+{
+       struct address_space *mapping;
+       struct page *page;
+       pgoff_t n;
+
+       n = offset >> PAGE_SHIFT;
+       mapping = inode->i_mapping;
+       page = read_mapping_page(mapping, n, NULL);
+       if (IS_ERR(page))
+               return page;
+       if (!PageUptodate(page)) {
+               put_page(page);
+               return ERR_PTR(-EIO);
+       }
+       lock_page(page);
+       return page;
+}
+
+/*
+ * Compare extents of two files to see if they are the same.
+ * Caller must have locked both inodes to prevent write races.
+ */
+int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
+                                 struct inode *dest, loff_t destoff,
+                                 loff_t len, bool *is_same)
+{
+       loff_t src_poff;
+       loff_t dest_poff;
+       void *src_addr;
+       void *dest_addr;
+       struct page *src_page;
+       struct page *dest_page;
+       loff_t cmp_len;
+       bool same;
+       int error;
+
+       error = -EINVAL;
+       same = true;
+       while (len) {
+               src_poff = srcoff & (PAGE_SIZE - 1);
+               dest_poff = destoff & (PAGE_SIZE - 1);
+               cmp_len = min(PAGE_SIZE - src_poff,
+                             PAGE_SIZE - dest_poff);
+               cmp_len = min(cmp_len, len);
+               if (cmp_len <= 0)
+                       goto out_error;
+
+               src_page = vfs_dedupe_get_page(src, srcoff);
+               if (IS_ERR(src_page)) {
+                       error = PTR_ERR(src_page);
+                       goto out_error;
+               }
+               dest_page = vfs_dedupe_get_page(dest, destoff);
+               if (IS_ERR(dest_page)) {
+                       error = PTR_ERR(dest_page);
+                       unlock_page(src_page);
+                       put_page(src_page);
+                       goto out_error;
+               }
+               src_addr = kmap_atomic(src_page);
+               dest_addr = kmap_atomic(dest_page);
+
+               flush_dcache_page(src_page);
+               flush_dcache_page(dest_page);
+
+               if (memcmp(src_addr + src_poff, dest_addr + dest_poff, cmp_len))
+                       same = false;
+
+               kunmap_atomic(dest_addr);
+               kunmap_atomic(src_addr);
+               unlock_page(dest_page);
+               unlock_page(src_page);
+               put_page(dest_page);
+               put_page(src_page);
+
+               if (!same)
+                       break;
+
+               srcoff += cmp_len;
+               destoff += cmp_len;
+               len -= cmp_len;
+       }
+
+       *is_same = same;
+       return 0;
+
+out_error:
+       return error;
+}
+EXPORT_SYMBOL(vfs_dedupe_file_range_compare);
+
 int vfs_dedupe_file_range(struct file *file, struct file_dedupe_range *same)
 {
        struct file_dedupe_range_info *info;
index 6e4f7f9..86ecc9b 100644 (file)
@@ -909,24 +909,6 @@ out_unlock:
        return error;
 }
 
-STATIC ssize_t
-xfs_file_copy_range(
-       struct file     *file_in,
-       loff_t          pos_in,
-       struct file     *file_out,
-       loff_t          pos_out,
-       size_t          len,
-       unsigned int    flags)
-{
-       int             error;
-
-       error = xfs_reflink_remap_range(file_in, pos_in, file_out, pos_out,
-                                    len, false);
-       if (error)
-               return error;
-       return len;
-}
-
 STATIC int
 xfs_file_clone_range(
        struct file     *file_in,
@@ -1625,7 +1607,6 @@ const struct file_operations xfs_file_operations = {
        .fsync          = xfs_file_fsync,
        .get_unmapped_area = thp_get_unmapped_area,
        .fallocate      = xfs_file_fallocate,
-       .copy_file_range = xfs_file_copy_range,
        .clone_file_range = xfs_file_clone_range,
        .dedupe_file_range = xfs_file_dedupe_range,
 };
index a279b4e..95d6828 100644 (file)
@@ -1165,111 +1165,6 @@ err:
 }
 
 /*
- * Read a page's worth of file data into the page cache.  Return the page
- * locked.
- */
-static struct page *
-xfs_get_page(
-       struct inode    *inode,
-       xfs_off_t       offset)
-{
-       struct address_space    *mapping;
-       struct page             *page;
-       pgoff_t                 n;
-
-       n = offset >> PAGE_SHIFT;
-       mapping = inode->i_mapping;
-       page = read_mapping_page(mapping, n, NULL);
-       if (IS_ERR(page))
-               return page;
-       if (!PageUptodate(page)) {
-               put_page(page);
-               return ERR_PTR(-EIO);
-       }
-       lock_page(page);
-       return page;
-}
-
-/*
- * Compare extents of two files to see if they are the same.
- */
-static int
-xfs_compare_extents(
-       struct inode    *src,
-       xfs_off_t       srcoff,
-       struct inode    *dest,
-       xfs_off_t       destoff,
-       xfs_off_t       len,
-       bool            *is_same)
-{
-       xfs_off_t       src_poff;
-       xfs_off_t       dest_poff;
-       void            *src_addr;
-       void            *dest_addr;
-       struct page     *src_page;
-       struct page     *dest_page;
-       xfs_off_t       cmp_len;
-       bool            same;
-       int             error;
-
-       error = -EINVAL;
-       same = true;
-       while (len) {
-               src_poff = srcoff & (PAGE_SIZE - 1);
-               dest_poff = destoff & (PAGE_SIZE - 1);
-               cmp_len = min(PAGE_SIZE - src_poff,
-                             PAGE_SIZE - dest_poff);
-               cmp_len = min(cmp_len, len);
-               ASSERT(cmp_len > 0);
-
-               trace_xfs_reflink_compare_extents(XFS_I(src), srcoff, cmp_len,
-                               XFS_I(dest), destoff);
-
-               src_page = xfs_get_page(src, srcoff);
-               if (IS_ERR(src_page)) {
-                       error = PTR_ERR(src_page);
-                       goto out_error;
-               }
-               dest_page = xfs_get_page(dest, destoff);
-               if (IS_ERR(dest_page)) {
-                       error = PTR_ERR(dest_page);
-                       unlock_page(src_page);
-                       put_page(src_page);
-                       goto out_error;
-               }
-               src_addr = kmap_atomic(src_page);
-               dest_addr = kmap_atomic(dest_page);
-
-               flush_dcache_page(src_page);
-               flush_dcache_page(dest_page);
-
-               if (memcmp(src_addr + src_poff, dest_addr + dest_poff, cmp_len))
-                       same = false;
-
-               kunmap_atomic(dest_addr);
-               kunmap_atomic(src_addr);
-               unlock_page(dest_page);
-               unlock_page(src_page);
-               put_page(dest_page);
-               put_page(src_page);
-
-               if (!same)
-                       break;
-
-               srcoff += cmp_len;
-               destoff += cmp_len;
-               len -= cmp_len;
-       }
-
-       *is_same = same;
-       return 0;
-
-out_error:
-       trace_xfs_reflink_compare_extents_error(XFS_I(dest), error, _RET_IP_);
-       return error;
-}
-
-/*
  * Link a range of blocks from one file to another.
  */
 int
@@ -1286,14 +1181,11 @@ xfs_reflink_remap_range(
        struct inode            *inode_out = file_inode(file_out);
        struct xfs_inode        *dest = XFS_I(inode_out);
        struct xfs_mount        *mp = src->i_mount;
-       loff_t                  bs = inode_out->i_sb->s_blocksize;
        bool                    same_inode = (inode_in == inode_out);
        xfs_fileoff_t           sfsbno, dfsbno;
        xfs_filblks_t           fsblen;
        xfs_extlen_t            cowextsize;
-       loff_t                  isize;
        ssize_t                 ret;
-       loff_t                  blen;
 
        if (!xfs_sb_version_hasreflink(&mp->m_sb))
                return -EOPNOTSUPP;
@@ -1310,26 +1202,8 @@ xfs_reflink_remap_range(
                xfs_lock_two_inodes(src, dest, XFS_MMAPLOCK_EXCL);
        }
 
-       /* Don't touch certain kinds of inodes */
-       ret = -EPERM;
-       if (IS_IMMUTABLE(inode_out))
-               goto out_unlock;
-
-       ret = -ETXTBSY;
-       if (IS_SWAPFILE(inode_in) || IS_SWAPFILE(inode_out))
-               goto out_unlock;
-
-
-       /* Don't reflink dirs, pipes, sockets... */
-       ret = -EISDIR;
-       if (S_ISDIR(inode_in->i_mode) || S_ISDIR(inode_out->i_mode))
-               goto out_unlock;
+       /* Check file eligibility and prepare for block sharing. */
        ret = -EINVAL;
-       if (S_ISFIFO(inode_in->i_mode) || S_ISFIFO(inode_out->i_mode))
-               goto out_unlock;
-       if (!S_ISREG(inode_in->i_mode) || !S_ISREG(inode_out->i_mode))
-               goto out_unlock;
-
        /* Don't reflink realtime inodes */
        if (XFS_IS_REALTIME_INODE(src) || XFS_IS_REALTIME_INODE(dest))
                goto out_unlock;
@@ -1338,91 +1212,18 @@ xfs_reflink_remap_range(
        if (IS_DAX(inode_in) || IS_DAX(inode_out))
                goto out_unlock;
 
-       /* Are we going all the way to the end? */
-       isize = i_size_read(inode_in);
-       if (isize == 0) {
-               ret = 0;
-               goto out_unlock;
-       }
-
-       if (len == 0)
-               len = isize - pos_in;
-
-       /* Ensure offsets don't wrap and the input is inside i_size */
-       if (pos_in + len < pos_in || pos_out + len < pos_out ||
-           pos_in + len > isize)
-               goto out_unlock;
-
-       /* Don't allow dedupe past EOF in the dest file */
-       if (is_dedupe) {
-               loff_t  disize;
-
-               disize = i_size_read(inode_out);
-               if (pos_out >= disize || pos_out + len > disize)
-                       goto out_unlock;
-       }
-
-       /* If we're linking to EOF, continue to the block boundary. */
-       if (pos_in + len == isize)
-               blen = ALIGN(isize, bs) - pos_in;
-       else
-               blen = len;
-
-       /* Only reflink if we're aligned to block boundaries */
-       if (!IS_ALIGNED(pos_in, bs) || !IS_ALIGNED(pos_in + blen, bs) ||
-           !IS_ALIGNED(pos_out, bs) || !IS_ALIGNED(pos_out + blen, bs))
-               goto out_unlock;
-
-       /* Don't allow overlapped reflink within the same file */
-       if (same_inode) {
-               if (pos_out + blen > pos_in && pos_out < pos_in + blen)
-                       goto out_unlock;
-       }
-
-       /* Wait for the completion of any pending IOs on both files */
-       inode_dio_wait(inode_in);
-       if (!same_inode)
-               inode_dio_wait(inode_out);
-
-       ret = filemap_write_and_wait_range(inode_in->i_mapping,
-                       pos_in, pos_in + len - 1);
-       if (ret)
-               goto out_unlock;
-
-       ret = filemap_write_and_wait_range(inode_out->i_mapping,
-                       pos_out, pos_out + len - 1);
-       if (ret)
+       ret = vfs_clone_file_prep_inodes(inode_in, pos_in, inode_out, pos_out,
+                       &len, is_dedupe);
+       if (ret || len == 0)
                goto out_unlock;
 
        trace_xfs_reflink_remap_range(src, pos_in, len, dest, pos_out);
 
-       /*
-        * Check that the extents are the same.
-        */
-       if (is_dedupe) {
-               bool            is_same = false;
-
-               ret = xfs_compare_extents(inode_in, pos_in, inode_out, pos_out,
-                               len, &is_same);
-               if (ret)
-                       goto out_unlock;
-               if (!is_same) {
-                       ret = -EBADE;
-                       goto out_unlock;
-               }
-       }
-
+       /* Set flags and remap blocks. */
        ret = xfs_reflink_set_inode_flag(src, dest);
        if (ret)
                goto out_unlock;
 
-       /*
-        * Invalidate the page cache so that we can clear any CoW mappings
-        * in the destination file.
-        */
-       truncate_inode_pages_range(&inode_out->i_data, pos_out,
-                                  PAGE_ALIGN(pos_out + len) - 1);
-
        dfsbno = XFS_B_TO_FSBT(mp, pos_out);
        sfsbno = XFS_B_TO_FSBT(mp, pos_in);
        fsblen = XFS_B_TO_FSB(mp, len);
@@ -1431,6 +1232,10 @@ xfs_reflink_remap_range(
        if (ret)
                goto out_unlock;
 
+       /* Zap any page cache for the destination file's range. */
+       truncate_inode_pages_range(&inode_out->i_data, pos_out,
+                                  PAGE_ALIGN(pos_out + len) - 1);
+
        /*
         * Carry the cowextsize hint from src to dest if we're sharing the
         * entire source file to the entire destination file, the source file
index 63554e9..59a3b2f 100644 (file)
@@ -54,6 +54,7 @@ KSYM(__kstrtab_\name):
 KSYM(__kcrctab_\name):
        __put KSYM(__crc_\name)
        .weak KSYM(__crc_\name)
+       .set KSYM(__crc_\name), 0
        .previous
 #endif
 #endif
index 432f5c9..928e5ca 100644 (file)
 #endif
 #endif /* CONFIG_ARCH_USE_BUILTIN_BSWAP && !__CHECKER__ */
 
-#if GCC_VERSION >= 50000
+#if GCC_VERSION >= 70000
+#define KASAN_ABI_VERSION 5
+#elif GCC_VERSION >= 50000
 #define KASAN_ABI_VERSION 4
 #elif GCC_VERSION >= 40902
 #define KASAN_ABI_VERSION 3
index 0e177d3..087813f 100644 (file)
@@ -1778,8 +1778,14 @@ extern ssize_t vfs_writev(struct file *, const struct iovec __user *,
                unsigned long, loff_t *, int);
 extern ssize_t vfs_copy_file_range(struct file *, loff_t , struct file *,
                                   loff_t, size_t, unsigned int);
+extern int vfs_clone_file_prep_inodes(struct inode *inode_in, loff_t pos_in,
+                                     struct inode *inode_out, loff_t pos_out,
+                                     u64 *len, bool is_dedupe);
 extern int vfs_clone_file_range(struct file *file_in, loff_t pos_in,
                struct file *file_out, loff_t pos_out, u64 len);
+extern int vfs_dedupe_file_range_compare(struct inode *src, loff_t srcoff,
+                                        struct inode *dest, loff_t destoff,
+                                        loff_t len, bool *is_same);
 extern int vfs_dedupe_file_range(struct file *file,
                                 struct file_dedupe_range *same);
 
index 3be7abd..c9f3796 100644 (file)
@@ -476,7 +476,6 @@ enum {
 enum {
        MLX4_INTERFACE_STATE_UP         = 1 << 0,
        MLX4_INTERFACE_STATE_DELETION   = 1 << 1,
-       MLX4_INTERFACE_STATE_SHUTDOWN   = 1 << 2,
 };
 
 #define MSTR_SM_CHANGE_MASK (MLX4_EQ_PORT_INFO_MSTR_SM_SL_CHANGE_MASK | \
index 2ab2336..a58cca8 100644 (file)
@@ -29,6 +29,7 @@ struct phy_device *of_phy_attach(struct net_device *dev,
 extern struct mii_bus *of_mdio_find_bus(struct device_node *mdio_np);
 extern int of_mdio_parse_addr(struct device *dev, const struct device_node *np);
 extern int of_phy_register_fixed_link(struct device_node *np);
+extern void of_phy_deregister_fixed_link(struct device_node *np);
 extern bool of_phy_is_fixed_link(struct device_node *np);
 
 #else /* CONFIG_OF */
@@ -83,6 +84,9 @@ static inline int of_phy_register_fixed_link(struct device_node *np)
 {
        return -ENOSYS;
 }
+static inline void of_phy_deregister_fixed_link(struct device_node *np)
+{
+}
 static inline bool of_phy_is_fixed_link(struct device_node *np)
 {
        return false;
index dd15d39..7dbe914 100644 (file)
@@ -374,16 +374,13 @@ static inline struct page *read_mapping_page(struct address_space *mapping,
 }
 
 /*
- * Get the offset in PAGE_SIZE.
- * (TODO: hugepage should have ->index in PAGE_SIZE)
+ * Get index of the page with in radix-tree
+ * (TODO: remove once hugetlb pages will have ->index in PAGE_SIZE)
  */
-static inline pgoff_t page_to_pgoff(struct page *page)
+static inline pgoff_t page_to_index(struct page *page)
 {
        pgoff_t pgoff;
 
-       if (unlikely(PageHeadHuge(page)))
-               return page->index << compound_order(page);
-
        if (likely(!PageTransTail(page)))
                return page->index;
 
@@ -397,6 +394,18 @@ static inline pgoff_t page_to_pgoff(struct page *page)
 }
 
 /*
+ * Get the offset in PAGE_SIZE.
+ * (TODO: hugepage should have ->index in PAGE_SIZE)
+ */
+static inline pgoff_t page_to_pgoff(struct page *page)
+{
+       if (unlikely(PageHeadHuge(page)))
+               return page->index << compound_order(page);
+
+       return page_to_index(page);
+}
+
+/*
  * Return byte-offset into filesystem object for page.
  */
 static inline loff_t page_offset(struct page *page)
index 0e49f70..a38772a 100644 (file)
@@ -1928,6 +1928,20 @@ static inline int pci_pcie_type(const struct pci_dev *dev)
        return (pcie_caps_reg(dev) & PCI_EXP_FLAGS_TYPE) >> 4;
 }
 
+static inline struct pci_dev *pcie_find_root_port(struct pci_dev *dev)
+{
+       while (1) {
+               if (!pci_is_pcie(dev))
+                       break;
+               if (pci_pcie_type(dev) == PCI_EXP_TYPE_ROOT_PORT)
+                       return dev;
+               if (!dev->bus->self)
+                       break;
+               dev = dev->bus->self;
+       }
+       return NULL;
+}
+
 void pci_request_acs(void);
 bool pci_acs_enabled(struct pci_dev *pdev, u16 acs_flags);
 bool pci_acs_path_enabled(struct pci_dev *start,
index 8fed1cd..f11ca83 100644 (file)
@@ -970,6 +970,8 @@ int compat_ipv6_setsockopt(struct sock *sk, int level, int optname,
 int compat_ipv6_getsockopt(struct sock *sk, int level, int optname,
                           char __user *optval, int __user *optlen);
 
+int __ip6_datagram_connect(struct sock *sk, struct sockaddr *addr,
+                          int addr_len);
 int ip6_datagram_connect(struct sock *sk, struct sockaddr *addr, int addr_len);
 int ip6_datagram_connect_v6_only(struct sock *sk, struct sockaddr *addr,
                                 int addr_len);
index 5041805..d9d52c0 100644 (file)
@@ -100,6 +100,9 @@ struct nf_conn {
 
        possible_net_t ct_net;
 
+#if IS_ENABLED(CONFIG_NF_NAT)
+       struct rhlist_head nat_bysource;
+#endif
        /* all members below initialized via memset */
        u8 __nfct_init_offset[0];
 
@@ -117,9 +120,6 @@ struct nf_conn {
        /* Extensions */
        struct nf_ct_ext *ext;
 
-#if IS_ENABLED(CONFIG_NF_NAT)
-       struct rhash_head       nat_bysource;
-#endif
        /* Storage reserved for other modules, must be the last member */
        union nf_conntrack_proto proto;
 };
index d79d1e9..b02af0b 100644 (file)
@@ -313,7 +313,7 @@ void nft_unregister_set(struct nft_set_ops *ops);
  *     @size: maximum set size
  *     @nelems: number of elements
  *     @ndeact: number of deactivated elements queued for removal
- *     @timeout: default timeout value in msecs
+ *     @timeout: default timeout value in jiffies
  *     @gc_int: garbage collection interval in msecs
  *     @policy: set parameterization (see enum nft_set_policies)
  *     @udlen: user data length
index d6d071f..3af60ee 100644 (file)
  * Control a data application associated with the currently viewed channel,
  * e.g. teletext or data broadcast application (MHEG, MHP, HbbTV, etc.)
  */
-#define KEY_DATA                       0x275
+#define KEY_DATA                       0x277
 
 #define BTN_TRIGGER_HAPPY              0x2c0
 #define BTN_TRIGGER_HAPPY1             0x2c0
index e3969bd..9611c7b 100644 (file)
@@ -11,3 +11,4 @@ header-y += tc_vlan.h
 header-y += tc_bpf.h
 header-y += tc_connmark.h
 header-y += tc_ife.h
+header-y += tc_tunnel_key.h
index c4fbc1e..34407f1 100644 (file)
@@ -1945,7 +1945,6 @@ config MODULE_FORCE_UNLOAD
 
 config MODVERSIONS
        bool "Module versioning support"
-       depends on BROKEN
        help
          Usually, you have to use modules compiled with your kernel.
          Saying Y here makes it sometimes possible to use modules
index 6a93615..8199821 100644 (file)
@@ -2454,6 +2454,7 @@ static bool states_equal(struct bpf_verifier_env *env,
                         struct bpf_verifier_state *old,
                         struct bpf_verifier_state *cur)
 {
+       bool varlen_map_access = env->varlen_map_value_access;
        struct bpf_reg_state *rold, *rcur;
        int i;
 
@@ -2467,12 +2468,17 @@ static bool states_equal(struct bpf_verifier_env *env,
                /* If the ranges were not the same, but everything else was and
                 * we didn't do a variable access into a map then we are a-ok.
                 */
-               if (!env->varlen_map_value_access &&
+               if (!varlen_map_access &&
                    rold->type == rcur->type && rold->imm == rcur->imm)
                        continue;
 
+               /* If we didn't map access then again we don't care about the
+                * mismatched range values and it's ok if our old type was
+                * UNKNOWN and we didn't go to a NOT_INIT'ed reg.
+                */
                if (rold->type == NOT_INIT ||
-                   (rold->type == UNKNOWN_VALUE && rcur->type != NOT_INIT))
+                   (!varlen_map_access && rold->type == UNKNOWN_VALUE &&
+                    rcur->type != NOT_INIT))
                        continue;
 
                if (rold->type == PTR_TO_PACKET && rcur->type == PTR_TO_PACKET &&
index f57dd63..0e54d5b 100644 (file)
@@ -1301,8 +1301,9 @@ static int check_version(Elf_Shdr *sechdrs,
                goto bad_version;
        }
 
-       pr_warn("%s: no symbol version for %s\n", mod->name, symname);
-       return 0;
+       /* Broken toolchain. Warn once, then let it go.. */
+       pr_warn_once("%s: no symbol version for %s\n", mod->name, symname);
+       return 1;
 
 bad_version:
        pr_warn("%s: disagrees about version of symbol %s\n",
index a8e1260..056052d 100644 (file)
@@ -362,6 +362,7 @@ void debug_object_init(void *addr, struct debug_obj_descr *descr)
 
        __debug_object_init(addr, descr, 0);
 }
+EXPORT_SYMBOL_GPL(debug_object_init);
 
 /**
  * debug_object_init_on_stack - debug checks when an object on stack is
@@ -376,6 +377,7 @@ void debug_object_init_on_stack(void *addr, struct debug_obj_descr *descr)
 
        __debug_object_init(addr, descr, 1);
 }
+EXPORT_SYMBOL_GPL(debug_object_init_on_stack);
 
 /**
  * debug_object_activate - debug checks when an object is activated
@@ -449,6 +451,7 @@ int debug_object_activate(void *addr, struct debug_obj_descr *descr)
        }
        return 0;
 }
+EXPORT_SYMBOL_GPL(debug_object_activate);
 
 /**
  * debug_object_deactivate - debug checks when an object is deactivated
@@ -496,6 +499,7 @@ void debug_object_deactivate(void *addr, struct debug_obj_descr *descr)
 
        raw_spin_unlock_irqrestore(&db->lock, flags);
 }
+EXPORT_SYMBOL_GPL(debug_object_deactivate);
 
 /**
  * debug_object_destroy - debug checks when an object is destroyed
@@ -542,6 +546,7 @@ void debug_object_destroy(void *addr, struct debug_obj_descr *descr)
 out_unlock:
        raw_spin_unlock_irqrestore(&db->lock, flags);
 }
+EXPORT_SYMBOL_GPL(debug_object_destroy);
 
 /**
  * debug_object_free - debug checks when an object is freed
@@ -582,6 +587,7 @@ void debug_object_free(void *addr, struct debug_obj_descr *descr)
 out_unlock:
        raw_spin_unlock_irqrestore(&db->lock, flags);
 }
+EXPORT_SYMBOL_GPL(debug_object_free);
 
 /**
  * debug_object_assert_init - debug checks when object should be init-ed
@@ -626,6 +632,7 @@ void debug_object_assert_init(void *addr, struct debug_obj_descr *descr)
 
        raw_spin_unlock_irqrestore(&db->lock, flags);
 }
+EXPORT_SYMBOL_GPL(debug_object_assert_init);
 
 /**
  * debug_object_active_state - debug checks object usage state machine
@@ -673,6 +680,7 @@ debug_object_active_state(void *addr, struct debug_obj_descr *descr,
 
        raw_spin_unlock_irqrestore(&db->lock, flags);
 }
+EXPORT_SYMBOL_GPL(debug_object_active_state);
 
 #ifdef CONFIG_DEBUG_OBJECTS_FREE
 static void __debug_check_no_obj_freed(const void *address, unsigned long size)
index 5e51872..fbdf879 100644 (file)
 #include <linux/uaccess.h>
 #include <linux/module.h>
 
+/*
+ * Note: test functions are marked noinline so that their names appear in
+ * reports.
+ */
+
 static noinline void __init kmalloc_oob_right(void)
 {
        char *ptr;
@@ -411,6 +416,29 @@ static noinline void __init copy_user_test(void)
        kfree(kmem);
 }
 
+static noinline void __init use_after_scope_test(void)
+{
+       volatile char *volatile p;
+
+       pr_info("use-after-scope on int\n");
+       {
+               int local = 0;
+
+               p = (char *)&local;
+       }
+       p[0] = 1;
+       p[3] = 1;
+
+       pr_info("use-after-scope on array\n");
+       {
+               char local[1024] = {0};
+
+               p = local;
+       }
+       p[0] = 1;
+       p[1023] = 1;
+}
+
 static int __init kmalloc_tests_init(void)
 {
        kmalloc_oob_right();
@@ -436,6 +464,7 @@ static int __init kmalloc_tests_init(void)
        kasan_global_oob();
        ksize_unpoisons_memory();
        copy_user_test();
+       use_after_scope_test();
        return -EAGAIN;
 }
 
index eff3de3..d4a6e40 100644 (file)
@@ -1456,9 +1456,9 @@ bool move_huge_pmd(struct vm_area_struct *vma, unsigned long old_addr,
                new_ptl = pmd_lockptr(mm, new_pmd);
                if (new_ptl != old_ptl)
                        spin_lock_nested(new_ptl, SINGLE_DEPTH_NESTING);
-               if (pmd_present(*old_pmd) && pmd_dirty(*old_pmd))
-                       force_flush = true;
                pmd = pmdp_huge_get_and_clear(mm, old_addr, old_pmd);
+               if (pmd_present(pmd) && pmd_dirty(pmd))
+                       force_flush = true;
                VM_BUG_ON(!pmd_none(*new_pmd));
 
                if (pmd_move_must_withdraw(new_ptl, old_ptl) &&
index 70c0097..0e9505f 100644 (file)
@@ -764,6 +764,25 @@ EXPORT_SYMBOL(__asan_storeN_noabort);
 void __asan_handle_no_return(void) {}
 EXPORT_SYMBOL(__asan_handle_no_return);
 
+/* Emitted by compiler to poison large objects when they go out of scope. */
+void __asan_poison_stack_memory(const void *addr, size_t size)
+{
+       /*
+        * Addr is KASAN_SHADOW_SCALE_SIZE-aligned and the object is surrounded
+        * by redzones, so we simply round up size to simplify logic.
+        */
+       kasan_poison_shadow(addr, round_up(size, KASAN_SHADOW_SCALE_SIZE),
+                           KASAN_USE_AFTER_SCOPE);
+}
+EXPORT_SYMBOL(__asan_poison_stack_memory);
+
+/* Emitted by compiler to unpoison large objects when they go into scope. */
+void __asan_unpoison_stack_memory(const void *addr, size_t size)
+{
+       kasan_unpoison_shadow(addr, size);
+}
+EXPORT_SYMBOL(__asan_unpoison_stack_memory);
+
 #ifdef CONFIG_MEMORY_HOTPLUG
 static int kasan_mem_notifier(struct notifier_block *nb,
                        unsigned long action, void *data)
index e5c2181..1c260e6 100644 (file)
@@ -21,6 +21,7 @@
 #define KASAN_STACK_MID         0xF2
 #define KASAN_STACK_RIGHT       0xF3
 #define KASAN_STACK_PARTIAL     0xF4
+#define KASAN_USE_AFTER_SCOPE   0xF8
 
 /* Don't break randconfig/all*config builds */
 #ifndef KASAN_ABI_VERSION
@@ -53,6 +54,9 @@ struct kasan_global {
 #if KASAN_ABI_VERSION >= 4
        struct kasan_source_location *location;
 #endif
+#if KASAN_ABI_VERSION >= 5
+       char *odr_indicator;
+#endif
 };
 
 /**
index 24c1211..073325a 100644 (file)
@@ -90,6 +90,9 @@ static void print_error_description(struct kasan_access_info *info)
        case KASAN_KMALLOC_FREE:
                bug_type = "use-after-free";
                break;
+       case KASAN_USE_AFTER_SCOPE:
+               bug_type = "use-after-scope";
+               break;
        }
 
        pr_err("BUG: KASAN: %s in %pS at addr %p\n",
index 728d779..87e1a7c 100644 (file)
@@ -103,6 +103,7 @@ static struct khugepaged_scan khugepaged_scan = {
        .mm_head = LIST_HEAD_INIT(khugepaged_scan.mm_head),
 };
 
+#ifdef CONFIG_SYSFS
 static ssize_t scan_sleep_millisecs_show(struct kobject *kobj,
                                         struct kobj_attribute *attr,
                                         char *buf)
@@ -295,6 +296,7 @@ struct attribute_group khugepaged_attr_group = {
        .attrs = khugepaged_attr,
        .name = "khugepaged",
 };
+#endif /* CONFIG_SYSFS */
 
 #define VM_NO_KHUGEPAGED (VM_SPECIAL | VM_HUGETLB)
 
index 145a425..cdbed8a 100644 (file)
@@ -190,10 +190,13 @@ unsigned int munlock_vma_page(struct page *page)
         */
        spin_lock_irq(zone_lru_lock(zone));
 
-       nr_pages = hpage_nr_pages(page);
-       if (!TestClearPageMlocked(page))
+       if (!TestClearPageMlocked(page)) {
+               /* Potentially, PTE-mapped THP: do not skip the rest PTEs */
+               nr_pages = 1;
                goto unlock_out;
+       }
 
+       nr_pages = hpage_nr_pages(page);
        __mod_zone_page_state(zone, NR_MLOCK, -nr_pages);
 
        if (__munlock_isolate_lru_page(page, true)) {
index 6ccecc0..30d7d24 100644 (file)
@@ -149,14 +149,18 @@ static void move_ptes(struct vm_area_struct *vma, pmd_t *old_pmd,
                if (pte_none(*old_pte))
                        continue;
 
+               pte = ptep_get_and_clear(mm, old_addr, old_pte);
                /*
-                * We are remapping a dirty PTE, make sure to
-                * flush TLB before we drop the PTL for the
+                * If we are remapping a dirty PTE, make sure
+                * to flush TLB before we drop the PTL for the
                 * old PTE or we may race with page_mkclean().
+                *
+                * This check has to be done after we removed the
+                * old PTE from page tables or another thread may
+                * dirty it after the check and before the removal.
                 */
-               if (pte_present(*old_pte) && pte_dirty(*old_pte))
+               if (pte_present(pte) && pte_dirty(pte))
                        force_flush = true;
-               pte = ptep_get_and_clear(mm, old_addr, old_pte);
                pte = move_pte(pte, new_vma->vm_page_prot, old_addr, new_addr);
                pte = move_soft_dirty_pte(pte);
                set_pte_at(mm, new_addr, new_pte, pte);
index a01cce4..8d8c62d 100644 (file)
@@ -283,7 +283,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
 
                        if (!trylock_page(page))
                                continue;
-                       WARN_ON(page_to_pgoff(page) != index);
+                       WARN_ON(page_to_index(page) != index);
                        if (PageWriteback(page)) {
                                unlock_page(page);
                                continue;
@@ -371,7 +371,7 @@ void truncate_inode_pages_range(struct address_space *mapping,
                        }
 
                        lock_page(page);
-                       WARN_ON(page_to_pgoff(page) != index);
+                       WARN_ON(page_to_index(page) != index);
                        wait_on_page_writeback(page);
                        truncate_inode_page(mapping, page);
                        unlock_page(page);
@@ -492,7 +492,7 @@ unsigned long invalidate_mapping_pages(struct address_space *mapping,
                        if (!trylock_page(page))
                                continue;
 
-                       WARN_ON(page_to_pgoff(page) != index);
+                       WARN_ON(page_to_index(page) != index);
 
                        /* Middle of THP: skip */
                        if (PageTransTail(page)) {
@@ -612,7 +612,7 @@ int invalidate_inode_pages2_range(struct address_space *mapping,
                        }
 
                        lock_page(page);
-                       WARN_ON(page_to_pgoff(page) != index);
+                       WARN_ON(page_to_index(page) != index);
                        if (page->mapping != mapping) {
                                unlock_page(page);
                                continue;
index 76fda22..d75cdf3 100644 (file)
@@ -2354,6 +2354,8 @@ static void shrink_node_memcg(struct pglist_data *pgdat, struct mem_cgroup *memc
                        }
                }
 
+               cond_resched();
+
                if (nr_reclaimed < nr_to_reclaim || scan_adjusted)
                        continue;
 
index 617475f..fb1f918 100644 (file)
@@ -348,7 +348,7 @@ static unsigned long count_shadow_nodes(struct shrinker *shrinker,
        shadow_nodes = list_lru_shrink_count(&workingset_shadow_nodes, sc);
        local_irq_enable();
 
-       if (memcg_kmem_enabled()) {
+       if (sc->memcg) {
                pages = mem_cgroup_node_nr_lru_pages(sc->memcg, sc->nid,
                                                     LRU_ALL_FILE);
        } else {
index 3937b1b..18e8893 100644 (file)
@@ -95,7 +95,6 @@ static void flow_cache_gc_task(struct work_struct *work)
        list_for_each_entry_safe(fce, n, &gc_list, u.gc_list) {
                flow_entry_kill(fce, xfrm);
                atomic_dec(&xfrm->flow_cache_gc_count);
-               WARN_ON(atomic_read(&xfrm->flow_cache_gc_count) < 0);
        }
 }
 
@@ -236,9 +235,8 @@ flow_cache_lookup(struct net *net, const struct flowi *key, u16 family, u8 dir,
                if (fcp->hash_count > fc->high_watermark)
                        flow_cache_shrink(fc, fcp);
 
-               if (fcp->hash_count > 2 * fc->high_watermark ||
-                   atomic_read(&net->xfrm.flow_cache_gc_count) > fc->high_watermark) {
-                       atomic_inc(&net->xfrm.flow_cache_genid);
+               if (atomic_read(&net->xfrm.flow_cache_gc_count) >
+                   2 * num_online_cpus() * fc->high_watermark) {
                        flo = ERR_PTR(-ENOBUFS);
                        goto ret_object;
                }
index deb35ac..a6196cf 100644 (file)
@@ -931,8 +931,8 @@ static noinline size_t if_nlmsg_size(const struct net_device *dev,
               + nla_total_size(4) /* IFLA_PROMISCUITY */
               + nla_total_size(4) /* IFLA_NUM_TX_QUEUES */
               + nla_total_size(4) /* IFLA_NUM_RX_QUEUES */
-              + nla_total_size(4) /* IFLA_MAX_GSO_SEGS */
-              + nla_total_size(4) /* IFLA_MAX_GSO_SIZE */
+              + nla_total_size(4) /* IFLA_GSO_MAX_SEGS */
+              + nla_total_size(4) /* IFLA_GSO_MAX_SIZE */
               + nla_total_size(1) /* IFLA_OPERSTATE */
               + nla_total_size(1) /* IFLA_LINKMODE */
               + nla_total_size(4) /* IFLA_CARRIER_CHANGES */
index 5e3ca41..00a074d 100644 (file)
@@ -715,7 +715,7 @@ int sock_setsockopt(struct socket *sock, int level, int optname,
                val = min_t(u32, val, sysctl_wmem_max);
 set_sndbuf:
                sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
-               sk->sk_sndbuf = max_t(u32, val * 2, SOCK_MIN_SNDBUF);
+               sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
                /* Wake up sending tasks if we upped the value. */
                sk->sk_write_space(sk);
                break;
@@ -751,7 +751,7 @@ set_rcvbuf:
                 * returning the value we actually used in getsockopt
                 * is the most desirable behavior.
                 */
-               sk->sk_rcvbuf = max_t(u32, val * 2, SOCK_MIN_RCVBUF);
+               sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
                break;
 
        case SO_RCVBUFFORCE:
index b567c87..edbe59d 100644 (file)
@@ -700,6 +700,7 @@ int dccp_invalid_packet(struct sk_buff *skb)
 {
        const struct dccp_hdr *dh;
        unsigned int cscov;
+       u8 dccph_doff;
 
        if (skb->pkt_type != PACKET_HOST)
                return 1;
@@ -721,18 +722,19 @@ int dccp_invalid_packet(struct sk_buff *skb)
        /*
         * If P.Data Offset is too small for packet type, drop packet and return
         */
-       if (dh->dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
-               DCCP_WARN("P.Data Offset(%u) too small\n", dh->dccph_doff);
+       dccph_doff = dh->dccph_doff;
+       if (dccph_doff < dccp_hdr_len(skb) / sizeof(u32)) {
+               DCCP_WARN("P.Data Offset(%u) too small\n", dccph_doff);
                return 1;
        }
        /*
         * If P.Data Offset is too too large for packet, drop packet and return
         */
-       if (!pskb_may_pull(skb, dh->dccph_doff * sizeof(u32))) {
-               DCCP_WARN("P.Data Offset(%u) too large\n", dh->dccph_doff);
+       if (!pskb_may_pull(skb, dccph_doff * sizeof(u32))) {
+               DCCP_WARN("P.Data Offset(%u) too large\n", dccph_doff);
                return 1;
        }
-
+       dh = dccp_hdr(skb);
        /*
         * If P.type is not Data, Ack, or DataAck and P.X == 0 (the packet
         * has short sequence numbers), drop packet and return
index a6902c1..7899919 100644 (file)
@@ -233,6 +233,8 @@ int dsa_cpu_dsa_setup(struct dsa_switch *ds, struct device *dev,
                genphy_read_status(phydev);
                if (ds->ops->adjust_link)
                        ds->ops->adjust_link(ds, port, phydev);
+
+               put_device(&phydev->mdio.dev);
        }
 
        return 0;
@@ -504,15 +506,8 @@ dsa_switch_setup(struct dsa_switch_tree *dst, int index,
 
 void dsa_cpu_dsa_destroy(struct device_node *port_dn)
 {
-       struct phy_device *phydev;
-
-       if (of_phy_is_fixed_link(port_dn)) {
-               phydev = of_phy_find_device(port_dn);
-               if (phydev) {
-                       phy_device_free(phydev);
-                       fixed_phy_unregister(phydev);
-               }
-       }
+       if (of_phy_is_fixed_link(port_dn))
+               of_phy_deregister_fixed_link(port_dn);
 }
 
 static void dsa_switch_destroy(struct dsa_switch *ds)
index f8a7d9a..5fff951 100644 (file)
@@ -28,8 +28,10 @@ static struct dsa_switch_tree *dsa_get_dst(u32 tree)
        struct dsa_switch_tree *dst;
 
        list_for_each_entry(dst, &dsa_switch_trees, list)
-               if (dst->tree == tree)
+               if (dst->tree == tree) {
+                       kref_get(&dst->refcount);
                        return dst;
+               }
        return NULL;
 }
 
index 6b1282c..30e2e21 100644 (file)
@@ -1125,7 +1125,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
        p->phy_interface = mode;
 
        phy_dn = of_parse_phandle(port_dn, "phy-handle", 0);
-       if (of_phy_is_fixed_link(port_dn)) {
+       if (!phy_dn && of_phy_is_fixed_link(port_dn)) {
                /* In the case of a fixed PHY, the DT node associated
                 * to the fixed PHY is the Port DT node
                 */
@@ -1135,7 +1135,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
                        return ret;
                }
                phy_is_fixed = true;
-               phy_dn = port_dn;
+               phy_dn = of_node_get(port_dn);
        }
 
        if (ds->ops->get_phy_flags)
@@ -1154,6 +1154,7 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
                        ret = dsa_slave_phy_connect(p, slave_dev, phy_id);
                        if (ret) {
                                netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret);
+                               of_node_put(phy_dn);
                                return ret;
                        }
                } else {
@@ -1162,6 +1163,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
                                                phy_flags,
                                                p->phy_interface);
                }
+
+               of_node_put(phy_dn);
        }
 
        if (p->phy && phy_is_fixed)
@@ -1174,6 +1177,8 @@ static int dsa_slave_phy_setup(struct dsa_slave_priv *p,
                ret = dsa_slave_phy_connect(p, slave_dev, p->port);
                if (ret) {
                        netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret);
+                       if (phy_is_fixed)
+                               of_phy_deregister_fixed_link(port_dn);
                        return ret;
                }
        }
@@ -1289,10 +1294,18 @@ int dsa_slave_create(struct dsa_switch *ds, struct device *parent,
 void dsa_slave_destroy(struct net_device *slave_dev)
 {
        struct dsa_slave_priv *p = netdev_priv(slave_dev);
+       struct dsa_switch *ds = p->parent;
+       struct device_node *port_dn;
+
+       port_dn = ds->ports[p->port].dn;
 
        netif_carrier_off(slave_dev);
-       if (p->phy)
+       if (p->phy) {
                phy_disconnect(p->phy);
+
+               if (of_phy_is_fixed_link(port_dn))
+                       of_phy_deregister_fixed_link(port_dn);
+       }
        unregister_netdev(slave_dev);
        free_netdev(slave_dev);
 }
index 300b068..b54b3ca 100644 (file)
@@ -715,6 +715,7 @@ config DEFAULT_TCP_CONG
        default "reno" if DEFAULT_RENO
        default "dctcp" if DEFAULT_DCTCP
        default "cdg" if DEFAULT_CDG
+       default "bbr" if DEFAULT_BBR
        default "cubic"
 
 config TCP_MD5SIG
index 5ddf5cd..2151432 100644 (file)
@@ -1233,7 +1233,7 @@ struct sk_buff *inet_gso_segment(struct sk_buff *skb,
                fixedid = !!(skb_shinfo(skb)->gso_type & SKB_GSO_TCP_FIXEDID);
 
                /* fixed ID is invalid if DF bit is not set */
-               if (fixedid && !(iph->frag_off & htons(IP_DF)))
+               if (fixedid && !(ip_hdr(skb)->frag_off & htons(IP_DF)))
                        goto out;
        }
 
index d95631d..20fb25e 100644 (file)
@@ -476,7 +476,7 @@ static int esp_input(struct xfrm_state *x, struct sk_buff *skb)
                esph = (void *)skb_push(skb, 4);
                *seqhi = esph->spi;
                esph->spi = esph->seq_no;
-               esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi);
+               esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
                aead_request_set_callback(req, 0, esp_input_done_esn, skb);
        }
 
index 105908d..877bdb0 100644 (file)
@@ -107,6 +107,8 @@ int __ip_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
        if (unlikely(!skb))
                return 0;
 
+       skb->protocol = htons(ETH_P_IP);
+
        return nf_hook(NFPROTO_IPV4, NF_INET_LOCAL_OUT,
                       net, sk, skb, NULL, skb_dst(skb)->dev,
                       dst_output);
index c3776ff..b3cc133 100644 (file)
@@ -24,10 +24,11 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
        struct flowi4 fl4 = {};
        __be32 saddr = iph->saddr;
        __u8 flags = skb->sk ? inet_sk_flowi_flags(skb->sk) : 0;
+       struct net_device *dev = skb_dst(skb)->dev;
        unsigned int hh_len;
 
        if (addr_type == RTN_UNSPEC)
-               addr_type = inet_addr_type(net, saddr);
+               addr_type = inet_addr_type_dev_table(net, dev, saddr);
        if (addr_type == RTN_LOCAL || addr_type == RTN_UNICAST)
                flags |= FLOWI_FLAG_ANYSRC;
        else
@@ -40,6 +41,8 @@ int ip_route_me_harder(struct net *net, struct sk_buff *skb, unsigned int addr_t
        fl4.saddr = saddr;
        fl4.flowi4_tos = RT_TOS(iph->tos);
        fl4.flowi4_oif = skb->sk ? skb->sk->sk_bound_dev_if : 0;
+       if (!fl4.flowi4_oif)
+               fl4.flowi4_oif = l3mdev_master_ifindex(dev);
        fl4.flowi4_mark = skb->mark;
        fl4.flowi4_flags = flags;
        rt = ip_route_output_key(net, &fl4);
index b31df59..6975384 100644 (file)
@@ -1201,8 +1201,8 @@ static int translate_compat_table(struct xt_table_info **pinfo,
 
        newinfo->number = compatr->num_entries;
        for (i = 0; i < NF_ARP_NUMHOOKS; i++) {
-               newinfo->hook_entry[i] = info->hook_entry[i];
-               newinfo->underflow[i] = info->underflow[i];
+               newinfo->hook_entry[i] = compatr->hook_entry[i];
+               newinfo->underflow[i] = compatr->underflow[i];
        }
        entry1 = newinfo->entries;
        pos = entry1;
index 37874e2..ccf4055 100644 (file)
@@ -139,7 +139,8 @@ void ip6_datagram_release_cb(struct sock *sk)
 }
 EXPORT_SYMBOL_GPL(ip6_datagram_release_cb);
 
-static int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
+int __ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr,
+                          int addr_len)
 {
        struct sockaddr_in6     *usin = (struct sockaddr_in6 *) uaddr;
        struct inet_sock        *inet = inet_sk(sk);
@@ -252,6 +253,7 @@ ipv4_connected:
 out:
        return err;
 }
+EXPORT_SYMBOL_GPL(__ip6_datagram_connect);
 
 int ip6_datagram_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
 {
index 060a60b..111ba55 100644 (file)
@@ -418,7 +418,7 @@ static int esp6_input(struct xfrm_state *x, struct sk_buff *skb)
                esph = (void *)skb_push(skb, 4);
                *seqhi = esph->spi;
                esph->spi = esph->seq_no;
-               esph->seq_no = htonl(XFRM_SKB_CB(skb)->seq.input.hi);
+               esph->seq_no = XFRM_SKB_CB(skb)->seq.input.hi;
                aead_request_set_callback(req, 0, esp_input_done_esn, skb);
        }
 
index 7370ad2..2772004 100644 (file)
@@ -447,8 +447,10 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
 
        if (__ipv6_addr_needs_scope_id(addr_type))
                iif = skb->dev->ifindex;
-       else
-               iif = l3mdev_master_ifindex(skb_dst(skb)->dev);
+       else {
+               dst = skb_dst(skb);
+               iif = l3mdev_master_ifindex(dst ? dst->dev : skb->dev);
+       }
 
        /*
         *      Must not send error if the source does not uniquely
index 1fcf61f..89c59e6 100644 (file)
@@ -99,7 +99,7 @@ static struct sk_buff *ipv6_gso_segment(struct sk_buff *skb,
                segs = ops->callbacks.gso_segment(skb, features);
        }
 
-       if (IS_ERR(segs))
+       if (IS_ERR_OR_NULL(segs))
                goto out;
 
        gso_partial = !!(skb_shinfo(segs)->gso_type & SKB_GSO_PARTIAL);
index 0a4759b..d76674e 100644 (file)
@@ -1181,7 +1181,6 @@ route_lookup:
        if (err)
                return err;
 
-       skb->protocol = htons(ETH_P_IPV6);
        skb_push(skb, sizeof(struct ipv6hdr));
        skb_reset_network_header(skb);
        ipv6h = ipv6_hdr(skb);
index 8a02ca8..c299c1e 100644 (file)
@@ -1138,6 +1138,33 @@ static struct xfrm6_protocol vti_ipcomp6_protocol __read_mostly = {
        .priority       =       100,
 };
 
+static bool is_vti6_tunnel(const struct net_device *dev)
+{
+       return dev->netdev_ops == &vti6_netdev_ops;
+}
+
+static int vti6_device_event(struct notifier_block *unused,
+                            unsigned long event, void *ptr)
+{
+       struct net_device *dev = netdev_notifier_info_to_dev(ptr);
+       struct ip6_tnl *t = netdev_priv(dev);
+
+       if (!is_vti6_tunnel(dev))
+               return NOTIFY_DONE;
+
+       switch (event) {
+       case NETDEV_DOWN:
+               if (!net_eq(t->net, dev_net(dev)))
+                       xfrm_garbage_collect(t->net);
+               break;
+       }
+       return NOTIFY_DONE;
+}
+
+static struct notifier_block vti6_notifier_block __read_mostly = {
+       .notifier_call = vti6_device_event,
+};
+
 /**
  * vti6_tunnel_init - register protocol and reserve needed resources
  *
@@ -1148,6 +1175,8 @@ static int __init vti6_tunnel_init(void)
        const char *msg;
        int err;
 
+       register_netdevice_notifier(&vti6_notifier_block);
+
        msg = "tunnel device";
        err = register_pernet_device(&vti6_net_ops);
        if (err < 0)
@@ -1180,6 +1209,7 @@ xfrm_proto_ah_failed:
 xfrm_proto_esp_failed:
        unregister_pernet_device(&vti6_net_ops);
 pernet_dev_failed:
+       unregister_netdevice_notifier(&vti6_notifier_block);
        pr_err("vti6 init: failed to register %s\n", msg);
        return err;
 }
@@ -1194,6 +1224,7 @@ static void __exit vti6_tunnel_cleanup(void)
        xfrm6_protocol_deregister(&vti_ah6_protocol, IPPROTO_AH);
        xfrm6_protocol_deregister(&vti_esp6_protocol, IPPROTO_ESP);
        unregister_pernet_device(&vti6_net_ops);
+       unregister_netdevice_notifier(&vti6_notifier_block);
 }
 
 module_init(vti6_tunnel_init);
index e4347ae..9948b5c 100644 (file)
@@ -576,11 +576,11 @@ int nf_ct_frag6_gather(struct net *net, struct sk_buff *skb, u32 user)
        /* Jumbo payload inhibits frag. header */
        if (ipv6_hdr(skb)->payload_len == 0) {
                pr_debug("payload len = 0\n");
-               return -EINVAL;
+               return 0;
        }
 
        if (find_prev_fhdr(skb, &prevhdr, &nhoff, &fhoff) < 0)
-               return -EINVAL;
+               return 0;
 
        if (!pskb_may_pull(skb, fhoff + sizeof(*fhdr)))
                return -ENOMEM;
index f7aab5a..f06b047 100644 (file)
@@ -69,7 +69,7 @@ static unsigned int ipv6_defrag(void *priv,
        if (err == -EINPROGRESS)
                return NF_STOLEN;
 
-       return NF_ACCEPT;
+       return err == 0 ? NF_ACCEPT : NF_DROP;
 }
 
 static struct nf_hook_ops ipv6_defrag_ops[] = {
index a540022..1009040 100644 (file)
@@ -156,6 +156,7 @@ void nf_send_reset6(struct net *net, struct sk_buff *oldskb, int hook)
        fl6.daddr = oip6h->saddr;
        fl6.fl6_sport = otcph->dest;
        fl6.fl6_dport = otcph->source;
+       fl6.flowi6_oif = l3mdev_master_ifindex(skb_dst(oldskb)->dev);
        security_skb_classify_flow(oldskb, flowi6_to_flowi(&fl6));
        dst = ip6_route_output(net, NULL, &fl6);
        if (dst->error) {
index 7cca8ac..cd42523 100644 (file)
@@ -155,6 +155,8 @@ int __ip6_local_out(struct net *net, struct sock *sk, struct sk_buff *skb)
        if (unlikely(!skb))
                return 0;
 
+       skb->protocol = htons(ETH_P_IPV6);
+
        return nf_hook(NFPROTO_IPV6, NF_INET_LOCAL_OUT,
                       net, sk, skb, NULL, skb_dst(skb)->dev,
                       dst_output);
index 982f6c4..8938b6b 100644 (file)
@@ -61,7 +61,8 @@ static struct sock *__l2tp_ip_bind_lookup(struct net *net, __be32 laddr, int dif
                if ((l2tp->conn_id == tunnel_id) &&
                    net_eq(sock_net(sk), net) &&
                    !(inet->inet_rcv_saddr && inet->inet_rcv_saddr != laddr) &&
-                   !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
+                   (!sk->sk_bound_dev_if || !dif ||
+                    sk->sk_bound_dev_if == dif))
                        goto found;
        }
 
@@ -182,15 +183,17 @@ pass_up:
                struct iphdr *iph = (struct iphdr *) skb_network_header(skb);
 
                read_lock_bh(&l2tp_ip_lock);
-               sk = __l2tp_ip_bind_lookup(net, iph->daddr, 0, tunnel_id);
+               sk = __l2tp_ip_bind_lookup(net, iph->daddr, inet_iif(skb),
+                                          tunnel_id);
+               if (!sk) {
+                       read_unlock_bh(&l2tp_ip_lock);
+                       goto discard;
+               }
+
+               sock_hold(sk);
                read_unlock_bh(&l2tp_ip_lock);
        }
 
-       if (sk == NULL)
-               goto discard;
-
-       sock_hold(sk);
-
        if (!xfrm4_policy_check(sk, XFRM_POLICY_IN, skb))
                goto discard_put;
 
@@ -256,15 +259,9 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (addr->l2tp_family != AF_INET)
                return -EINVAL;
 
-       ret = -EADDRINUSE;
-       read_lock_bh(&l2tp_ip_lock);
-       if (__l2tp_ip_bind_lookup(net, addr->l2tp_addr.s_addr,
-                                 sk->sk_bound_dev_if, addr->l2tp_conn_id))
-               goto out_in_use;
-
-       read_unlock_bh(&l2tp_ip_lock);
-
        lock_sock(sk);
+
+       ret = -EINVAL;
        if (!sock_flag(sk, SOCK_ZAPPED))
                goto out;
 
@@ -281,14 +278,22 @@ static int l2tp_ip_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
                inet->inet_rcv_saddr = inet->inet_saddr = addr->l2tp_addr.s_addr;
        if (chk_addr_ret == RTN_MULTICAST || chk_addr_ret == RTN_BROADCAST)
                inet->inet_saddr = 0;  /* Use device */
-       sk_dst_reset(sk);
 
+       write_lock_bh(&l2tp_ip_lock);
+       if (__l2tp_ip_bind_lookup(net, addr->l2tp_addr.s_addr,
+                                 sk->sk_bound_dev_if, addr->l2tp_conn_id)) {
+               write_unlock_bh(&l2tp_ip_lock);
+               ret = -EADDRINUSE;
+               goto out;
+       }
+
+       sk_dst_reset(sk);
        l2tp_ip_sk(sk)->conn_id = addr->l2tp_conn_id;
 
-       write_lock_bh(&l2tp_ip_lock);
        sk_add_bind_node(sk, &l2tp_ip_bind_table);
        sk_del_node_init(sk);
        write_unlock_bh(&l2tp_ip_lock);
+
        ret = 0;
        sock_reset_flag(sk, SOCK_ZAPPED);
 
@@ -296,11 +301,6 @@ out:
        release_sock(sk);
 
        return ret;
-
-out_in_use:
-       read_unlock_bh(&l2tp_ip_lock);
-
-       return ret;
 }
 
 static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len)
@@ -308,21 +308,24 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
        struct sockaddr_l2tpip *lsa = (struct sockaddr_l2tpip *) uaddr;
        int rc;
 
-       if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
-               return -EINVAL;
-
        if (addr_len < sizeof(*lsa))
                return -EINVAL;
 
        if (ipv4_is_multicast(lsa->l2tp_addr.s_addr))
                return -EINVAL;
 
-       rc = ip4_datagram_connect(sk, uaddr, addr_len);
-       if (rc < 0)
-               return rc;
-
        lock_sock(sk);
 
+       /* Must bind first - autobinding does not work */
+       if (sock_flag(sk, SOCK_ZAPPED)) {
+               rc = -EINVAL;
+               goto out_sk;
+       }
+
+       rc = __ip4_datagram_connect(sk, uaddr, addr_len);
+       if (rc < 0)
+               goto out_sk;
+
        l2tp_ip_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
 
        write_lock_bh(&l2tp_ip_lock);
@@ -330,7 +333,9 @@ static int l2tp_ip_connect(struct sock *sk, struct sockaddr *uaddr, int addr_len
        sk_add_bind_node(sk, &l2tp_ip_bind_table);
        write_unlock_bh(&l2tp_ip_lock);
 
+out_sk:
        release_sock(sk);
+
        return rc;
 }
 
index 9978d01..aa821cb 100644 (file)
@@ -72,8 +72,9 @@ static struct sock *__l2tp_ip6_bind_lookup(struct net *net,
 
                if ((l2tp->conn_id == tunnel_id) &&
                    net_eq(sock_net(sk), net) &&
-                   !(addr && ipv6_addr_equal(addr, laddr)) &&
-                   !(sk->sk_bound_dev_if && sk->sk_bound_dev_if != dif))
+                   (!addr || ipv6_addr_equal(addr, laddr)) &&
+                   (!sk->sk_bound_dev_if || !dif ||
+                    sk->sk_bound_dev_if == dif))
                        goto found;
        }
 
@@ -196,16 +197,17 @@ pass_up:
                struct ipv6hdr *iph = ipv6_hdr(skb);
 
                read_lock_bh(&l2tp_ip6_lock);
-               sk = __l2tp_ip6_bind_lookup(net, &iph->daddr,
-                                           0, tunnel_id);
+               sk = __l2tp_ip6_bind_lookup(net, &iph->daddr, inet6_iif(skb),
+                                           tunnel_id);
+               if (!sk) {
+                       read_unlock_bh(&l2tp_ip6_lock);
+                       goto discard;
+               }
+
+               sock_hold(sk);
                read_unlock_bh(&l2tp_ip6_lock);
        }
 
-       if (sk == NULL)
-               goto discard;
-
-       sock_hold(sk);
-
        if (!xfrm6_policy_check(sk, XFRM_POLICY_IN, skb))
                goto discard_put;
 
@@ -266,6 +268,7 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        struct sockaddr_l2tpip6 *addr = (struct sockaddr_l2tpip6 *) uaddr;
        struct net *net = sock_net(sk);
        __be32 v4addr = 0;
+       int bound_dev_if;
        int addr_type;
        int err;
 
@@ -284,13 +287,6 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (addr_type & IPV6_ADDR_MULTICAST)
                return -EADDRNOTAVAIL;
 
-       err = -EADDRINUSE;
-       read_lock_bh(&l2tp_ip6_lock);
-       if (__l2tp_ip6_bind_lookup(net, &addr->l2tp_addr,
-                                  sk->sk_bound_dev_if, addr->l2tp_conn_id))
-               goto out_in_use;
-       read_unlock_bh(&l2tp_ip6_lock);
-
        lock_sock(sk);
 
        err = -EINVAL;
@@ -300,28 +296,25 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        if (sk->sk_state != TCP_CLOSE)
                goto out_unlock;
 
+       bound_dev_if = sk->sk_bound_dev_if;
+
        /* Check if the address belongs to the host. */
        rcu_read_lock();
        if (addr_type != IPV6_ADDR_ANY) {
                struct net_device *dev = NULL;
 
                if (addr_type & IPV6_ADDR_LINKLOCAL) {
-                       if (addr_len >= sizeof(struct sockaddr_in6) &&
-                           addr->l2tp_scope_id) {
-                               /* Override any existing binding, if another
-                                * one is supplied by user.
-                                */
-                               sk->sk_bound_dev_if = addr->l2tp_scope_id;
-                       }
+                       if (addr->l2tp_scope_id)
+                               bound_dev_if = addr->l2tp_scope_id;
 
                        /* Binding to link-local address requires an
-                          interface */
-                       if (!sk->sk_bound_dev_if)
+                        * interface.
+                        */
+                       if (!bound_dev_if)
                                goto out_unlock_rcu;
 
                        err = -ENODEV;
-                       dev = dev_get_by_index_rcu(sock_net(sk),
-                                                  sk->sk_bound_dev_if);
+                       dev = dev_get_by_index_rcu(sock_net(sk), bound_dev_if);
                        if (!dev)
                                goto out_unlock_rcu;
                }
@@ -336,13 +329,22 @@ static int l2tp_ip6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len)
        }
        rcu_read_unlock();
 
-       inet->inet_rcv_saddr = inet->inet_saddr = v4addr;
+       write_lock_bh(&l2tp_ip6_lock);
+       if (__l2tp_ip6_bind_lookup(net, &addr->l2tp_addr, bound_dev_if,
+                                  addr->l2tp_conn_id)) {
+               write_unlock_bh(&l2tp_ip6_lock);
+               err = -EADDRINUSE;
+               goto out_unlock;
+       }
+
+       inet->inet_saddr = v4addr;
+       inet->inet_rcv_saddr = v4addr;
+       sk->sk_bound_dev_if = bound_dev_if;
        sk->sk_v6_rcv_saddr = addr->l2tp_addr;
        np->saddr = addr->l2tp_addr;
 
        l2tp_ip6_sk(sk)->conn_id = addr->l2tp_conn_id;
 
-       write_lock_bh(&l2tp_ip6_lock);
        sk_add_bind_node(sk, &l2tp_ip6_bind_table);
        sk_del_node_init(sk);
        write_unlock_bh(&l2tp_ip6_lock);
@@ -355,10 +357,7 @@ out_unlock_rcu:
        rcu_read_unlock();
 out_unlock:
        release_sock(sk);
-       return err;
 
-out_in_use:
-       read_unlock_bh(&l2tp_ip6_lock);
        return err;
 }
 
@@ -371,9 +370,6 @@ static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
        int     addr_type;
        int rc;
 
-       if (sock_flag(sk, SOCK_ZAPPED)) /* Must bind first - autobinding does not work */
-               return -EINVAL;
-
        if (addr_len < sizeof(*lsa))
                return -EINVAL;
 
@@ -390,10 +386,18 @@ static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
                        return -EINVAL;
        }
 
-       rc = ip6_datagram_connect(sk, uaddr, addr_len);
-
        lock_sock(sk);
 
+        /* Must bind first - autobinding does not work */
+       if (sock_flag(sk, SOCK_ZAPPED)) {
+               rc = -EINVAL;
+               goto out_sk;
+       }
+
+       rc = __ip6_datagram_connect(sk, uaddr, addr_len);
+       if (rc < 0)
+               goto out_sk;
+
        l2tp_ip6_sk(sk)->peer_conn_id = lsa->l2tp_conn_id;
 
        write_lock_bh(&l2tp_ip6_lock);
@@ -401,6 +405,7 @@ static int l2tp_ip6_connect(struct sock *sk, struct sockaddr *uaddr,
        sk_add_bind_node(sk, &l2tp_ip6_bind_table);
        write_unlock_bh(&l2tp_ip6_lock);
 
+out_sk:
        release_sock(sk);
 
        return rc;
index bbb8f3d..5b9c884 100644 (file)
@@ -42,7 +42,7 @@ struct nf_nat_conn_key {
        const struct nf_conntrack_zone *zone;
 };
 
-static struct rhashtable nf_nat_bysource_table;
+static struct rhltable nf_nat_bysource_table;
 
 inline const struct nf_nat_l3proto *
 __nf_nat_l3proto_find(u8 family)
@@ -193,9 +193,12 @@ static int nf_nat_bysource_cmp(struct rhashtable_compare_arg *arg,
        const struct nf_nat_conn_key *key = arg->key;
        const struct nf_conn *ct = obj;
 
-       return same_src(ct, key->tuple) &&
-              net_eq(nf_ct_net(ct), key->net) &&
-              nf_ct_zone_equal(ct, key->zone, IP_CT_DIR_ORIGINAL);
+       if (!same_src(ct, key->tuple) ||
+           !net_eq(nf_ct_net(ct), key->net) ||
+           !nf_ct_zone_equal(ct, key->zone, IP_CT_DIR_ORIGINAL))
+               return 1;
+
+       return 0;
 }
 
 static struct rhashtable_params nf_nat_bysource_params = {
@@ -204,7 +207,6 @@ static struct rhashtable_params nf_nat_bysource_params = {
        .obj_cmpfn = nf_nat_bysource_cmp,
        .nelem_hint = 256,
        .min_size = 1024,
-       .nulls_base = (1U << RHT_BASE_SHIFT),
 };
 
 /* Only called for SRC manip */
@@ -223,12 +225,15 @@ find_appropriate_src(struct net *net,
                .tuple = tuple,
                .zone = zone
        };
+       struct rhlist_head *hl;
 
-       ct = rhashtable_lookup_fast(&nf_nat_bysource_table, &key,
-                                   nf_nat_bysource_params);
-       if (!ct)
+       hl = rhltable_lookup(&nf_nat_bysource_table, &key,
+                            nf_nat_bysource_params);
+       if (!hl)
                return 0;
 
+       ct = container_of(hl, typeof(*ct), nat_bysource);
+
        nf_ct_invert_tuplepr(result,
                             &ct->tuplehash[IP_CT_DIR_REPLY].tuple);
        result->dst = tuple->dst;
@@ -446,11 +451,17 @@ nf_nat_setup_info(struct nf_conn *ct,
        }
 
        if (maniptype == NF_NAT_MANIP_SRC) {
+               struct nf_nat_conn_key key = {
+                       .net = nf_ct_net(ct),
+                       .tuple = &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                       .zone = nf_ct_zone(ct),
+               };
                int err;
 
-               err = rhashtable_insert_fast(&nf_nat_bysource_table,
-                                            &ct->nat_bysource,
-                                            nf_nat_bysource_params);
+               err = rhltable_insert_key(&nf_nat_bysource_table,
+                                         &key,
+                                         &ct->nat_bysource,
+                                         nf_nat_bysource_params);
                if (err)
                        return NF_DROP;
        }
@@ -567,8 +578,8 @@ static int nf_nat_proto_clean(struct nf_conn *ct, void *data)
         * will delete entry from already-freed table.
         */
        ct->status &= ~IPS_NAT_DONE_MASK;
-       rhashtable_remove_fast(&nf_nat_bysource_table, &ct->nat_bysource,
-                              nf_nat_bysource_params);
+       rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource,
+                       nf_nat_bysource_params);
 
        /* don't delete conntrack.  Although that would make things a lot
         * simpler, we'd end up flushing all conntracks on nat rmmod.
@@ -698,8 +709,8 @@ static void nf_nat_cleanup_conntrack(struct nf_conn *ct)
        if (!nat)
                return;
 
-       rhashtable_remove_fast(&nf_nat_bysource_table, &ct->nat_bysource,
-                              nf_nat_bysource_params);
+       rhltable_remove(&nf_nat_bysource_table, &ct->nat_bysource,
+                       nf_nat_bysource_params);
 }
 
 static struct nf_ct_ext_type nat_extend __read_mostly = {
@@ -834,13 +845,13 @@ static int __init nf_nat_init(void)
 {
        int ret;
 
-       ret = rhashtable_init(&nf_nat_bysource_table, &nf_nat_bysource_params);
+       ret = rhltable_init(&nf_nat_bysource_table, &nf_nat_bysource_params);
        if (ret)
                return ret;
 
        ret = nf_ct_extend_register(&nat_extend);
        if (ret < 0) {
-               rhashtable_destroy(&nf_nat_bysource_table);
+               rhltable_destroy(&nf_nat_bysource_table);
                printk(KERN_ERR "nf_nat_core: Unable to register extension\n");
                return ret;
        }
@@ -864,7 +875,7 @@ static int __init nf_nat_init(void)
        return 0;
 
  cleanup_extend:
-       rhashtable_destroy(&nf_nat_bysource_table);
+       rhltable_destroy(&nf_nat_bysource_table);
        nf_ct_extend_unregister(&nat_extend);
        return ret;
 }
@@ -883,7 +894,7 @@ static void __exit nf_nat_cleanup(void)
        for (i = 0; i < NFPROTO_NUMPROTO; i++)
                kfree(nf_nat_l4protos[i]);
 
-       rhashtable_destroy(&nf_nat_bysource_table);
+       rhltable_destroy(&nf_nat_bysource_table);
 }
 
 MODULE_LICENSE("GPL");
index 026581b..e5194f6 100644 (file)
@@ -2570,7 +2570,8 @@ static int nf_tables_fill_set(struct sk_buff *skb, const struct nft_ctx *ctx,
        }
 
        if (set->timeout &&
-           nla_put_be64(skb, NFTA_SET_TIMEOUT, cpu_to_be64(set->timeout),
+           nla_put_be64(skb, NFTA_SET_TIMEOUT,
+                        cpu_to_be64(jiffies_to_msecs(set->timeout)),
                         NFTA_SET_PAD))
                goto nla_put_failure;
        if (set->gc_int &&
@@ -2859,7 +2860,8 @@ static int nf_tables_newset(struct net *net, struct sock *nlsk,
        if (nla[NFTA_SET_TIMEOUT] != NULL) {
                if (!(flags & NFT_SET_TIMEOUT))
                        return -EINVAL;
-               timeout = be64_to_cpu(nla_get_be64(nla[NFTA_SET_TIMEOUT]));
+               timeout = msecs_to_jiffies(be64_to_cpu(nla_get_be64(
+                                               nla[NFTA_SET_TIMEOUT])));
        }
        gc_int = 0;
        if (nla[NFTA_SET_GC_INTERVAL] != NULL) {
@@ -3178,7 +3180,8 @@ static int nf_tables_fill_setelem(struct sk_buff *skb,
 
        if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT) &&
            nla_put_be64(skb, NFTA_SET_ELEM_TIMEOUT,
-                        cpu_to_be64(*nft_set_ext_timeout(ext)),
+                        cpu_to_be64(jiffies_to_msecs(
+                                               *nft_set_ext_timeout(ext))),
                         NFTA_SET_ELEM_PAD))
                goto nla_put_failure;
 
@@ -3447,7 +3450,7 @@ void *nft_set_elem_init(const struct nft_set *set,
                memcpy(nft_set_ext_data(ext), data, set->dlen);
        if (nft_set_ext_exists(ext, NFT_SET_EXT_EXPIRATION))
                *nft_set_ext_expiration(ext) =
-                       jiffies + msecs_to_jiffies(timeout);
+                       jiffies + timeout;
        if (nft_set_ext_exists(ext, NFT_SET_EXT_TIMEOUT))
                *nft_set_ext_timeout(ext) = timeout;
 
@@ -3535,7 +3538,8 @@ static int nft_add_set_elem(struct nft_ctx *ctx, struct nft_set *set,
        if (nla[NFTA_SET_ELEM_TIMEOUT] != NULL) {
                if (!(set->flags & NFT_SET_TIMEOUT))
                        return -EINVAL;
-               timeout = be64_to_cpu(nla_get_be64(nla[NFTA_SET_ELEM_TIMEOUT]));
+               timeout = msecs_to_jiffies(be64_to_cpu(nla_get_be64(
+                                       nla[NFTA_SET_ELEM_TIMEOUT])));
        } else if (set->flags & NFT_SET_TIMEOUT) {
                timeout = set->timeout;
        }
index baf694d..d5447a2 100644 (file)
@@ -53,6 +53,7 @@ static int nft_hash_init(const struct nft_ctx *ctx,
 {
        struct nft_hash *priv = nft_expr_priv(expr);
        u32 len;
+       int err;
 
        if (!tb[NFTA_HASH_SREG] ||
            !tb[NFTA_HASH_DREG] ||
@@ -67,8 +68,10 @@ static int nft_hash_init(const struct nft_ctx *ctx,
        priv->sreg = nft_parse_register(tb[NFTA_HASH_SREG]);
        priv->dreg = nft_parse_register(tb[NFTA_HASH_DREG]);
 
-       len = ntohl(nla_get_be32(tb[NFTA_HASH_LEN]));
-       if (len == 0 || len > U8_MAX)
+       err = nft_parse_u32_check(tb[NFTA_HASH_LEN], U8_MAX, &len);
+       if (err < 0)
+               return err;
+       if (len == 0)
                return -ERANGE;
 
        priv->len = len;
index fbc8800..8f0aaae 100644 (file)
@@ -59,6 +59,12 @@ static int nft_range_init(const struct nft_ctx *ctx, const struct nft_expr *expr
        int err;
        u32 op;
 
+       if (!tb[NFTA_RANGE_SREG]      ||
+           !tb[NFTA_RANGE_OP]        ||
+           !tb[NFTA_RANGE_FROM_DATA] ||
+           !tb[NFTA_RANGE_TO_DATA])
+               return -EINVAL;
+
        err = nft_data_init(NULL, &priv->data_from, sizeof(priv->data_from),
                            &desc_from, tb[NFTA_RANGE_FROM_DATA]);
        if (err < 0)
index 62bea45..602e5eb 100644 (file)
@@ -322,14 +322,11 @@ static void netlink_skb_set_owner_r(struct sk_buff *skb, struct sock *sk)
        sk_mem_charge(sk, skb->truesize);
 }
 
-static void netlink_sock_destruct(struct sock *sk)
+static void __netlink_sock_destruct(struct sock *sk)
 {
        struct netlink_sock *nlk = nlk_sk(sk);
 
        if (nlk->cb_running) {
-               if (nlk->cb.done)
-                       nlk->cb.done(&nlk->cb);
-
                module_put(nlk->cb.module);
                kfree_skb(nlk->cb.skb);
        }
@@ -346,6 +343,28 @@ static void netlink_sock_destruct(struct sock *sk)
        WARN_ON(nlk_sk(sk)->groups);
 }
 
+static void netlink_sock_destruct_work(struct work_struct *work)
+{
+       struct netlink_sock *nlk = container_of(work, struct netlink_sock,
+                                               work);
+
+       nlk->cb.done(&nlk->cb);
+       __netlink_sock_destruct(&nlk->sk);
+}
+
+static void netlink_sock_destruct(struct sock *sk)
+{
+       struct netlink_sock *nlk = nlk_sk(sk);
+
+       if (nlk->cb_running && nlk->cb.done) {
+               INIT_WORK(&nlk->work, netlink_sock_destruct_work);
+               schedule_work(&nlk->work);
+               return;
+       }
+
+       __netlink_sock_destruct(sk);
+}
+
 /* This lock without WQ_FLAG_EXCLUSIVE is good on UP and it is _very_ bad on
  * SMP. Look, when several writers sleep and reader wakes them up, all but one
  * immediately hit write lock and grab all the cpus. Exclusive sleep solves
index 3cfd6cc..4fdb383 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/rhashtable.h>
 #include <linux/atomic.h>
+#include <linux/workqueue.h>
 #include <net/sock.h>
 
 #define NLGRPSZ(x)     (ALIGN(x, sizeof(unsigned long) * 8) / 8)
@@ -33,6 +34,7 @@ struct netlink_sock {
 
        struct rhash_head       node;
        struct rcu_head         rcu;
+       struct work_struct      work;
 };
 
 static inline struct netlink_sock *nlk_sk(struct sock *sk)
index 31045ef..fecefa2 100644 (file)
@@ -370,8 +370,11 @@ static int handle_fragments(struct net *net, struct sw_flow_key *key,
                skb_orphan(skb);
                memset(IP6CB(skb), 0, sizeof(struct inet6_skb_parm));
                err = nf_ct_frag6_gather(net, skb, user);
-               if (err)
+               if (err) {
+                       if (err != -EINPROGRESS)
+                               kfree_skb(skb);
                        return err;
+               }
 
                key->ip.proto = ipv6_hdr(skb)->nexthdr;
                ovs_cb.mru = IP6CB(skb)->frag_max_size;
index d2238b2..dd23323 100644 (file)
@@ -3648,19 +3648,25 @@ packet_setsockopt(struct socket *sock, int level, int optname, char __user *optv
 
                if (optlen != sizeof(val))
                        return -EINVAL;
-               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec)
-                       return -EBUSY;
                if (copy_from_user(&val, optval, sizeof(val)))
                        return -EFAULT;
                switch (val) {
                case TPACKET_V1:
                case TPACKET_V2:
                case TPACKET_V3:
-                       po->tp_version = val;
-                       return 0;
+                       break;
                default:
                        return -EINVAL;
                }
+               lock_sock(sk);
+               if (po->rx_ring.pg_vec || po->tx_ring.pg_vec) {
+                       ret = -EBUSY;
+               } else {
+                       po->tp_version = val;
+                       ret = 0;
+               }
+               release_sock(sk);
+               return ret;
        }
        case PACKET_RESERVE:
        {
@@ -4164,6 +4170,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
        /* Added to avoid minimal code churn */
        struct tpacket_req *req = &req_u->req;
 
+       lock_sock(sk);
        /* Opening a Tx-ring is NOT supported in TPACKET_V3 */
        if (!closing && tx_ring && (po->tp_version > TPACKET_V2)) {
                net_warn_ratelimited("Tx-ring is not supported.\n");
@@ -4245,7 +4252,6 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                        goto out;
        }
 
-       lock_sock(sk);
 
        /* Detach socket from network */
        spin_lock(&po->bind_lock);
@@ -4294,11 +4300,11 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                if (!tx_ring)
                        prb_shutdown_retire_blk_timer(po, rb_queue);
        }
-       release_sock(sk);
 
        if (pg_vec)
                free_pg_vec(pg_vec, order, req->tp_block_nr);
 out:
+       release_sock(sk);
        return err;
 }
 
index fcddacc..20e2923 100644 (file)
@@ -659,6 +659,8 @@ out_recv:
 out_pernet:
        unregister_pernet_subsys(&rds_tcp_net_ops);
 out_slab:
+       if (unregister_netdevice_notifier(&rds_tcp_dev_notifier))
+               pr_warn("could not unregister rds_tcp_dev_notifier\n");
        kmem_cache_destroy(rds_tcp_conn_slab);
 out:
        return ret;
index b54d56d..cf9b2fe 100644 (file)
@@ -108,6 +108,17 @@ static void tcf_pedit_cleanup(struct tc_action *a, int bind)
        kfree(keys);
 }
 
+static bool offset_valid(struct sk_buff *skb, int offset)
+{
+       if (offset > 0 && offset > skb->len)
+               return false;
+
+       if  (offset < 0 && -offset > skb_headroom(skb))
+               return false;
+
+       return true;
+}
+
 static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
                     struct tcf_result *res)
 {
@@ -134,6 +145,11 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
                        if (tkey->offmask) {
                                char *d, _d;
 
+                               if (!offset_valid(skb, off + tkey->at)) {
+                                       pr_info("tc filter pedit 'at' offset %d out of bounds\n",
+                                               off + tkey->at);
+                                       goto bad;
+                               }
                                d = skb_header_pointer(skb, off + tkey->at, 1,
                                                       &_d);
                                if (!d)
@@ -146,10 +162,10 @@ static int tcf_pedit(struct sk_buff *skb, const struct tc_action *a,
                                        " offset must be on 32 bit boundaries\n");
                                goto bad;
                        }
-                       if (offset > 0 && offset > skb->len) {
-                               pr_info("tc filter pedit"
-                                       " offset %d can't exceed pkt length %d\n",
-                                      offset, skb->len);
+
+                       if (!offset_valid(skb, off + offset)) {
+                               pr_info("tc filter pedit offset %d out of bounds\n",
+                                       offset);
                                goto bad;
                        }
 
index eb219b7..5877f60 100644 (file)
@@ -62,9 +62,6 @@ static unsigned long basic_get(struct tcf_proto *tp, u32 handle)
        struct basic_head *head = rtnl_dereference(tp->root);
        struct basic_filter *f;
 
-       if (head == NULL)
-               return 0UL;
-
        list_for_each_entry(f, &head->flist, link) {
                if (f->handle == handle) {
                        l = (unsigned long) f;
@@ -109,7 +106,6 @@ static bool basic_destroy(struct tcf_proto *tp, bool force)
                tcf_unbind_filter(tp, &f->res);
                call_rcu(&f->rcu, basic_delete_filter);
        }
-       RCU_INIT_POINTER(tp->root, NULL);
        kfree_rcu(head, rcu);
        return true;
 }
index bb1d5a4..0a47ba5 100644 (file)
@@ -292,7 +292,6 @@ static bool cls_bpf_destroy(struct tcf_proto *tp, bool force)
                call_rcu(&prog->rcu, __cls_bpf_delete_prog);
        }
 
-       RCU_INIT_POINTER(tp->root, NULL);
        kfree_rcu(head, rcu);
        return true;
 }
@@ -303,9 +302,6 @@ static unsigned long cls_bpf_get(struct tcf_proto *tp, u32 handle)
        struct cls_bpf_prog *prog;
        unsigned long ret = 0UL;
 
-       if (head == NULL)
-               return 0UL;
-
        list_for_each_entry(prog, &head->plist, link) {
                if (prog->handle == handle) {
                        ret = (unsigned long) prog;
index 85233c4..c1f2007 100644 (file)
@@ -137,11 +137,10 @@ static bool cls_cgroup_destroy(struct tcf_proto *tp, bool force)
 
        if (!force)
                return false;
-
-       if (head) {
-               RCU_INIT_POINTER(tp->root, NULL);
+       /* Head can still be NULL due to cls_cgroup_init(). */
+       if (head)
                call_rcu(&head->rcu, cls_cgroup_destroy_rcu);
-       }
+
        return true;
 }
 
index e396723..6575aba 100644 (file)
@@ -596,7 +596,6 @@ static bool flow_destroy(struct tcf_proto *tp, bool force)
                list_del_rcu(&f->list);
                call_rcu(&f->rcu, flow_destroy_filter);
        }
-       RCU_INIT_POINTER(tp->root, NULL);
        kfree_rcu(head, rcu);
        return true;
 }
index f6f40fb..9044424 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/init.h>
 #include <linux/module.h>
 #include <linux/rhashtable.h>
+#include <linux/workqueue.h>
 
 #include <linux/if_ether.h>
 #include <linux/in6.h>
@@ -64,7 +65,10 @@ struct cls_fl_head {
        bool mask_assigned;
        struct list_head filters;
        struct rhashtable_params ht_params;
-       struct rcu_head rcu;
+       union {
+               struct work_struct work;
+               struct rcu_head rcu;
+       };
 };
 
 struct cls_fl_filter {
@@ -269,6 +273,24 @@ static void fl_hw_update_stats(struct tcf_proto *tp, struct cls_fl_filter *f)
        dev->netdev_ops->ndo_setup_tc(dev, tp->q->handle, tp->protocol, &tc);
 }
 
+static void fl_destroy_sleepable(struct work_struct *work)
+{
+       struct cls_fl_head *head = container_of(work, struct cls_fl_head,
+                                               work);
+       if (head->mask_assigned)
+               rhashtable_destroy(&head->ht);
+       kfree(head);
+       module_put(THIS_MODULE);
+}
+
+static void fl_destroy_rcu(struct rcu_head *rcu)
+{
+       struct cls_fl_head *head = container_of(rcu, struct cls_fl_head, rcu);
+
+       INIT_WORK(&head->work, fl_destroy_sleepable);
+       schedule_work(&head->work);
+}
+
 static bool fl_destroy(struct tcf_proto *tp, bool force)
 {
        struct cls_fl_head *head = rtnl_dereference(tp->root);
@@ -282,10 +304,9 @@ static bool fl_destroy(struct tcf_proto *tp, bool force)
                list_del_rcu(&f->list);
                call_rcu(&f->rcu, fl_destroy_filter);
        }
-       RCU_INIT_POINTER(tp->root, NULL);
-       if (head->mask_assigned)
-               rhashtable_destroy(&head->ht);
-       kfree_rcu(head, rcu);
+
+       __module_get(THIS_MODULE);
+       call_rcu(&head->rcu, fl_destroy_rcu);
        return true;
 }
 
@@ -711,8 +732,9 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
                goto errout;
 
        if (fold) {
-               rhashtable_remove_fast(&head->ht, &fold->ht_node,
-                                      head->ht_params);
+               if (!tc_skip_sw(fold->flags))
+                       rhashtable_remove_fast(&head->ht, &fold->ht_node,
+                                              head->ht_params);
                fl_hw_destroy_filter(tp, (unsigned long)fold);
        }
 
@@ -739,8 +761,9 @@ static int fl_delete(struct tcf_proto *tp, unsigned long arg)
        struct cls_fl_head *head = rtnl_dereference(tp->root);
        struct cls_fl_filter *f = (struct cls_fl_filter *) arg;
 
-       rhashtable_remove_fast(&head->ht, &f->ht_node,
-                              head->ht_params);
+       if (!tc_skip_sw(f->flags))
+               rhashtable_remove_fast(&head->ht, &f->ht_node,
+                                      head->ht_params);
        list_del_rcu(&f->list);
        fl_hw_destroy_filter(tp, (unsigned long)f);
        tcf_unbind_filter(tp, &f->res);
index 25927b6..f935429 100644 (file)
@@ -114,7 +114,6 @@ static bool mall_destroy(struct tcf_proto *tp, bool force)
 
                call_rcu(&f->rcu, mall_destroy_filter);
        }
-       RCU_INIT_POINTER(tp->root, NULL);
        kfree_rcu(head, rcu);
        return true;
 }
index 4f05a19..322438f 100644 (file)
@@ -152,7 +152,8 @@ static int rsvp_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                return -1;
        nhptr = ip_hdr(skb);
 #endif
-
+       if (unlikely(!head))
+               return -1;
 restart:
 
 #if RSVP_DST_LEN == 4
index 96144bd..0751245 100644 (file)
@@ -543,7 +543,6 @@ static bool tcindex_destroy(struct tcf_proto *tp, bool force)
        walker.fn = tcindex_destroy_element;
        tcindex_walk(tp, &walker);
 
-       RCU_INIT_POINTER(tp->root, NULL);
        call_rcu(&p->rcu, __tcindex_destroy);
        return true;
 }
index 975dbeb..52d7476 100644 (file)
@@ -421,6 +421,10 @@ int tipc_enable_l2_media(struct net *net, struct tipc_bearer *b,
        dev = dev_get_by_name(net, driver_name);
        if (!dev)
                return -ENODEV;
+       if (tipc_mtu_bad(dev, 0)) {
+               dev_put(dev);
+               return -EINVAL;
+       }
 
        /* Associate TIPC bearer with L2 bearer */
        rcu_assign_pointer(b->media_ptr, dev);
@@ -610,8 +614,6 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
        if (!b)
                return NOTIFY_DONE;
 
-       b->mtu = dev->mtu;
-
        switch (evt) {
        case NETDEV_CHANGE:
                if (netif_carrier_ok(dev))
@@ -624,6 +626,11 @@ static int tipc_l2_device_event(struct notifier_block *nb, unsigned long evt,
                tipc_reset_bearer(net, b);
                break;
        case NETDEV_CHANGEMTU:
+               if (tipc_mtu_bad(dev, 0)) {
+                       bearer_disable(net, b);
+                       break;
+               }
+               b->mtu = dev->mtu;
                tipc_reset_bearer(net, b);
                break;
        case NETDEV_CHANGEADDR:
index 78892e2..278ff7f 100644 (file)
@@ -39,6 +39,7 @@
 
 #include "netlink.h"
 #include "core.h"
+#include "msg.h"
 #include <net/genetlink.h>
 
 #define MAX_MEDIA      3
@@ -59,6 +60,9 @@
 #define TIPC_MEDIA_TYPE_IB     2
 #define TIPC_MEDIA_TYPE_UDP    3
 
+/* minimum bearer MTU */
+#define TIPC_MIN_BEARER_MTU    (MAX_H_SIZE + INT_H_SIZE)
+
 /**
  * struct tipc_media_addr - destination address used by TIPC bearers
  * @value: address info (format defined by media)
@@ -215,4 +219,13 @@ void tipc_bearer_xmit(struct net *net, u32 bearer_id,
 void tipc_bearer_bc_xmit(struct net *net, u32 bearer_id,
                         struct sk_buff_head *xmitq);
 
+/* check if device MTU is too low for tipc headers */
+static inline bool tipc_mtu_bad(struct net_device *dev, unsigned int reserve)
+{
+       if (dev->mtu >= TIPC_MIN_BEARER_MTU + reserve)
+               return false;
+       netdev_warn(dev, "MTU too low for tipc bearer\n");
+       return true;
+}
+
 #endif /* _TIPC_BEARER_H */
index ecc1241..bda89bf 100644 (file)
@@ -47,8 +47,8 @@
 #include <linux/pkt_sched.h>
 
 struct tipc_stats {
-       u32 sent_info;          /* used in counting # sent packets */
-       u32 recv_info;          /* used in counting # recv'd packets */
+       u32 sent_pkts;
+       u32 recv_pkts;
        u32 sent_states;
        u32 recv_states;
        u32 sent_probes;
@@ -857,7 +857,6 @@ void tipc_link_reset(struct tipc_link *l)
        l->acked = 0;
        l->silent_intv_cnt = 0;
        l->rst_cnt = 0;
-       l->stats.recv_info = 0;
        l->stale_count = 0;
        l->bc_peer_is_up = false;
        memset(&l->mon_state, 0, sizeof(l->mon_state));
@@ -888,6 +887,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
        struct sk_buff_head *transmq = &l->transmq;
        struct sk_buff_head *backlogq = &l->backlogq;
        struct sk_buff *skb, *_skb, *bskb;
+       int pkt_cnt = skb_queue_len(list);
 
        /* Match msg importance against this and all higher backlog limits: */
        if (!skb_queue_empty(backlogq)) {
@@ -901,6 +901,11 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                return -EMSGSIZE;
        }
 
+       if (pkt_cnt > 1) {
+               l->stats.sent_fragmented++;
+               l->stats.sent_fragments += pkt_cnt;
+       }
+
        /* Prepare each packet for sending, and add to relevant queue: */
        while (skb_queue_len(list)) {
                skb = skb_peek(list);
@@ -920,6 +925,7 @@ int tipc_link_xmit(struct tipc_link *l, struct sk_buff_head *list,
                        __skb_queue_tail(xmitq, _skb);
                        TIPC_SKB_CB(skb)->ackers = l->ackers;
                        l->rcv_unacked = 0;
+                       l->stats.sent_pkts++;
                        seqno++;
                        continue;
                }
@@ -968,6 +974,7 @@ void tipc_link_advance_backlog(struct tipc_link *l, struct sk_buff_head *xmitq)
                msg_set_ack(hdr, ack);
                msg_set_bcast_ack(hdr, bc_ack);
                l->rcv_unacked = 0;
+               l->stats.sent_pkts++;
                seqno++;
        }
        l->snd_nxt = seqno;
@@ -1260,7 +1267,7 @@ int tipc_link_rcv(struct tipc_link *l, struct sk_buff *skb,
 
                /* Deliver packet */
                l->rcv_nxt++;
-               l->stats.recv_info++;
+               l->stats.recv_pkts++;
                if (!tipc_data_input(l, skb, l->inputq))
                        rc |= tipc_link_input(l, skb, l->inputq);
                if (unlikely(++l->rcv_unacked >= TIPC_MIN_LINK_WIN))
@@ -1800,10 +1807,6 @@ void tipc_link_set_queue_limits(struct tipc_link *l, u32 win)
 void tipc_link_reset_stats(struct tipc_link *l)
 {
        memset(&l->stats, 0, sizeof(l->stats));
-       if (!link_is_bc_sndlink(l)) {
-               l->stats.sent_info = l->snd_nxt;
-               l->stats.recv_info = l->rcv_nxt;
-       }
 }
 
 static void link_print(struct tipc_link *l, const char *str)
@@ -1867,12 +1870,12 @@ static int __tipc_nl_add_stats(struct sk_buff *skb, struct tipc_stats *s)
        };
 
        struct nla_map map[] = {
-               {TIPC_NLA_STATS_RX_INFO, s->recv_info},
+               {TIPC_NLA_STATS_RX_INFO, 0},
                {TIPC_NLA_STATS_RX_FRAGMENTS, s->recv_fragments},
                {TIPC_NLA_STATS_RX_FRAGMENTED, s->recv_fragmented},
                {TIPC_NLA_STATS_RX_BUNDLES, s->recv_bundles},
                {TIPC_NLA_STATS_RX_BUNDLED, s->recv_bundled},
-               {TIPC_NLA_STATS_TX_INFO, s->sent_info},
+               {TIPC_NLA_STATS_TX_INFO, 0},
                {TIPC_NLA_STATS_TX_FRAGMENTS, s->sent_fragments},
                {TIPC_NLA_STATS_TX_FRAGMENTED, s->sent_fragmented},
                {TIPC_NLA_STATS_TX_BUNDLES, s->sent_bundles},
@@ -1947,9 +1950,9 @@ int __tipc_nl_add_link(struct net *net, struct tipc_nl_msg *msg,
                goto attr_msg_full;
        if (nla_put_u32(msg->skb, TIPC_NLA_LINK_MTU, link->mtu))
                goto attr_msg_full;
-       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->rcv_nxt))
+       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, link->stats.recv_pkts))
                goto attr_msg_full;
-       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->snd_nxt))
+       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, link->stats.sent_pkts))
                goto attr_msg_full;
 
        if (tipc_link_is_up(link))
@@ -2004,12 +2007,12 @@ static int __tipc_nl_add_bc_link_stat(struct sk_buff *skb,
        };
 
        struct nla_map map[] = {
-               {TIPC_NLA_STATS_RX_INFO, stats->recv_info},
+               {TIPC_NLA_STATS_RX_INFO, stats->recv_pkts},
                {TIPC_NLA_STATS_RX_FRAGMENTS, stats->recv_fragments},
                {TIPC_NLA_STATS_RX_FRAGMENTED, stats->recv_fragmented},
                {TIPC_NLA_STATS_RX_BUNDLES, stats->recv_bundles},
                {TIPC_NLA_STATS_RX_BUNDLED, stats->recv_bundled},
-               {TIPC_NLA_STATS_TX_INFO, stats->sent_info},
+               {TIPC_NLA_STATS_TX_INFO, stats->sent_pkts},
                {TIPC_NLA_STATS_TX_FRAGMENTS, stats->sent_fragments},
                {TIPC_NLA_STATS_TX_FRAGMENTED, stats->sent_fragmented},
                {TIPC_NLA_STATS_TX_BUNDLES, stats->sent_bundles},
@@ -2076,9 +2079,9 @@ int tipc_nl_add_bc_link(struct net *net, struct tipc_nl_msg *msg)
                goto attr_msg_full;
        if (nla_put_string(msg->skb, TIPC_NLA_LINK_NAME, bcl->name))
                goto attr_msg_full;
-       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, bcl->rcv_nxt))
+       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_RX, 0))
                goto attr_msg_full;
-       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, bcl->snd_nxt))
+       if (nla_put_u32(msg->skb, TIPC_NLA_LINK_TX, 0))
                goto attr_msg_full;
 
        prop = nla_nest_start(msg->skb, TIPC_NLA_LINK_PROP);
index 78cab9c..b58dc95 100644 (file)
@@ -697,6 +697,11 @@ static int tipc_udp_enable(struct net *net, struct tipc_bearer *b,
                udp_conf.local_ip.s_addr = htonl(INADDR_ANY);
                udp_conf.use_udp_checksums = false;
                ub->ifindex = dev->ifindex;
+               if (tipc_mtu_bad(dev, sizeof(struct iphdr) +
+                                     sizeof(struct udphdr))) {
+                       err = -EINVAL;
+                       goto err;
+               }
                b->mtu = dev->mtu - sizeof(struct iphdr)
                        - sizeof(struct udphdr);
 #if IS_ENABLED(CONFIG_IPV6)
index fd69866..5bf7e1b 100644 (file)
@@ -1268,12 +1268,14 @@ static struct xfrm_policy *xfrm_sk_policy_lookup(const struct sock *sk, int dir,
                        err = security_xfrm_policy_lookup(pol->security,
                                                      fl->flowi_secid,
                                                      policy_to_flow_dir(dir));
-                       if (!err && !xfrm_pol_hold_rcu(pol))
-                               goto again;
-                       else if (err == -ESRCH)
+                       if (!err) {
+                               if (!xfrm_pol_hold_rcu(pol))
+                                       goto again;
+                       } else if (err == -ESRCH) {
                                pol = NULL;
-                       else
+                       } else {
                                pol = ERR_PTR(err);
+                       }
                } else
                        pol = NULL;
        }
index 0889209..671a1d0 100644 (file)
@@ -2450,7 +2450,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh)
 
 #ifdef CONFIG_COMPAT
        if (in_compat_syscall())
-               return -ENOTSUPP;
+               return -EOPNOTSUPP;
 #endif
 
        type = nlh->nlmsg_type;
index 90f44bd..dadd516 100644 (file)
@@ -113,7 +113,7 @@ static int (*bpf_skb_under_cgroup)(void *ctx, void *map, int index) =
 #define PT_REGS_FP(x) ((x)->gprs[11]) /* Works only with CONFIG_FRAME_POINTER */
 #define PT_REGS_RC(x) ((x)->gprs[2])
 #define PT_REGS_SP(x) ((x)->gprs[15])
-#define PT_REGS_IP(x) ((x)->ip)
+#define PT_REGS_IP(x) ((x)->psw.addr)
 
 #elif defined(__aarch64__)
 
index 774a681..ceabf31 100644 (file)
@@ -25,7 +25,7 @@ int do_sample(struct bpf_perf_event_data *ctx)
        u64 ip;
        u32 *value, init_val = 1;
 
-       ip = ctx->regs.ip;
+       ip = PT_REGS_IP(&ctx->regs);
        value = bpf_map_lookup_elem(&ip_map, &ip);
        if (value)
                *value += 1;
index 71a8ed3..41b6115 100644 (file)
@@ -50,7 +50,7 @@ int bpf_prog1(struct bpf_perf_event_data *ctx)
        key.userstack = bpf_get_stackid(ctx, &stackmap, USER_STACKID_FLAGS);
        if ((int)key.kernstack < 0 && (int)key.userstack < 0) {
                bpf_trace_printk(fmt, sizeof(fmt), cpu, ctx->sample_period,
-                                ctx->regs.ip);
+                                PT_REGS_IP(&ctx->regs));
                return 0;
        }
 
index ebced77..90a091b 100644 (file)
@@ -35,6 +35,8 @@ nconfig: $(obj)/nconf
 
 silentoldconfig: $(obj)/conf
        $(Q)mkdir -p include/config include/generated
+       $(Q)test -e include/generated/autoksyms.h || \
+           touch   include/generated/autoksyms.h
        $< $(silent) --$@ $(Kconfig)
 
 localyesconfig localmodconfig: $(obj)/streamline_config.pl $(obj)/conf
index 0190cb6..3fe4468 100644 (file)
@@ -304,7 +304,7 @@ struct snd_dbri {
        spinlock_t lock;
 
        struct dbri_dma *dma;   /* Pointer to our DMA block */
-       u32 dma_dvma;           /* DBRI visible DMA address */
+       dma_addr_t dma_dvma;    /* DBRI visible DMA address */
 
        void __iomem *regs;     /* dbri HW regs */
        int dbri_irqp;          /* intr queue pointer */
@@ -657,12 +657,14 @@ static void dbri_cmdwait(struct snd_dbri *dbri)
  */
 static s32 *dbri_cmdlock(struct snd_dbri *dbri, int len)
 {
+       u32 dvma_addr = (u32)dbri->dma_dvma;
+
        /* Space for 2 WAIT cmds (replaced later by 1 JUMP cmd) */
        len += 2;
        spin_lock(&dbri->cmdlock);
        if (dbri->cmdptr - dbri->dma->cmd + len < DBRI_NO_CMDS - 2)
                return dbri->cmdptr + 2;
-       else if (len < sbus_readl(dbri->regs + REG8) - dbri->dma_dvma)
+       else if (len < sbus_readl(dbri->regs + REG8) - dvma_addr)
                return dbri->dma->cmd;
        else
                printk(KERN_ERR "DBRI: no space for commands.");
@@ -680,6 +682,7 @@ static s32 *dbri_cmdlock(struct snd_dbri *dbri, int len)
  */
 static void dbri_cmdsend(struct snd_dbri *dbri, s32 *cmd, int len)
 {
+       u32 dvma_addr = (u32)dbri->dma_dvma;
        s32 tmp, addr;
        static int wait_id = 0;
 
@@ -689,7 +692,7 @@ static void dbri_cmdsend(struct snd_dbri *dbri, s32 *cmd, int len)
        *(cmd+1) = DBRI_CMD(D_WAIT, 1, wait_id);
 
        /* Replace the last command with JUMP */
-       addr = dbri->dma_dvma + (cmd - len - dbri->dma->cmd) * sizeof(s32);
+       addr = dvma_addr + (cmd - len - dbri->dma->cmd) * sizeof(s32);
        *(dbri->cmdptr+1) = addr;
        *(dbri->cmdptr) = DBRI_CMD(D_JUMP, 0, 0);
 
@@ -747,6 +750,7 @@ static void dbri_reset(struct snd_dbri *dbri)
 /* Lock must not be held before calling this */
 static void dbri_initialize(struct snd_dbri *dbri)
 {
+       u32 dvma_addr = (u32)dbri->dma_dvma;
        s32 *cmd;
        u32 dma_addr;
        unsigned long flags;
@@ -764,7 +768,7 @@ static void dbri_initialize(struct snd_dbri *dbri)
        /*
         * Initialize the interrupt ring buffer.
         */
-       dma_addr = dbri->dma_dvma + dbri_dma_off(intr, 0);
+       dma_addr = dvma_addr + dbri_dma_off(intr, 0);
        dbri->dma->intr[0] = dma_addr;
        dbri->dbri_irqp = 1;
        /*
@@ -778,7 +782,7 @@ static void dbri_initialize(struct snd_dbri *dbri)
        dbri->cmdptr = cmd;
        *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
        *(cmd++) = DBRI_CMD(D_WAIT, 1, 0);
-       dma_addr = dbri->dma_dvma + dbri_dma_off(cmd, 0);
+       dma_addr = dvma_addr + dbri_dma_off(cmd, 0);
        sbus_writel(dma_addr, dbri->regs + REG8);
        spin_unlock(&dbri->cmdlock);
 
@@ -1077,6 +1081,7 @@ static void recv_fixed(struct snd_dbri *dbri, int pipe, volatile __u32 *ptr)
 static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period)
 {
        struct dbri_streaminfo *info = &dbri->stream_info[streamno];
+       u32 dvma_addr = (u32)dbri->dma_dvma;
        __u32 dvma_buffer;
        int desc;
        int len;
@@ -1177,7 +1182,7 @@ static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period)
                else {
                        dbri->next_desc[last_desc] = desc;
                        dbri->dma->desc[last_desc].nda =
-                           dbri->dma_dvma + dbri_dma_off(desc, desc);
+                           dvma_addr + dbri_dma_off(desc, desc);
                }
 
                last_desc = desc;
@@ -1192,7 +1197,7 @@ static int setup_descs(struct snd_dbri *dbri, int streamno, unsigned int period)
        }
 
        dbri->dma->desc[last_desc].nda =
-           dbri->dma_dvma + dbri_dma_off(desc, first_desc);
+           dvma_addr + dbri_dma_off(desc, first_desc);
        dbri->next_desc[last_desc] = first_desc;
        dbri->pipes[info->pipe].first_desc = first_desc;
        dbri->pipes[info->pipe].desc = first_desc;
@@ -1697,6 +1702,7 @@ interrupts are disabled.
 static void xmit_descs(struct snd_dbri *dbri)
 {
        struct dbri_streaminfo *info;
+       u32 dvma_addr = (u32)dbri->dma_dvma;
        s32 *cmd;
        unsigned long flags;
        int first_td;
@@ -1718,7 +1724,7 @@ static void xmit_descs(struct snd_dbri *dbri)
                        *(cmd++) = DBRI_CMD(D_SDP, 0,
                                            dbri->pipes[info->pipe].sdp
                                            | D_SDP_P | D_SDP_EVERY | D_SDP_C);
-                       *(cmd++) = dbri->dma_dvma +
+                       *(cmd++) = dvma_addr +
                                   dbri_dma_off(desc, first_td);
                        dbri_cmdsend(dbri, cmd, 2);
 
@@ -1740,7 +1746,7 @@ static void xmit_descs(struct snd_dbri *dbri)
                        *(cmd++) = DBRI_CMD(D_SDP, 0,
                                            dbri->pipes[info->pipe].sdp
                                            | D_SDP_P | D_SDP_EVERY | D_SDP_C);
-                       *(cmd++) = dbri->dma_dvma +
+                       *(cmd++) = dvma_addr +
                                   dbri_dma_off(desc, first_td);
                        dbri_cmdsend(dbri, cmd, 2);
 
@@ -2539,7 +2545,7 @@ static int snd_dbri_create(struct snd_card *card,
        if (!dbri->dma)
                return -ENOMEM;
 
-       dprintk(D_GEN, "DMA Cmd Block 0x%p (0x%08x)\n",
+       dprintk(D_GEN, "DMA Cmd Block 0x%p (%pad)\n",
                dbri->dma, dbri->dma_dvma);
 
        /* Map the registers into memory. */
index 0a063af..9bab867 100644 (file)
@@ -50,8 +50,10 @@ void vgic_v2_process_maintenance(struct kvm_vcpu *vcpu)
 
                        WARN_ON(cpuif->vgic_lr[lr] & GICH_LR_STATE);
 
-                       kvm_notify_acked_irq(vcpu->kvm, 0,
-                                            intid - VGIC_NR_PRIVATE_IRQS);
+                       /* Only SPIs require notification */
+                       if (vgic_valid_spi(vcpu->kvm, intid))
+                               kvm_notify_acked_irq(vcpu->kvm, 0,
+                                                    intid - VGIC_NR_PRIVATE_IRQS);
                }
        }
 
index 9f0dae3..5c9f974 100644 (file)
@@ -41,8 +41,10 @@ void vgic_v3_process_maintenance(struct kvm_vcpu *vcpu)
 
                        WARN_ON(cpuif->vgic_lr[lr] & ICH_LR_STATE);
 
-                       kvm_notify_acked_irq(vcpu->kvm, 0,
-                                            intid - VGIC_NR_PRIVATE_IRQS);
+                       /* Only SPIs require notification */
+                       if (vgic_valid_spi(vcpu->kvm, intid))
+                               kvm_notify_acked_irq(vcpu->kvm, 0,
+                                                    intid - VGIC_NR_PRIVATE_IRQS);
                }
 
                /*
index 5c36034..7f9ee29 100644 (file)
@@ -2889,10 +2889,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
 
        ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
        if (ret < 0) {
-               ops->destroy(dev);
                mutex_lock(&kvm->lock);
                list_del(&dev->vm_node);
                mutex_unlock(&kvm->lock);
+               ops->destroy(dev);
                return ret;
        }