diff options
author | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-25 13:11:52 +0200 |
---|---|---|
committer | Greg Kroah-Hartman <gregkh@linuxfoundation.org> | 2014-09-25 13:11:52 +0200 |
commit | 346e2e4a8b47089f4319f114ec9ac3a95b5f0ac8 (patch) | |
tree | 0e824d68b72969127abcad85e82b468ed4e23237 | |
parent | 5caf6ae5ce880ec15448b310e47a9515ebb7e808 (diff) | |
parent | 4f0eb5d7efe375859b15c97f453113a242bf057b (diff) |
Merge tag 'phy-for_3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/kishon/linux-phy into usb-next
Kishon writes:
Adds 3 new PHY drivers stih407, stih41x and rcar gen2 PHY. It also
includes miscellaneous cleanup of other PHY drivers.
Conflicts:
MAINTAINERS
170 files changed, 2254 insertions, 907 deletions
diff --git a/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt b/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt new file mode 100644 index 000000000000..1ef8228db73b --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-stih407-usb.txt @@ -0,0 +1,30 @@ +ST STiH407 USB PHY controller + +This file documents the dt bindings for the usb picoPHY driver which is the PHY for both USB2 and USB3 +host controllers (when controlling usb2/1.1 devices) available on STiH407 SoC family from STMicroelectronics. + +Required properties: +- compatible : should be "st,stih407-usb2-phy" +- reg : contain the offset and length of the system configuration registers + used as glue logic to control & parameter phy +- reg-names : the names of the system configuration registers in "reg", should be "param" and "reg" +- st,syscfg : sysconfig register to manage phy parameter at driver level +- resets : list of phandle and reset specifier pairs. There should be two entries, one + for the whole phy and one for the port +- reset-names : list of reset signal names. Should be "global" and "port" +See: Documentation/devicetree/bindings/reset/st,sti-powerdown.txt +See: Documentation/devicetree/bindings/reset/reset.txt + +Example: + +usb2_picophy0: usbpicophy@f8 { + compatible = "st,stih407-usb2-phy"; + reg = <0xf8 0x04>, /* syscfg 5062 */ + <0xf4 0x04>; /* syscfg 5061 */ + reg-names = "param", "ctrl"; + #phy-cells = <0>; + st,syscfg = <&syscfg_core>; + resets = <&softreset STIH407_PICOPHY_SOFTRESET>, + <&picophyreset STIH407_PICOPHY0_RESET>; + reset-names = "global", "port"; +}; diff --git a/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt b/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt new file mode 100644 index 000000000000..00944a05ee6b --- /dev/null +++ b/Documentation/devicetree/bindings/phy/phy-stih41x-usb.txt @@ -0,0 +1,24 @@ +STMicroelectronics STiH41x USB PHY binding +------------------------------------------ + +This file contains documentation for the usb phy found in STiH415/6 SoCs from +STMicroelectronics. + +Required properties: +- compatible : should be "st,stih416-usb-phy" or "st,stih415-usb-phy" +- st,syscfg : should be a phandle of the syscfg node +- clock-names : must contain "osc_phy" +- clocks : must contain an entry for each name in clock-names. +See: Documentation/devicetree/bindings/clock/clock-bindings.txt +- #phy-cells : must be 0 for this phy +See: Documentation/devicetree/bindings/phy/phy-bindings.txt + +Example: + +usb2_phy: usb2phy@0 { + compatible = "st,stih416-usb-phy"; + #phy-cell = <0>; + st,syscfg = <&syscfg_rear>; + clocks = <&clk_sysin>; + clock-names = "osc_phy"; +}; diff --git a/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt b/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt new file mode 100644 index 000000000000..00fc52a034b7 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/rcar-gen2-phy.txt @@ -0,0 +1,51 @@ +* Renesas R-Car generation 2 USB PHY + +This file provides information on what the device node for the R-Car generation +2 USB PHY contains. + +Required properties: +- compatible: "renesas,usb-phy-r8a7790" if the device is a part of R8A7790 SoC. + "renesas,usb-phy-r8a7791" if the device is a part of R8A7791 SoC. +- reg: offset and length of the register block. +- #address-cells: number of address cells for the USB channel subnodes, must + be <1>. +- #size-cells: number of size cells for the USB channel subnodes, must be <0>. +- clocks: clock phandle and specifier pair. +- clock-names: string, clock input name, must be "usbhs". + +The USB PHY device tree node should have the subnodes corresponding to the USB +channels. These subnodes must contain the following properties: +- reg: the USB controller selector; see the table below for the values. +- #phy-cells: see phy-bindings.txt in the same directory, must be <1>. + +The phandle's argument in the PHY specifier is the USB controller selector for +the USB channel; see the selector meanings below: + ++-----------+---------------+---------------+ +|\ Selector | | | ++ --------- + 0 | 1 | +| Channel \| | | ++-----------+---------------+---------------+ +| 0 | PCI EHCI/OHCI | HS-USB | +| 2 | PCI EHCI/OHCI | xHCI | ++-----------+---------------+---------------+ + +Example (Lager board): + + usb-phy@e6590100 { + compatible = "renesas,usb-phy-r8a7790"; + reg = <0 0xe6590100 0 0x100>; + #address-cells = <1>; + #size-cells = <0>; + clocks = <&mstp7_clks R8A7790_CLK_HSUSB>; + clock-names = "usbhs"; + + usb-channel@0 { + reg = <0>; + #phy-cells = <1>; + }; + usb-channel@2 { + reg = <2>; + #phy-cells = <1>; + }; + }; diff --git a/Documentation/devicetree/bindings/phy/samsung-phy.txt b/Documentation/devicetree/bindings/phy/samsung-phy.txt index 7a6feea2a48b..15e0f2c7130f 100644 --- a/Documentation/devicetree/bindings/phy/samsung-phy.txt +++ b/Documentation/devicetree/bindings/phy/samsung-phy.txt @@ -17,8 +17,11 @@ Samsung EXYNOS SoC series Display Port PHY ------------------------------------------------- Required properties: -- compatible : should be "samsung,exynos5250-dp-video-phy"; -- reg : offset and length of the Display Port PHY register set; +- compatible : should be one of the following supported values: + - "samsung,exynos5250-dp-video-phy" + - "samsung,exynos5420-dp-video-phy" +- samsung,pmu-syscon: phandle for PMU system controller interface, used to + control pmu registers for power isolation. - #phy-cells : from the generic PHY bindings, must be 0; Samsung S5P/EXYNOS SoC series USB PHY diff --git a/Documentation/networking/filter.txt b/Documentation/networking/filter.txt index c48a9704bda8..d16f424c5e8d 100644 --- a/Documentation/networking/filter.txt +++ b/Documentation/networking/filter.txt @@ -462,9 +462,9 @@ JIT compiler ------------ The Linux kernel has a built-in BPF JIT compiler for x86_64, SPARC, PowerPC, -ARM and s390 and can be enabled through CONFIG_BPF_JIT. The JIT compiler is -transparently invoked for each attached filter from user space or for internal -kernel users if it has been previously enabled by root: +ARM, MIPS and s390 and can be enabled through CONFIG_BPF_JIT. The JIT compiler +is transparently invoked for each attached filter from user space or for +internal kernel users if it has been previously enabled by root: echo 1 > /proc/sys/net/core/bpf_jit_enable diff --git a/MAINTAINERS b/MAINTAINERS index 51ecce8b785a..df0d0a858826 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -1392,12 +1392,14 @@ S: Maintained F: arch/arm/mach-sti/ F: arch/arm/boot/dts/sti* F: drivers/clocksource/arm_global_timer.c -F: drivers/reset/sti/ -F: drivers/pinctrl/pinctrl-st.c -F: drivers/media/rc/st_rc.c F: drivers/i2c/busses/i2c-st.c -F: drivers/tty/serial/st-asc.c +F: drivers/media/rc/st_rc.c F: drivers/mmc/host/sdhci-st.c +F: drivers/phy/phy-stih407-usb.c +F: drivers/phy/phy-stih41x-usb.c +F: drivers/pinctrl/pinctrl-st.c +F: drivers/reset/sti/ +F: drivers/tty/serial/st-asc.c F: drivers/usb/dwc3/dwc3-st.c F: drivers/usb/host/ehci-st.c F: drivers/usb/host/ohci-st.c diff --git a/arch/ia64/configs/bigsur_defconfig b/arch/ia64/configs/bigsur_defconfig index 4c4ac163c600..b6bda1838629 100644 --- a/arch/ia64/configs/bigsur_defconfig +++ b/arch/ia64/configs/bigsur_defconfig @@ -1,4 +1,3 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_LOG_BUF_SHIFT=16 @@ -6,6 +5,8 @@ CONFIG_PROFILING=y CONFIG_OPROFILE=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_SGI_PARTITION=y CONFIG_IA64_DIG=y CONFIG_SMP=y CONFIG_NR_CPUS=2 @@ -51,9 +52,6 @@ CONFIG_DM_MIRROR=m CONFIG_DM_ZERO=m CONFIG_NETDEVICES=y CONFIG_DUMMY=y -CONFIG_NET_ETHERNET=y -CONFIG_MII=y -CONFIG_NET_PCI=y CONFIG_INPUT_EVDEV=y CONFIG_SERIAL_8250=y CONFIG_SERIAL_8250_CONSOLE=y @@ -85,7 +83,6 @@ CONFIG_EXT3_FS=y CONFIG_XFS_FS=y CONFIG_XFS_QUOTA=y CONFIG_XFS_POSIX_ACL=y -CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m CONFIG_ISO9660_FS=m CONFIG_JOLIET=y @@ -95,17 +92,13 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y +CONFIG_NFS_V4=m CONFIG_NFSD=m CONFIG_NFSD_V4=y CONFIG_CIFS=m CONFIG_CIFS_STATS=y CONFIG_CIFS_XATTR=y CONFIG_CIFS_POSIX=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_SGI_PARTITION=y -CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_ISO8859_1=y CONFIG_NLS_UTF8=m diff --git a/arch/ia64/configs/generic_defconfig b/arch/ia64/configs/generic_defconfig index e8ed3ae70aae..81f686dee53c 100644 --- a/arch/ia64/configs/generic_defconfig +++ b/arch/ia64/configs/generic_defconfig @@ -1,4 +1,3 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_IKCONFIG=y @@ -6,13 +5,13 @@ CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=20 CONFIG_CGROUPS=y CONFIG_CPUSETS=y -CONFIG_SYSFS_DEPRECATED_V2=y CONFIG_BLK_DEV_INITRD=y CONFIG_KALLSYMS_ALL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y -# CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_SGI_PARTITION=y CONFIG_MCKINLEY=y CONFIG_IA64_PAGE_SIZE_64KB=y CONFIG_IA64_CYCLONE=y @@ -29,14 +28,13 @@ CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m CONFIG_ACPI_DOCK=y CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_CONTAINER=y CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_ACPI=y +CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y CONFIG_IP_MULTICAST=y -CONFIG_ARPD=y CONFIG_SYN_COOKIES=y # CONFIG_IPV6 is not set CONFIG_UEVENT_HELPER_PATH="/sbin/hotplug" @@ -82,16 +80,13 @@ CONFIG_FUSION_FC=m CONFIG_FUSION_SAS=y CONFIG_NETDEVICES=y CONFIG_DUMMY=m -CONFIG_NET_ETHERNET=y +CONFIG_NETCONSOLE=y +CONFIG_TIGON3=y CONFIG_NET_TULIP=y CONFIG_TULIP=m -CONFIG_NET_PCI=y -CONFIG_NET_VENDOR_INTEL=y CONFIG_E100=m CONFIG_E1000=y CONFIG_IGB=y -CONFIG_TIGON3=y -CONFIG_NETCONSOLE=y # CONFIG_SERIO_SERPORT is not set CONFIG_GAMEPORT=m CONFIG_SERIAL_NONSTANDARD=y @@ -151,6 +146,7 @@ CONFIG_USB_STORAGE=m CONFIG_INFINIBAND=m CONFIG_INFINIBAND_MTHCA=m CONFIG_INFINIBAND_IPOIB=m +CONFIG_INTEL_IOMMU=y CONFIG_MSPEC=m CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y @@ -164,7 +160,6 @@ CONFIG_REISERFS_FS_XATTR=y CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y CONFIG_XFS_FS=y -CONFIG_AUTOFS_FS=m CONFIG_AUTOFS4_FS=m CONFIG_ISO9660_FS=m CONFIG_JOLIET=y @@ -175,16 +170,10 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y +CONFIG_NFS_V4=m CONFIG_NFSD=m CONFIG_NFSD_V4=y -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y CONFIG_CIFS=m -CONFIG_PARTITION_ADVANCED=y -CONFIG_SGI_PARTITION=y -CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m @@ -225,11 +214,7 @@ CONFIG_NLS_UTF8=m CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y -# CONFIG_RCU_CPU_STALL_DETECTOR is not set -CONFIG_SYSCTL_SYSCALL_CHECK=y -CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MD5=y # CONFIG_CRYPTO_ANSI_CPRNG is not set CONFIG_CRC_T10DIF=y -CONFIG_INTEL_IOMMU=y diff --git a/arch/ia64/configs/gensparse_defconfig b/arch/ia64/configs/gensparse_defconfig index d663efd1e4db..5b4fcdd51457 100644 --- a/arch/ia64/configs/gensparse_defconfig +++ b/arch/ia64/configs/gensparse_defconfig @@ -1,4 +1,3 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_IKCONFIG=y @@ -9,6 +8,8 @@ CONFIG_KALLSYMS_ALL=y CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_PARTITION_ADVANCED=y +CONFIG_SGI_PARTITION=y CONFIG_MCKINLEY=y CONFIG_IA64_CYCLONE=y CONFIG_SMP=y @@ -24,14 +25,12 @@ CONFIG_BINFMT_MISC=m CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_CONTAINER=m CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y CONFIG_IP_MULTICAST=y -CONFIG_ARPD=y CONFIG_SYN_COOKIES=y # CONFIG_IPV6 is not set CONFIG_BLK_DEV_LOOP=m @@ -71,15 +70,12 @@ CONFIG_FUSION_SPI=y CONFIG_FUSION_FC=m CONFIG_NETDEVICES=y CONFIG_DUMMY=m -CONFIG_NET_ETHERNET=y +CONFIG_NETCONSOLE=y +CONFIG_TIGON3=y CONFIG_NET_TULIP=y CONFIG_TULIP=m -CONFIG_NET_PCI=y -CONFIG_NET_VENDOR_INTEL=y CONFIG_E100=m CONFIG_E1000=y -CONFIG_TIGON3=y -CONFIG_NETCONSOLE=y # CONFIG_SERIO_SERPORT is not set CONFIG_GAMEPORT=m CONFIG_SERIAL_NONSTANDARD=y @@ -146,7 +142,6 @@ CONFIG_REISERFS_FS_XATTR=y CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y CONFIG_XFS_FS=y -CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y CONFIG_ISO9660_FS=m CONFIG_JOLIET=y @@ -157,16 +152,10 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y +CONFIG_NFS_V4=m CONFIG_NFSD=m CONFIG_NFSD_V4=y -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y CONFIG_CIFS=m -CONFIG_PARTITION_ADVANCED=y -CONFIG_SGI_PARTITION=y -CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m diff --git a/arch/ia64/configs/sim_defconfig b/arch/ia64/configs/sim_defconfig index b4548a3e82d5..f0f69fdbddae 100644 --- a/arch/ia64/configs/sim_defconfig +++ b/arch/ia64/configs/sim_defconfig @@ -1,13 +1,12 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_IKCONFIG=y CONFIG_IKCONFIG_PROC=y CONFIG_LOG_BUF_SHIFT=16 -# CONFIG_CC_OPTIMIZE_FOR_SIZE is not set CONFIG_MODULES=y CONFIG_MODULE_UNLOAD=y CONFIG_MODULE_FORCE_UNLOAD=y CONFIG_MODVERSIONS=y +CONFIG_PARTITION_ADVANCED=y CONFIG_IA64_HP_SIM=y CONFIG_MCKINLEY=y CONFIG_IA64_PAGE_SIZE_64KB=y @@ -27,7 +26,6 @@ CONFIG_BLK_DEV_LOOP=y CONFIG_BLK_DEV_RAM=y CONFIG_SCSI=y CONFIG_BLK_DEV_SD=y -CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y CONFIG_SCSI_SPI_ATTRS=y @@ -49,8 +47,6 @@ CONFIG_HUGETLBFS=y CONFIG_NFS_FS=y CONFIG_NFSD=y CONFIG_NFSD_V3=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_EFI_PARTITION=y +CONFIG_DEBUG_INFO=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y -CONFIG_DEBUG_INFO=y diff --git a/arch/ia64/configs/tiger_defconfig b/arch/ia64/configs/tiger_defconfig index c8a3f40e77f6..192ed157c9ce 100644 --- a/arch/ia64/configs/tiger_defconfig +++ b/arch/ia64/configs/tiger_defconfig @@ -1,4 +1,3 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_POSIX_MQUEUE=y CONFIG_IKCONFIG=y @@ -11,6 +10,8 @@ CONFIG_MODULE_UNLOAD=y CONFIG_MODVERSIONS=y CONFIG_MODULE_SRCVERSION_ALL=y # CONFIG_BLK_DEV_BSG is not set +CONFIG_PARTITION_ADVANCED=y +CONFIG_SGI_PARTITION=y CONFIG_IA64_DIG=y CONFIG_MCKINLEY=y CONFIG_IA64_PAGE_SIZE_64KB=y @@ -29,14 +30,12 @@ CONFIG_BINFMT_MISC=m CONFIG_ACPI_BUTTON=m CONFIG_ACPI_FAN=m CONFIG_ACPI_PROCESSOR=m -CONFIG_ACPI_CONTAINER=m CONFIG_HOTPLUG_PCI=y -CONFIG_HOTPLUG_PCI_ACPI=m +CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y CONFIG_IP_MULTICAST=y -CONFIG_ARPD=y CONFIG_SYN_COOKIES=y # CONFIG_IPV6 is not set CONFIG_BLK_DEV_LOOP=m @@ -53,6 +52,7 @@ CONFIG_BLK_DEV_SD=y CONFIG_CHR_DEV_ST=m CONFIG_BLK_DEV_SR=m CONFIG_CHR_DEV_SG=m +CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_QLOGIC_1280=y CONFIG_MD=y @@ -72,15 +72,12 @@ CONFIG_FUSION_FC=y CONFIG_FUSION_CTL=y CONFIG_NETDEVICES=y CONFIG_DUMMY=m -CONFIG_NET_ETHERNET=y +CONFIG_NETCONSOLE=y +CONFIG_TIGON3=y CONFIG_NET_TULIP=y CONFIG_TULIP=m -CONFIG_NET_PCI=y -CONFIG_NET_VENDOR_INTEL=y CONFIG_E100=m CONFIG_E1000=y -CONFIG_TIGON3=y -CONFIG_NETCONSOLE=y # CONFIG_SERIO_SERPORT is not set CONFIG_GAMEPORT=m CONFIG_SERIAL_NONSTANDARD=y @@ -118,7 +115,6 @@ CONFIG_REISERFS_FS_XATTR=y CONFIG_REISERFS_FS_POSIX_ACL=y CONFIG_REISERFS_FS_SECURITY=y CONFIG_XFS_FS=y -CONFIG_AUTOFS_FS=y CONFIG_AUTOFS4_FS=y CONFIG_ISO9660_FS=m CONFIG_JOLIET=y @@ -129,16 +125,10 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_NFS_FS=m -CONFIG_NFS_V3=y -CONFIG_NFS_V4=y +CONFIG_NFS_V4=m CONFIG_NFSD=m CONFIG_NFSD_V4=y -CONFIG_SMB_FS=m -CONFIG_SMB_NLS_DEFAULT=y CONFIG_CIFS=m -CONFIG_PARTITION_ADVANCED=y -CONFIG_SGI_PARTITION=y -CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=m CONFIG_NLS_CODEPAGE_775=m @@ -180,6 +170,5 @@ CONFIG_MAGIC_SYSRQ=y CONFIG_DEBUG_KERNEL=y CONFIG_DEBUG_MUTEXES=y CONFIG_IA64_GRANULE_16MB=y -CONFIG_CRYPTO_ECB=m CONFIG_CRYPTO_PCBC=m CONFIG_CRYPTO_MD5=y diff --git a/arch/ia64/configs/zx1_defconfig b/arch/ia64/configs/zx1_defconfig index 54bc72eda30d..b504c8e2fd52 100644 --- a/arch/ia64/configs/zx1_defconfig +++ b/arch/ia64/configs/zx1_defconfig @@ -1,9 +1,9 @@ -CONFIG_EXPERIMENTAL=y CONFIG_SYSVIPC=y CONFIG_BSD_PROCESS_ACCT=y CONFIG_BLK_DEV_INITRD=y CONFIG_KPROBES=y CONFIG_MODULES=y +CONFIG_PARTITION_ADVANCED=y CONFIG_IA64_HP_ZX1=y CONFIG_MCKINLEY=y CONFIG_SMP=y @@ -18,6 +18,7 @@ CONFIG_EFI_VARS=y CONFIG_BINFMT_MISC=y CONFIG_HOTPLUG_PCI=y CONFIG_HOTPLUG_PCI_ACPI=y +CONFIG_NET=y CONFIG_PACKET=y CONFIG_UNIX=y CONFIG_INET=y @@ -37,9 +38,9 @@ CONFIG_CHR_DEV_OSST=y CONFIG_BLK_DEV_SR=y CONFIG_BLK_DEV_SR_VENDOR=y CONFIG_CHR_DEV_SG=y -CONFIG_SCSI_MULTI_LUN=y CONFIG_SCSI_CONSTANTS=y CONFIG_SCSI_LOGGING=y +CONFIG_SCSI_FC_ATTRS=y CONFIG_SCSI_SYM53C8XX_2=y CONFIG_SCSI_QLOGIC_1280=y CONFIG_FUSION=y @@ -48,18 +49,15 @@ CONFIG_FUSION_FC=y CONFIG_FUSION_CTL=m CONFIG_NETDEVICES=y CONFIG_DUMMY=y -CONFIG_NET_ETHERNET=y +CONFIG_TIGON3=y CONFIG_NET_TULIP=y CONFIG_TULIP=y CONFIG_TULIP_MWI=y CONFIG_TULIP_MMIO=y CONFIG_TULIP_NAPI=y CONFIG_TULIP_NAPI_HW_MITIGATION=y -CONFIG_NET_PCI=y -CONFIG_NET_VENDOR_INTEL=y CONFIG_E100=y CONFIG_E1000=y -CONFIG_TIGON3=y CONFIG_INPUT_JOYDEV=y CONFIG_INPUT_EVDEV=y # CONFIG_INPUT_KEYBOARD is not set @@ -100,7 +98,6 @@ CONFIG_USB_STORAGE=y CONFIG_EXT2_FS=y CONFIG_EXT2_FS_XATTR=y CONFIG_EXT3_FS=y -CONFIG_AUTOFS_FS=y CONFIG_ISO9660_FS=y CONFIG_JOLIET=y CONFIG_UDF_FS=y @@ -110,12 +107,9 @@ CONFIG_PROC_KCORE=y CONFIG_TMPFS=y CONFIG_HUGETLBFS=y CONFIG_NFS_FS=y -CONFIG_NFS_V3=y CONFIG_NFS_V4=y CONFIG_NFSD=y CONFIG_NFSD_V3=y -CONFIG_PARTITION_ADVANCED=y -CONFIG_EFI_PARTITION=y CONFIG_NLS_CODEPAGE_437=y CONFIG_NLS_CODEPAGE_737=y CONFIG_NLS_CODEPAGE_775=y diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 571aab064936..f42e35e42790 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -53,6 +53,7 @@ */ unsigned long empty_zero_page, zero_page_mask; EXPORT_SYMBOL_GPL(empty_zero_page); +EXPORT_SYMBOL(zero_page_mask); /* * Not static inline because used by IP27 special magic initialization code diff --git a/arch/parisc/Makefile b/arch/parisc/Makefile index 7187664034c3..5db8882f732c 100644 --- a/arch/parisc/Makefile +++ b/arch/parisc/Makefile @@ -48,7 +48,12 @@ cflags-y := -pipe # These flags should be implied by an hppa-linux configuration, but they # are not in gcc 3.2. -cflags-y += -mno-space-regs -mfast-indirect-calls +cflags-y += -mno-space-regs + +# -mfast-indirect-calls is only relevant for 32-bit kernels. +ifndef CONFIG_64BIT +cflags-y += -mfast-indirect-calls +endif # Currently we save and restore fpregs on all kernel entry/interruption paths. # If that gets optimized, we might need to disable the use of fpregs in the diff --git a/arch/parisc/kernel/ptrace.c b/arch/parisc/kernel/ptrace.c index 3bab72462ab5..92438c21d453 100644 --- a/arch/parisc/kernel/ptrace.c +++ b/arch/parisc/kernel/ptrace.c @@ -17,6 +17,7 @@ #include <linux/user.h> #include <linux/personality.h> #include <linux/security.h> +#include <linux/seccomp.h> #include <linux/compat.h> #include <linux/signal.h> #include <linux/audit.h> @@ -271,10 +272,7 @@ long do_syscall_trace_enter(struct pt_regs *regs) long ret = 0; /* Do the secure computing check first. */ - if (secure_computing(regs->gr[20])) { - /* seccomp failures shouldn't expose any additional code. */ - return -1; - } + secure_computing_strict(regs->gr[20]); if (test_thread_flag(TIF_SYSCALL_TRACE) && tracehook_report_syscall_entry(regs)) diff --git a/arch/s390/mm/init.c b/arch/s390/mm/init.c index 0c1073ed1e84..c7235e01fd67 100644 --- a/arch/s390/mm/init.c +++ b/arch/s390/mm/init.c @@ -43,6 +43,7 @@ pgd_t swapper_pg_dir[PTRS_PER_PGD] __attribute__((__aligned__(PAGE_SIZE))); unsigned long empty_zero_page, zero_page_mask; EXPORT_SYMBOL(empty_zero_page); +EXPORT_SYMBOL(zero_page_mask); static void __init setup_zero_pages(void) { diff --git a/arch/sparc/net/bpf_jit_comp.c b/arch/sparc/net/bpf_jit_comp.c index 1f76c22a6a75..51ae87b483e0 100644 --- a/arch/sparc/net/bpf_jit_comp.c +++ b/arch/sparc/net/bpf_jit_comp.c @@ -234,12 +234,18 @@ do { BUILD_BUG_ON(FIELD_SIZEOF(STRUCT, FIELD) != sizeof(u8)); \ __emit_load8(BASE, STRUCT, FIELD, DEST); \ } while (0) -#define emit_ldmem(OFF, DEST) \ -do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(DEST); \ +#ifdef CONFIG_SPARC64 +#define BIAS (STACK_BIAS - 4) +#else +#define BIAS (-4) +#endif + +#define emit_ldmem(OFF, DEST) \ +do { *prog++ = LD32I | RS1(SP) | S13(BIAS - (OFF)) | RD(DEST); \ } while (0) -#define emit_stmem(OFF, SRC) \ -do { *prog++ = LD32I | RS1(FP) | S13(-(OFF)) | RD(SRC); \ +#define emit_stmem(OFF, SRC) \ +do { *prog++ = ST32I | RS1(SP) | S13(BIAS - (OFF)) | RD(SRC); \ } while (0) #ifdef CONFIG_SMP @@ -615,10 +621,11 @@ void bpf_jit_compile(struct bpf_prog *fp) case BPF_ANC | SKF_AD_VLAN_TAG: case BPF_ANC | SKF_AD_VLAN_TAG_PRESENT: emit_skb_load16(vlan_tci, r_A); - if (code == (BPF_ANC | SKF_AD_VLAN_TAG)) { - emit_andi(r_A, VLAN_VID_MASK, r_A); + if (code != (BPF_ANC | SKF_AD_VLAN_TAG)) { + emit_alu_K(SRL, 12); + emit_andi(r_A, 1, r_A); } else { - emit_loadimm(VLAN_TAG_PRESENT, r_TMP); + emit_loadimm(~VLAN_TAG_PRESENT, r_TMP); emit_and(r_A, r_TMP, r_A); } break; @@ -630,15 +637,19 @@ void bpf_jit_compile(struct bpf_prog *fp) emit_loadimm(K, r_X); break; case BPF_LD | BPF_MEM: + seen |= SEEN_MEM; emit_ldmem(K * 4, r_A); break; case BPF_LDX | BPF_MEM: + seen |= SEEN_MEM | SEEN_XREG; emit_ldmem(K * 4, r_X); break; case BPF_ST: + seen |= SEEN_MEM; emit_stmem(K * 4, r_A); break; case BPF_STX: + seen |= SEEN_MEM | SEEN_XREG; emit_stmem(K * 4, r_X); break; diff --git a/arch/x86/boot/compressed/head_32.S b/arch/x86/boot/compressed/head_32.S index d6b8aa4c986c..cbed1407a5cd 100644 --- a/arch/x86/boot/compressed/head_32.S +++ b/arch/x86/boot/compressed/head_32.S @@ -30,33 +30,6 @@ #include <asm/boot.h> #include <asm/asm-offsets.h> -/* - * Adjust our own GOT - * - * The relocation base must be in %ebx - * - * It is safe to call this macro more than once, because in some of the - * code paths multiple invocations are inevitable, e.g. via the efi* - * entry points. - * - * Relocation is only performed the first time. - */ -.macro FIXUP_GOT - cmpb $1, got_fixed(%ebx) - je 2f - - leal _got(%ebx), %edx - leal _egot(%ebx), %ecx -1: - cmpl %ecx, %edx - jae 2f - addl %ebx, (%edx) - addl $4, %edx - jmp 1b -2: - movb $1, got_fixed(%ebx) -.endm - __HEAD ENTRY(startup_32) #ifdef CONFIG_EFI_STUB @@ -83,9 +56,6 @@ ENTRY(efi_pe_entry) add %esi, 88(%eax) pushl %eax - movl %esi, %ebx - FIXUP_GOT - call make_boot_params cmpl $0, %eax je fail @@ -111,10 +81,6 @@ ENTRY(efi32_stub_entry) leal efi32_config(%esi), %eax add %esi, 88(%eax) pushl %eax - - movl %esi, %ebx - FIXUP_GOT - 2: call efi_main cmpl $0, %eax @@ -224,7 +190,19 @@ relocated: shrl $2, %ecx rep stosl - FIXUP_GOT +/* + * Adjust our own GOT + */ + leal _got(%ebx), %edx + leal _egot(%ebx), %ecx +1: + cmpl %ecx, %edx + jae 2f + addl %ebx, (%edx) + addl $4, %edx + jmp 1b +2: + /* * Do the decompression, and jump to the new kernel.. */ @@ -247,12 +225,8 @@ relocated: xorl %ebx, %ebx jmp *%eax - .data -/* Have we relocated the GOT? */ -got_fixed: - .byte 0 - #ifdef CONFIG_EFI_STUB + .data efi32_config: .fill 11,8,0 .long efi_call_phys diff --git a/arch/x86/boot/compressed/head_64.S b/arch/x86/boot/compressed/head_64.S index 50f69c7eaaf4..2884e0c3e8a5 100644 --- a/arch/x86/boot/compressed/head_64.S +++ b/arch/x86/boot/compressed/head_64.S @@ -32,33 +32,6 @@ #include <asm/processor-flags.h> #include <asm/asm-offsets.h> -/* - * Adjust our own GOT - * - * The relocation base must be in %rbx - * - * It is safe to call this macro more than once, because in some of the - * code paths multiple invocations are inevitable, e.g. via the efi* - * entry points. - * - * Relocation is only performed the first time. - */ -.macro FIXUP_GOT - cmpb $1, got_fixed(%rip) - je 2f - - leaq _got(%rip), %rdx - leaq _egot(%rip), %rcx -1: - cmpq %rcx, %rdx - jae 2f - addq %rbx, (%rdx) - addq $8, %rdx - jmp 1b -2: - movb $1, got_fixed(%rip) -.endm - __HEAD .code32 ENTRY(startup_32) @@ -279,13 +252,10 @@ ENTRY(efi_pe_entry) subq $1b, %rbp /* - * Relocate efi_config->call() and the GOT entries. + * Relocate efi_config->call(). */ addq %rbp, efi64_config+88(%rip) - movq %rbp, %rbx - FIXUP_GOT - movq %rax, %rdi call make_boot_params cmpq $0,%rax @@ -301,13 +271,10 @@ handover_entry: subq $1b, %rbp /* - * Relocate efi_config->call() and the GOT entries. + * Relocate efi_config->call(). */ movq efi_config(%rip), %rax addq %rbp, 88(%rax) - - movq %rbp, %rbx - FIXUP_GOT 2: movq efi_config(%rip), %rdi call efi_main @@ -418,8 +385,19 @@ relocated: shrq $3, %rcx rep stosq - FIXUP_GOT - +/* + * Adjust our own GOT + */ + leaq _got(%rip), %rdx + leaq _egot(%rip), %rcx +1: + cmpq %rcx, %rdx + jae 2f + addq %rbx, (%rdx) + addq $8, %rdx + jmp 1b +2: + /* * Do the decompression, and jump to the new kernel.. */ @@ -459,10 +437,6 @@ gdt: .quad 0x0000000000000000 /* TS continued */ gdt_end: -/* Have we relocated the GOT? */ -got_fixed: - .byte 0 - #ifdef CONFIG_EFI_STUB efi_config: .quad 0 diff --git a/block/blk-exec.c b/block/blk-exec.c index f4d27b12c90b..9924725fa50d 100644 --- a/block/blk-exec.c +++ b/block/blk-exec.c @@ -56,6 +56,7 @@ void blk_execute_rq_nowait(struct request_queue *q, struct gendisk *bd_disk, bool is_pm_resume; WARN_ON(irqs_disabled()); + WARN_ON(rq->cmd_type == REQ_TYPE_FS); rq->rq_disk = bd_disk; rq->end_io = done; diff --git a/block/blk-mq.c b/block/blk-mq.c index 383ea0cb1f0a..c88e6089746d 100644 --- a/block/blk-mq.c +++ b/block/blk-mq.c @@ -203,7 +203,6 @@ __blk_mq_alloc_request(struct blk_mq_alloc_data *data, int rw) if (tag != BLK_MQ_TAG_FAIL) { rq = data->hctx->tags->rqs[tag]; - rq->cmd_flags = 0; if (blk_mq_tag_busy(data->hctx)) { rq->cmd_flags = REQ_MQ_INFLIGHT; atomic_inc(&data->hctx->nr_active); @@ -258,6 +257,7 @@ static void __blk_mq_free_request(struct blk_mq_hw_ctx *hctx, if (rq->cmd_flags & REQ_MQ_INFLIGHT) atomic_dec(&hctx->nr_active); + rq->cmd_flags = 0; clear_bit(REQ_ATOM_STARTED, &rq->atomic_flags); blk_mq_put_tag(hctx, tag, &ctx->last_tag); @@ -393,6 +393,12 @@ static void blk_mq_start_request(struct request *rq, bool last) blk_add_timer(rq); /* + * Ensure that ->deadline is visible before set the started + * flag and clear the completed flag. + */ + smp_mb__before_atomic(); + + /* * Mark us as started and clear complete. Complete might have been * set if requeue raced with timeout, which then marked it as * complete. So be sure to clear complete again when we start @@ -473,7 +479,11 @@ static void blk_mq_requeue_work(struct work_struct *work) blk_mq_insert_request(rq, false, false, false); } - blk_mq_run_queues(q, false); + /* + * Use the start variant of queue running here, so that running + * the requeue work will kick stopped queues. + */ + blk_mq_start_hw_queues(q); } void blk_mq_add_to_requeue_list(struct request *rq, bool at_head) @@ -957,14 +967,9 @@ void blk_mq_insert_request(struct request *rq, bool at_head, bool run_queue, hctx = q->mq_ops->map_queue(q, ctx->cpu); - if (rq->cmd_flags & (REQ_FLUSH | REQ_FUA) && - !(rq->cmd_flags & (REQ_FLUSH_SEQ))) { - blk_insert_flush(rq); - } else { - spin_lock(&ctx->lock); - __blk_mq_insert_request(hctx, rq, at_head); - spin_unlock(&ctx->lock); - } + spin_lock(&ctx->lock); + __blk_mq_insert_request(hctx, rq, at_head); + spin_unlock(&ctx->lock); if (run_queue) blk_mq_run_hw_queue(hctx, async); @@ -1404,6 +1409,8 @@ static struct blk_mq_tags *blk_mq_init_rq_map(struct blk_mq_tag_set *set, left -= to_do * rq_size; for (j = 0; j < to_do; j++) { tags->rqs[i] = p; + tags->rqs[i]->atomic_flags = 0; + tags->rqs[i]->cmd_flags = 0; if (set->ops->init_request) { if (set->ops->init_request(set->driver_data, tags->rqs[i], hctx_idx, i, @@ -1956,7 +1963,6 @@ out_unwind: while (--i >= 0) blk_mq_free_rq_map(set, set->tags[i], i); - set->tags = NULL; return -ENOMEM; } diff --git a/block/genhd.c b/block/genhd.c index 09da5e4a8e03..e6723bd4d7a1 100644 --- a/block/genhd.c +++ b/block/genhd.c @@ -445,8 +445,6 @@ int blk_alloc_devt(struct hd_struct *part, dev_t *devt) */ void blk_free_devt(dev_t devt) { - might_sleep(); - if (devt == MKDEV(0, 0)) return; diff --git a/drivers/clk/at91/clk-slow.c b/drivers/clk/at91/clk-slow.c index 0300c46ee247..32f7c1b36204 100644 --- a/drivers/clk/at91/clk-slow.c +++ b/drivers/clk/at91/clk-slow.c @@ -447,7 +447,7 @@ void __init of_at91sam9260_clk_slow_setup(struct device_node *np, int i; num_parents = of_count_phandle_with_args(np, "clocks", "#clock-cells"); - if (num_parents <= 0 || num_parents > 1) + if (num_parents != 2) return; for (i = 0; i < num_parents; ++i) { diff --git a/drivers/clk/clk-efm32gg.c b/drivers/clk/clk-efm32gg.c index bac2ddf49d02..73a8d0ff530c 100644 --- a/drivers/clk/clk-efm32gg.c +++ b/drivers/clk/clk-efm32gg.c @@ -22,7 +22,7 @@ static struct clk_onecell_data clk_data = { .clk_num = ARRAY_SIZE(clk), }; -static int __init efm32gg_cmu_init(struct device_node *np) +static void __init efm32gg_cmu_init(struct device_node *np) { int i; void __iomem *base; @@ -33,7 +33,7 @@ static int __init efm32gg_cmu_init(struct device_node *np) base = of_iomap(np, 0); if (!base) { pr_warn("Failed to map address range for efm32gg,cmu node\n"); - return -EADDRNOTAVAIL; + return; } clk[clk_HFXO] = clk_register_fixed_rate(NULL, "HFXO", NULL, @@ -76,6 +76,6 @@ static int __init efm32gg_cmu_init(struct device_node *np) clk[clk_HFPERCLKDAC0] = clk_register_gate(NULL, "HFPERCLK.DAC0", "HFXO", 0, base + CMU_HFPERCLKEN0, 17, 0, NULL); - return of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); + of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data); } CLK_OF_DECLARE(efm32ggcmu, "efm32gg,cmu", efm32gg_cmu_init); diff --git a/drivers/clk/clk.c b/drivers/clk/clk.c index b76fa69b44cb..bacc06ff939b 100644 --- a/drivers/clk/clk.c +++ b/drivers/clk/clk.c @@ -1467,6 +1467,7 @@ static struct clk *clk_propagate_rate_change(struct clk *clk, unsigned long even static void clk_change_rate(struct clk *clk) { struct clk *child; + struct hlist_node *tmp; unsigned long old_rate; unsigned long best_parent_rate = 0; bool skip_set_rate = false; @@ -1502,7 +1503,11 @@ static void clk_change_rate(struct clk *clk) if (clk->notifier_count && old_rate != clk->rate) __clk_notify(clk, POST_RATE_CHANGE, old_rate, clk->rate); - hlist_for_each_entry(child, &clk->children, child_node) { + /* + * Use safe iteration, as change_rate can actually swap parents + * for certain clock types. + */ + hlist_for_each_entry_safe(child, tmp, &clk->children, child_node) { /* Skip children who will be reparented to another clock */ if (child->new_parent && child->new_parent != clk) continue; diff --git a/drivers/clk/qcom/gcc-ipq806x.c b/drivers/clk/qcom/gcc-ipq806x.c index 4032e510d9aa..3b83b7dd78c7 100644 --- a/drivers/clk/qcom/gcc-ipq806x.c +++ b/drivers/clk/qcom/gcc-ipq806x.c @@ -1095,7 +1095,7 @@ static struct clk_branch prng_clk = { }; static const struct freq_tbl clk_tbl_sdc[] = { - { 144000, P_PXO, 5, 18,625 }, + { 200000, P_PXO, 2, 2, 125 }, { 400000, P_PLL8, 4, 1, 240 }, { 16000000, P_PLL8, 4, 1, 6 }, { 17070000, P_PLL8, 1, 2, 45 }, diff --git a/drivers/clk/rockchip/clk-rk3288.c b/drivers/clk/rockchip/clk-rk3288.c index 0d8c6c59a75e..b22a2d2f21e9 100644 --- a/drivers/clk/rockchip/clk-rk3288.c +++ b/drivers/clk/rockchip/clk-rk3288.c @@ -545,7 +545,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(PCLK_PWM, "pclk_pwm", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 0, GFLAGS), GATE(PCLK_TIMER, "pclk_timer", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 1, GFLAGS), GATE(PCLK_I2C0, "pclk_i2c0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 2, GFLAGS), - GATE(PCLK_I2C1, "pclk_i2c1", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS), + GATE(PCLK_I2C2, "pclk_i2c2", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 3, GFLAGS), GATE(0, "pclk_ddrupctl0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 14, GFLAGS), GATE(0, "pclk_publ0", "pclk_cpu", 0, RK3288_CLKGATE_CON(10), 15, GFLAGS), GATE(0, "pclk_ddrupctl1", "pclk_cpu", 0, RK3288_CLKGATE_CON(11), 0, GFLAGS), @@ -603,7 +603,7 @@ static struct rockchip_clk_branch rk3288_clk_branches[] __initdata = { GATE(PCLK_I2C4, "pclk_i2c4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 15, GFLAGS), GATE(PCLK_UART3, "pclk_uart3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 11, GFLAGS), GATE(PCLK_UART4, "pclk_uart4", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 12, GFLAGS), - GATE(PCLK_I2C2, "pclk_i2c2", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 13, GFLAGS), + GATE(PCLK_I2C1, "pclk_i2c1", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 13, GFLAGS), GATE(PCLK_I2C3, "pclk_i2c3", "pclk_peri", 0, RK3288_CLKGATE_CON(6), 14, GFLAGS), GATE(PCLK_SARADC, "pclk_saradc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 1, GFLAGS), GATE(PCLK_TSADC, "pclk_tsadc", "pclk_peri", 0, RK3288_CLKGATE_CON(7), 2, GFLAGS), diff --git a/drivers/clk/ti/clk-dra7-atl.c b/drivers/clk/ti/clk-dra7-atl.c index 4a65b410e4d5..af29359677da 100644 --- a/drivers/clk/ti/clk-dra7-atl.c +++ b/drivers/clk/ti/clk-dra7-atl.c @@ -139,9 +139,13 @@ static long atl_clk_round_rate(struct clk_hw *hw, unsigned long rate, static int atl_clk_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct dra7_atl_desc *cdesc = to_atl_desc(hw); + struct dra7_atl_desc *cdesc; u32 divider; + if (!hw || !rate) + return -EINVAL; + + cdesc = to_atl_desc(hw); divider = ((parent_rate + rate / 2) / rate) - 1; if (divider > DRA7_ATL_DIVIDER_MASK) divider = DRA7_ATL_DIVIDER_MASK; diff --git a/drivers/clk/ti/divider.c b/drivers/clk/ti/divider.c index e6aa10db7bba..a837f703be65 100644 --- a/drivers/clk/ti/divider.c +++ b/drivers/clk/ti/divider.c @@ -211,11 +211,16 @@ static long ti_clk_divider_round_rate(struct clk_hw *hw, unsigned long rate, static int ti_clk_divider_set_rate(struct clk_hw *hw, unsigned long rate, unsigned long parent_rate) { - struct clk_divider *divider = to_clk_divider(hw); + struct clk_divider *divider; unsigned int div, value; unsigned long flags = 0; u32 val; + if (!hw || !rate) + return -EINVAL; + + divider = to_clk_divider(hw); + div = DIV_ROUND_UP(parent_rate, rate); value = _get_val(divider, div); diff --git a/drivers/hwmon/fam15h_power.c b/drivers/hwmon/fam15h_power.c index 4a7cbfad1d74..fcdbde4ec692 100644 --- a/drivers/hwmon/fam15h_power.c +++ b/drivers/hwmon/fam15h_power.c @@ -93,13 +93,29 @@ static ssize_t show_power_crit(struct device *dev, } static DEVICE_ATTR(power1_crit, S_IRUGO, show_power_crit, NULL); +static umode_t fam15h_power_is_visible(struct kobject *kobj, + struct attribute *attr, + int index) +{ + /* power1_input is only reported for Fam15h, Models 00h-0fh */ + if (attr == &dev_attr_power1_input.attr && + (boot_cpu_data.x86 != 0x15 || boot_cpu_data.x86_model > 0xf)) + return 0; + + return attr->mode; +} + static struct attribute *fam15h_power_attrs[] = { &dev_attr_power1_input.attr, &dev_attr_power1_crit.attr, NULL }; -ATTRIBUTE_GROUPS(fam15h_power); +static const struct attribute_group fam15h_power_group = { + .attrs = fam15h_power_attrs, + .is_visible = fam15h_power_is_visible, +}; +__ATTRIBUTE_GROUPS(fam15h_power); static bool fam15h_power_is_internal_node0(struct pci_dev *f4) { @@ -216,7 +232,9 @@ static int fam15h_power_probe(struct pci_dev *pdev, static const struct pci_device_id fam15h_power_id_table[] = { { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_NB_F4) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_15H_M30H_NB_F4) }, { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) }, + { PCI_VDEVICE(AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) }, {} }; MODULE_DEVICE_TABLE(pci, fam15h_power_id_table); diff --git a/drivers/hwmon/tmp103.c b/drivers/hwmon/tmp103.c index e42964f07f67..ad571ec795a3 100644 --- a/drivers/hwmon/tmp103.c +++ b/drivers/hwmon/tmp103.c @@ -145,7 +145,7 @@ static int tmp103_probe(struct i2c_client *client, } i2c_set_clientdata(client, regmap); - hwmon_dev = hwmon_device_register_with_groups(dev, client->name, + hwmon_dev = devm_hwmon_device_register_with_groups(dev, client->name, regmap, tmp103_groups); return PTR_ERR_OR_ZERO(hwmon_dev); } diff --git a/drivers/infiniband/core/umem.c b/drivers/infiniband/core/umem.c index a3a2e9c1639b..df0c4f605a21 100644 --- a/drivers/infiniband/core/umem.c +++ b/drivers/infiniband/core/umem.c @@ -105,6 +105,7 @@ struct ib_umem *ib_umem_get(struct ib_ucontext *context, unsigned long addr, umem->length = size; umem->offset = addr & ~PAGE_MASK; umem->page_size = PAGE_SIZE; + umem->pid = get_task_pid(current, PIDTYPE_PID); /* * We ask for writable memory if any access flags other than * "remote read" are set. "Local write" and "remote write" @@ -198,6 +199,7 @@ out: if (ret < 0) { if (need_release) __ib_umem_release(context->device, umem, 0); + put_pid(umem->pid); kfree(umem); } else current->mm->pinned_vm = locked; @@ -230,15 +232,19 @@ void ib_umem_release(struct ib_umem *umem) { struct ib_ucontext *context = umem->context; struct mm_struct *mm; + struct task_struct *task; unsigned long diff; __ib_umem_release(umem->context->device, umem, 1); - mm = get_task_mm(current); - if (!mm) { - kfree(umem); - return; - } + task = get_pid_task(umem->pid, PIDTYPE_PID); + put_pid(umem->pid); + if (!task) + goto out; + mm = get_task_mm(task); + put_task_struct(task); + if (!mm) + goto out; diff = PAGE_ALIGN(umem->length + umem->offset) >> PAGE_SHIFT; @@ -262,9 +268,10 @@ void ib_umem_release(struct ib_umem *umem) } else down_write(&mm->mmap_sem); - current->mm->pinned_vm -= diff; + mm->pinned_vm -= diff; up_write(&mm->mmap_sem); mmput(mm); +out: kfree(umem); } EXPORT_SYMBOL(ib_umem_release); diff --git a/drivers/infiniband/core/uverbs_marshall.c b/drivers/infiniband/core/uverbs_marshall.c index e7bee46868d1..abd97247443e 100644 --- a/drivers/infiniband/core/uverbs_marshall.c +++ b/drivers/infiniband/core/uverbs_marshall.c @@ -140,5 +140,9 @@ void ib_copy_path_rec_from_user(struct ib_sa_path_rec *dst, dst->packet_life_time = src->packet_life_time; dst->preference = src->preference; dst->packet_life_time_selector = src->packet_life_time_selector; + + memset(dst->smac, 0, sizeof(dst->smac)); + memset(dst->dmac, 0, sizeof(dst->dmac)); + dst->vlan_id = 0xffff; } EXPORT_SYMBOL(ib_copy_path_rec_from_user); diff --git a/drivers/infiniband/hw/ipath/ipath_user_pages.c b/drivers/infiniband/hw/ipath/ipath_user_pages.c index dc66c4506916..1da1252dcdb3 100644 --- a/drivers/infiniband/hw/ipath/ipath_user_pages.c +++ b/drivers/infiniband/hw/ipath/ipath_user_pages.c @@ -54,7 +54,7 @@ static void __ipath_release_user_pages(struct page **p, size_t num_pages, /* call with current->mm->mmap_sem held */ static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages, - struct page **p, struct vm_area_struct **vma) + struct page **p) { unsigned long lock_limit; size_t got; @@ -74,7 +74,7 @@ static int __ipath_get_user_pages(unsigned long start_page, size_t num_pages, ret = get_user_pages(current, current->mm, start_page + got * PAGE_SIZE, num_pages - got, 1, 1, - p + got, vma); + p + got, NULL); if (ret < 0) goto bail_release; } @@ -165,7 +165,7 @@ int ipath_get_user_pages(unsigned long start_page, size_t num_pages, down_write(¤t->mm->mmap_sem); - ret = __ipath_get_user_pages(start_page, num_pages, p, NULL); + ret = __ipath_get_user_pages(start_page, num_pages, p); up_write(¤t->mm->mmap_sem); diff --git a/drivers/infiniband/hw/mlx4/main.c b/drivers/infiniband/hw/mlx4/main.c index af8256353c7d..bda5994ceb68 100644 --- a/drivers/infiniband/hw/mlx4/main.c +++ b/drivers/infiniband/hw/mlx4/main.c @@ -59,6 +59,7 @@ #define MLX4_IB_FLOW_MAX_PRIO 0xFFF #define MLX4_IB_FLOW_QPN_MASK 0xFFFFFF +#define MLX4_IB_CARD_REV_A0 0xA0 MODULE_AUTHOR("Roland Dreier"); MODULE_DESCRIPTION("Mellanox ConnectX HCA InfiniBand driver"); @@ -119,6 +120,17 @@ static int check_flow_steering_support(struct mlx4_dev *dev) return dmfs; } +static int num_ib_ports(struct mlx4_dev *dev) +{ + int ib_ports = 0; + int i; + + mlx4_foreach_port(i, dev, MLX4_PORT_TYPE_IB) + ib_ports++; + + return ib_ports; +} + static int mlx4_ib_query_device(struct ib_device *ibdev, struct ib_device_attr *props) { @@ -126,6 +138,7 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, struct ib_smp *in_mad = NULL; struct ib_smp *out_mad = NULL; int err = -ENOMEM; + int have_ib_ports; in_mad = kzalloc(sizeof *in_mad, GFP_KERNEL); out_mad = kmalloc(sizeof *out_mad, GFP_KERNEL); @@ -142,6 +155,8 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, memset(props, 0, sizeof *props); + have_ib_ports = num_ib_ports(dev->dev); + props->fw_ver = dev->dev->caps.fw_ver; props->device_cap_flags = IB_DEVICE_CHANGE_PHY_PORT | IB_DEVICE_PORT_ACTIVE_EVENT | @@ -152,13 +167,15 @@ static int mlx4_ib_query_device(struct ib_device *ibdev, props->device_cap_flags |= IB_DEVICE_BAD_PKEY_CNTR; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BAD_QKEY_CNTR) props->device_cap_flags |= IB_DEVICE_BAD_QKEY_CNTR; - if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM) + if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_APM && have_ib_ports) props->device_cap_flags |= IB_DEVICE_AUTO_PATH_MIG; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_UD_AV_PORT) props->device_cap_flags |= IB_DEVICE_UD_AV_PORT_ENFORCE; if (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_IPOIB_CSUM) props->device_cap_flags |= IB_DEVICE_UD_IP_CSUM; - if (dev->dev->caps.max_gso_sz && dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH) + if (dev->dev->caps.max_gso_sz && + (dev->dev->rev_id != MLX4_IB_CARD_REV_A0) && + (dev->dev->caps.flags & MLX4_DEV_CAP_FLAG_BLH)) props->device_cap_flags |= IB_DEVICE_UD_TSO; if (dev->dev->caps.bmme_flags & MLX4_BMME_FLAG_RESERVED_LKEY) props->device_cap_flags |= IB_DEVICE_LOCAL_DMA_LKEY; @@ -357,7 +374,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port, props->state = IB_PORT_DOWN; props->phys_state = state_to_phys_state(props->state); props->active_mtu = IB_MTU_256; - spin_lock(&iboe->lock); + spin_lock_bh(&iboe->lock); ndev = iboe->netdevs[port - 1]; if (!ndev) goto out_unlock; @@ -369,7 +386,7 @@ static int eth_link_query_port(struct ib_device *ibdev, u8 port, IB_PORT_ACTIVE : IB_PORT_DOWN; props->phys_state = state_to_phys_state(props->state); out_unlock: - spin_unlock(&iboe->lock); + spin_unlock_bh(&iboe->lock); out: mlx4_free_cmd_mailbox(mdev->dev, mailbox); return err; @@ -811,11 +828,11 @@ int mlx4_ib_add_mc(struct mlx4_ib_dev *mdev, struct mlx4_ib_qp *mqp, if (!mqp->port) return 0; - spin_lock(&mdev->iboe.lock); + spin_lock_bh(&mdev->iboe.lock); ndev = mdev->iboe.netdevs[mqp->port - 1]; if (ndev) dev_hold(ndev); - spin_unlock(&mdev->iboe.lock); + spin_unlock_bh(&mdev->iboe.lock); if (ndev) { ret = 1; @@ -1292,11 +1309,11 @@ static int mlx4_ib_mcg_detach(struct ib_qp *ibqp, union ib_gid *gid, u16 lid) mutex_lock(&mqp->mutex); ge = find_gid_entry(mqp, gid->raw); if (ge) { - spin_lock(&mdev->iboe.lock); + spin_lock_bh(&mdev->iboe.lock); ndev = ge->added ? mdev->iboe.netdevs[ge->port - 1] : NULL; if (ndev) dev_hold(ndev); - spin_unlock(&mdev->iboe.lock); + spin_unlock_bh(&mdev->iboe.lock); if (ndev) dev_put(ndev); list_del(&ge->list); @@ -1417,6 +1434,9 @@ static void update_gids_task(struct work_struct *work) int err; struct mlx4_dev *dev = gw->dev->dev; + if (!gw->dev->ib_active) + return; + mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) { pr_warn("update gid table failed %ld\n", PTR_ERR(mailbox)); @@ -1447,6 +1467,9 @@ static void reset_gids_task(struct work_struct *work) int err; struct mlx4_dev *dev = gw->dev->dev; + if (!gw->dev->ib_active) + return; + mailbox = mlx4_alloc_cmd_mailbox(dev); if (IS_ERR(mailbox)) { pr_warn("reset gid table failed\n"); @@ -1581,7 +1604,7 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev, return 0; iboe = &ibdev->iboe; - spin_lock(&iboe->lock); + spin_lock_bh(&iboe->lock); for (port = 1; port <= ibdev->dev->caps.num_ports; ++port) if ((netif_is_bond_master(real_dev) && @@ -1591,7 +1614,7 @@ static int mlx4_ib_addr_event(int event, struct net_device *event_netdev, update_gid_table(ibdev, port, gid, event == NETDEV_DOWN, 0); - spin_unlock(&iboe->lock); + spin_unlock_bh(&iboe->lock); return 0; } @@ -1664,13 +1687,21 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev, new_smac = mlx4_mac_to_u64(dev->dev_addr); read_unlock(&dev_base_lock); + atomic64_set(&ibdev->iboe.mac[port - 1], new_smac); + + /* no need for update QP1 and mac registration in non-SRIOV */ + if (!mlx4_is_mfunc(ibdev->dev)) + return; + mutex_lock(&ibdev->qp1_proxy_lock[port - 1]); qp = ibdev->qp1_proxy[port - 1]; if (qp) { int new_smac_index; - u64 old_smac = qp->pri.smac; + u64 old_smac; struct mlx4_update_qp_params update_params; + mutex_lock(&qp->mutex); + old_smac = qp->pri.smac; if (new_smac == old_smac) goto unlock; @@ -1680,22 +1711,25 @@ static void mlx4_ib_update_qps(struct mlx4_ib_dev *ibdev, goto unlock; update_params.smac_index = new_smac_index; - if (mlx4_update_qp(ibdev->dev, &qp->mqp, MLX4_UPDATE_QP_SMAC, + if (mlx4_update_qp(ibdev->dev, qp->mqp.qpn, MLX4_UPDATE_QP_SMAC, &update_params)) { release_mac = new_smac; goto unlock; } - + /* if old port was zero, no mac was yet registered for this QP */ + if (qp->pri.smac_port) + release_mac = old_smac; qp->pri.smac = new_smac; + qp->pri.smac_port = port; qp->pri.smac_index = new_smac_index; - - release_mac = old_smac; } unlock: - mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]); if (release_mac != MLX4_IB_INVALID_MAC) mlx4_unregister_mac(ibdev->dev, port, release_mac); + if (qp) + mutex_unlock(&qp->mutex); + mutex_unlock(&ibdev->qp1_proxy_lock[port - 1]); } static void mlx4_ib_get_dev_addr(struct net_device *dev, @@ -1706,6 +1740,7 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, struct inet6_dev *in6_dev; union ib_gid *pgid; struct inet6_ifaddr *ifp; + union ib_gid default_gid; #endif union ib_gid gid; @@ -1726,12 +1761,15 @@ static void mlx4_ib_get_dev_addr(struct net_device *dev, in_dev_put(in_dev); } #if IS_ENABLED(CONFIG_IPV6) + mlx4_make_default_gid(dev, &default_gid); /* IPv6 gids */ in6_dev = in6_dev_get(dev); if (in6_dev) { read_lock_bh(&in6_dev->lock); list_for_each_entry(ifp, &in6_dev->addr_list, if_list) { pgid = (union ib_gid *)&ifp->addr; + if (!memcmp(pgid, &default_gid, sizeof(*pgid))) + continue; update_gid_table(ibdev, port, pgid, 0, 0); } read_unlock_bh(&in6_dev->lock); @@ -1753,24 +1791,33 @@ static int mlx4_ib_init_gid_table(struct mlx4_ib_dev *ibdev) struct net_device *dev; struct mlx4_ib_iboe *iboe = &ibdev->iboe; int i; + int err = 0; - for (i = 1; i <= ibdev->num_ports; ++i) - if (reset_gid_table(ibdev, i)) - return -1; + for (i = 1; i <= ibdev->num_ports; ++i) { + if (rdma_port_get_link_layer(&ibdev->ib_dev, i) == + IB_LINK_LAYER_ETHERNET) { + err = reset_gid_table(ibdev, i); + if (err) + goto out; + } + } read_lock(&dev_base_lock); - spin_lock(&iboe->lock); + spin_lock_bh(&iboe->lock); for_each_netdev(&init_net, dev) { u8 port = mlx4_ib_get_dev_port(dev, ibdev); - if (port) + /* port will be non-zero only for ETH ports */ + if (port) { + mlx4_ib_set_default_gid(ibdev, dev, port); mlx4_ib_get_dev_addr(dev, ibdev, port); + } } - spin_unlock(&iboe->lock); + spin_unlock_bh(&iboe->lock); read_unlock(&dev_base_lock); - - return 0; +out: + return err; } static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev, @@ -1784,7 +1831,7 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev, iboe = &ibdev->iboe; - spin_lock(&iboe->lock); + spin_lock_bh(&iboe->lock); mlx4_foreach_ib_transport_port(port, ibdev->dev) { enum ib_port_state port_state = IB_PORT_NOP; struct net_device *old_master = iboe->masters[port - 1]; @@ -1816,35 +1863,47 @@ static void mlx4_ib_scan_netdevs(struct mlx4_ib_dev *ibdev, port_state = (netif_running(curr_netdev) && netif_carrier_ok(curr_netdev)) ? IB_PORT_ACTIVE : IB_PORT_DOWN; mlx4_ib_set_default_gid(ibdev, curr_netdev, port); - } else { - reset_gid_table(ibdev, port); - } - /* if using bonding/team and a slave port is down, we don't the bond IP - * based gids in the table since flows that select port by gid may get - * the down port. - */ - if (curr_master && (port_state == IB_PORT_DOWN)) { - reset_gid_table(ibdev, port); - mlx4_ib_set_default_gid(ibdev, curr_netdev, port); - } - /* if bonding is used it is possible that we add it to masters - * only after IP address is assigned to the net bonding - * interface. - */ - if (curr_master && (old_master != curr_master)) { - reset_gid_table(ibdev, port); - mlx4_ib_set_default_gid(ibdev, curr_netdev, port); - mlx4_ib_get_dev_addr(curr_master, ibdev, port); - } + if (curr_master) { + /* if using bonding/team and a slave port is down, we + * don't want the bond IP based gids in the table since + * flows that select port by gid may get the down port. + */ + if (port_state == IB_PORT_DOWN) { + reset_gid_table(ibdev, port); + mlx4_ib_set_default_gid(ibdev, + curr_netdev, + port); + } else { + /* gids from the upper dev (bond/team) + * should appear in port's gid table + */ + mlx4_ib_get_dev_addr(curr_master, + ibdev, port); + } + } + /* if bonding is used it is possible that we add it to + * masters only after IP address is assigned to the + * net bonding interface. + */ + if (curr_master && (old_master != curr_master)) { + reset_gid_table(ibdev, port); + mlx4_ib_set_default_gid(ibdev, + curr_netdev, port); + mlx4_ib_get_dev_addr(curr_master, ibdev, port); + } - if (!curr_master && (old_master != curr_master)) { + if (!curr_master && (old_master != curr_master)) { + reset_gid_table(ibdev, port); + mlx4_ib_set_default_gid(ibdev, + curr_netdev, port); + mlx4_ib_get_dev_addr(curr_netdev, ibdev, port); + } + } else { reset_gid_table(ibdev, port); - mlx4_ib_set_default_gid(ibdev, curr_netdev, port); - mlx4_ib_get_dev_addr(curr_netdev, ibdev, port); } } - spin_unlock(&iboe->lock); + spin_unlock_bh(&iboe->lock); if (update_qps_port > 0) mlx4_ib_update_qps(ibdev, dev, update_qps_port); @@ -2186,6 +2245,9 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) goto err_steer_free_bitmap; } + for (j = 1; j <= ibdev->dev->caps.num_ports; j++) + atomic64_set(&iboe->mac[j - 1], ibdev->dev->caps.def_mac[j]); + if (ib_register_device(&ibdev->ib_dev, NULL)) goto err_steer_free_bitmap; @@ -2222,12 +2284,8 @@ static void *mlx4_ib_add(struct mlx4_dev *dev) } } #endif - for (i = 1 ; i <= ibdev->num_ports ; ++i) - reset_gid_table(ibdev, i); - rtnl_lock(); - mlx4_ib_scan_netdevs(ibdev, NULL, 0); - rtnl_unlock(); - mlx4_ib_init_gid_table(ibdev); + if (mlx4_ib_init_gid_table(ibdev)) + goto err_notif; } for (j = 0; j < ARRAY_SIZE(mlx4_class_attributes); ++j) { @@ -2375,6 +2433,9 @@ static void mlx4_ib_remove(struct mlx4_dev *dev, void *ibdev_ptr) struct mlx4_ib_dev *ibdev = ibdev_ptr; int p; + ibdev->ib_active = false; + flush_workqueue(wq); + mlx4_ib_close_sriov(ibdev); mlx4_ib_mad_cleanup(ibdev); ib_unregister_device(&ibdev->ib_dev); diff --git a/drivers/infiniband/hw/mlx4/mlx4_ib.h b/drivers/infiniband/hw/mlx4/mlx4_ib.h index e8cad3926bfc..6eb743f65f6f 100644 --- a/drivers/infiniband/hw/mlx4/mlx4_ib.h +++ b/drivers/infiniband/hw/mlx4/mlx4_ib.h @@ -451,6 +451,7 @@ struct mlx4_ib_iboe { spinlock_t lock; struct net_device *netdevs[MLX4_MAX_PORTS]; struct net_device *masters[MLX4_MAX_PORTS]; + atomic64_t mac[MLX4_MAX_PORTS]; struct notifier_block nb; struct notifier_block nb_inet; struct notifier_block nb_inet6; diff --git a/drivers/infiniband/hw/mlx4/mr.c b/drivers/infiniband/hw/mlx4/mr.c index 9b0e80e59b08..8f9325cfc85d 100644 --- a/drivers/infiniband/hw/mlx4/mr.c +++ b/drivers/infiniband/hw/mlx4/mr.c @@ -234,14 +234,13 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, 0); if (IS_ERR(mmr->umem)) { err = PTR_ERR(mmr->umem); + /* Prevent mlx4_ib_dereg_mr from free'ing invalid pointer */ mmr->umem = NULL; goto release_mpt_entry; } n = ib_umem_page_count(mmr->umem); shift = ilog2(mmr->umem->page_size); - mmr->mmr.iova = virt_addr; - mmr->mmr.size = length; err = mlx4_mr_rereg_mem_write(dev->dev, &mmr->mmr, virt_addr, length, n, shift, *pmpt_entry); @@ -249,6 +248,8 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, ib_umem_release(mmr->umem); goto release_mpt_entry; } + mmr->mmr.iova = virt_addr; + mmr->mmr.size = length; err = mlx4_ib_umem_write_mtt(dev, &mmr->mmr.mtt, mmr->umem); if (err) { @@ -262,6 +263,8 @@ int mlx4_ib_rereg_user_mr(struct ib_mr *mr, int flags, * return a failure. But dereg_mr will free the resources. */ err = mlx4_mr_hw_write_mpt(dev->dev, &mmr->mmr, pmpt_entry); + if (!err && flags & IB_MR_REREG_ACCESS) + mmr->mmr.access = mr_access_flags; release_mpt_entry: mlx4_mr_hw_put_mpt(dev->dev, pmpt_entry); diff --git a/drivers/infiniband/hw/mlx4/qp.c b/drivers/infiniband/hw/mlx4/qp.c index efb9eff8906c..9c5150c3cb31 100644 --- a/drivers/infiniband/hw/mlx4/qp.c +++ b/drivers/infiniband/hw/mlx4/qp.c @@ -964,9 +964,10 @@ static void destroy_qp_common(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, MLX4_QP_STATE_RST, NULL, 0, 0, &qp->mqp)) pr_warn("modify QP %06x to RESET failed.\n", qp->mqp.qpn); - if (qp->pri.smac) { + if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port)) { mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac); qp->pri.smac = 0; + qp->pri.smac_port = 0; } if (qp->alt.smac) { mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac); @@ -1325,7 +1326,8 @@ static int _mlx4_set_path(struct mlx4_ib_dev *dev, const struct ib_ah_attr *ah, * If one was already assigned, but the new mac differs, * unregister the old one and register the new one. */ - if (!smac_info->smac || smac_info->smac != smac) { + if ((!smac_info->smac && !smac_info->smac_port) || + smac_info->smac != smac) { /* register candidate now, unreg if needed, after success */ smac_index = mlx4_register_mac(dev->dev, port, smac); if (smac_index >= 0) { @@ -1390,21 +1392,13 @@ static void update_mcg_macs(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp) static int handle_eth_ud_smac_index(struct mlx4_ib_dev *dev, struct mlx4_ib_qp *qp, u8 *smac, struct mlx4_qp_context *context) { - struct net_device *ndev; u64 u64_mac; int smac_index; - - ndev = dev->iboe.netdevs[qp->port - 1]; - if (ndev) { - smac = ndev->dev_addr; - u64_mac = mlx4_mac_to_u64(smac); - } else { - u64_mac = dev->dev->caps.def_mac[qp->port]; - } + u64_mac = atomic64_read(&dev->iboe.mac[qp->port - 1]); context->pri_path.sched_queue = MLX4_IB_DEFAULT_SCHED_QUEUE | ((qp->port - 1) << 6); - if (!qp->pri.smac) { + if (!qp->pri.smac && !qp->pri.smac_port) { smac_index = mlx4_register_mac(dev->dev, qp->port, u64_mac); if (smac_index >= 0) { qp->pri.candidate_smac_index = smac_index; @@ -1432,6 +1426,12 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, int steer_qp = 0; int err = -EINVAL; + /* APM is not supported under RoCE */ + if (attr_mask & IB_QP_ALT_PATH && + rdma_port_get_link_layer(&dev->ib_dev, qp->port) == + IB_LINK_LAYER_ETHERNET) + return -ENOTSUPP; + context = kzalloc(sizeof *context, GFP_KERNEL); if (!context) return -ENOMEM; @@ -1682,7 +1682,7 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, MLX4_IB_LINK_TYPE_ETH; if (dev->dev->caps.tunnel_offload_mode == MLX4_TUNNEL_OFFLOAD_MODE_VXLAN) { /* set QP to receive both tunneled & non-tunneled packets */ - if (!(context->flags & (1 << MLX4_RSS_QPC_FLAG_OFFSET))) + if (!(context->flags & cpu_to_be32(1 << MLX4_RSS_QPC_FLAG_OFFSET))) context->srqn = cpu_to_be32(7 << 28); } } @@ -1786,9 +1786,10 @@ static int __mlx4_ib_modify_qp(struct ib_qp *ibqp, if (qp->flags & MLX4_IB_QP_NETIF) mlx4_ib_steer_qp_reg(dev, qp, 0); } - if (qp->pri.smac) { + if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port)) { mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac); qp->pri.smac = 0; + qp->pri.smac_port = 0; } if (qp->alt.smac) { mlx4_unregister_mac(dev->dev, qp->alt.smac_port, qp->alt.smac); @@ -1812,11 +1813,12 @@ out: if (err && steer_qp) mlx4_ib_steer_qp_reg(dev, qp, 0); kfree(context); - if (qp->pri.candidate_smac) { + if (qp->pri.candidate_smac || + (!qp->pri.candidate_smac && qp->pri.candidate_smac_port)) { if (err) { mlx4_unregister_mac(dev->dev, qp->pri.candidate_smac_port, qp->pri.candidate_smac); } else { - if (qp->pri.smac) + if (qp->pri.smac || (!qp->pri.smac && qp->pri.smac_port)) mlx4_unregister_mac(dev->dev, qp->pri.smac_port, qp->pri.smac); qp->pri.smac = qp->pri.candidate_smac; qp->pri.smac_index = qp->pri.candidate_smac_index; @@ -2089,6 +2091,16 @@ static int build_sriov_qp0_header(struct mlx4_ib_sqp *sqp, return 0; } +static void mlx4_u64_to_smac(u8 *dst_mac, u64 src_mac) +{ + int i; + + for (i = ETH_ALEN; i; i--) { + dst_mac[i - 1] = src_mac & 0xff; + src_mac >>= 8; + } +} + static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, void *wqe, unsigned *mlx_seg_len) { @@ -2203,7 +2215,6 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, } if (is_eth) { - u8 *smac; struct in6_addr in6; u16 pcp = (be32_to_cpu(ah->av.ib.sl_tclass_flowlabel) >> 29) << 13; @@ -2216,12 +2227,17 @@ static int build_mlx_header(struct mlx4_ib_sqp *sqp, struct ib_send_wr *wr, memcpy(&ctrl->imm, ah->av.eth.mac + 2, 4); memcpy(&in6, sgid.raw, sizeof(in6)); - if (!mlx4_is_mfunc(to_mdev(ib_dev)->dev)) - smac = to_mdev(sqp->qp.ibqp.device)-> - iboe.netdevs[sqp->qp.port - 1]->dev_addr; - else /* use the src mac of the tunnel */ - smac = ah->av.eth.s_mac; - memcpy(sqp->ud_header.eth.smac_h, smac, 6); + if (!mlx4_is_mfunc(to_mdev(ib_dev)->dev)) { + u64 mac = atomic64_read(&to_mdev(ib_dev)->iboe.mac[sqp->qp.port - 1]); + u8 smac[ETH_ALEN]; + + mlx4_u64_to_smac(smac, mac); + memcpy(sqp->ud_header.eth.smac_h, smac, ETH_ALEN); + } else { + /* use the src mac of the tunnel */ + memcpy(sqp->ud_header.eth.smac_h, ah->av.eth.s_mac, ETH_ALEN); + } + if (!memcmp(sqp->ud_header.eth.smac_h, sqp->ud_header.eth.dmac_h, 6)) mlx->flags |= cpu_to_be32(MLX4_WQE_CTRL_FORCE_LOOPBACK); if (!is_vlan) { diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c index 40f8536c10b0..ac02ce4e8040 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_ah.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_ah.c @@ -38,7 +38,7 @@ #define OCRDMA_VID_PCP_SHIFT 0xD static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah, - struct ib_ah_attr *attr, int pdid) + struct ib_ah_attr *attr, union ib_gid *sgid, int pdid) { int status = 0; u16 vlan_tag; bool vlan_enabled = false; @@ -49,8 +49,7 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah, memset(ð, 0, sizeof(eth)); memset(&grh, 0, sizeof(grh)); - ah->sgid_index = attr->grh.sgid_index; - + /* VLAN */ vlan_tag = attr->vlan_id; if (!vlan_tag || (vlan_tag > 0xFFF)) vlan_tag = dev->pvid; @@ -65,15 +64,14 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah, eth.eth_type = cpu_to_be16(OCRDMA_ROCE_ETH_TYPE); eth_sz = sizeof(struct ocrdma_eth_basic); } + /* MAC */ memcpy(ð.smac[0], &dev->nic_info.mac_addr[0], ETH_ALEN); - memcpy(ð.dmac[0], attr->dmac, ETH_ALEN); status = ocrdma_resolve_dmac(dev, attr, ð.dmac[0]); if (status) return status; - status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index, - (union ib_gid *)&grh.sgid[0]); - if (status) - return status; + ah->sgid_index = attr->grh.sgid_index; + memcpy(&grh.sgid[0], sgid->raw, sizeof(union ib_gid)); + memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw)); grh.tclass_flow = cpu_to_be32((6 << 28) | (attr->grh.traffic_class << 24) | @@ -81,8 +79,7 @@ static inline int set_av_attr(struct ocrdma_dev *dev, struct ocrdma_ah *ah, /* 0x1b is next header value in GRH */ grh.pdid_hoplimit = cpu_to_be32((pdid << 16) | (0x1b << 8) | attr->grh.hop_limit); - - memcpy(&grh.dgid[0], attr->grh.dgid.raw, sizeof(attr->grh.dgid.raw)); + /* Eth HDR */ memcpy(&ah->av->eth_hdr, ð, eth_sz); memcpy((u8 *)ah->av + eth_sz, &grh, sizeof(struct ocrdma_grh)); if (vlan_enabled) @@ -98,6 +95,8 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr) struct ocrdma_ah *ah; struct ocrdma_pd *pd = get_ocrdma_pd(ibpd); struct ocrdma_dev *dev = get_ocrdma_dev(ibpd->device); + union ib_gid sgid; + u8 zmac[ETH_ALEN]; if (!(attr->ah_flags & IB_AH_GRH)) return ERR_PTR(-EINVAL); @@ -111,7 +110,27 @@ struct ib_ah *ocrdma_create_ah(struct ib_pd *ibpd, struct ib_ah_attr *attr) status = ocrdma_alloc_av(dev, ah); if (status) goto av_err; - status = set_av_attr(dev, ah, attr, pd->id); + + status = ocrdma_query_gid(&dev->ibdev, 1, attr->grh.sgid_index, &sgid); + if (status) { + pr_err("%s(): Failed to query sgid, status = %d\n", + __func__, status); + goto av_conf_err; + } + + memset(&zmac, 0, ETH_ALEN); + if (pd->uctx && + memcmp(attr->dmac, &zmac, ETH_ALEN)) { + status = rdma_addr_find_dmac_by_grh(&sgid, &attr->grh.dgid, + attr->dmac, &attr->vlan_id); + if (status) { + pr_err("%s(): Failed to resolve dmac from gid." + "status = %d\n", __func__, status); + goto av_conf_err; + } + } + + status = set_av_attr(dev, ah, attr, &sgid, pd->id); if (status) goto av_conf_err; @@ -145,7 +164,7 @@ int ocrdma_query_ah(struct ib_ah *ibah, struct ib_ah_attr *attr) struct ocrdma_av *av = ah->av; struct ocrdma_grh *grh; attr->ah_flags |= IB_AH_GRH; - if (ah->av->valid & Bit(1)) { + if (ah->av->valid & OCRDMA_AV_VALID) { grh = (struct ocrdma_grh *)((u8 *)ah->av + sizeof(struct ocrdma_eth_vlan)); attr->sl = be16_to_cpu(av->eth_hdr.vlan_tag) >> 13; diff --git a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c index acb434d16903..8f5f2577f288 100644 --- a/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c +++ b/drivers/infiniband/hw/ocrdma/ocrdma_verbs.c @@ -101,7 +101,7 @@ int ocrdma_query_device(struct ib_device *ibdev, struct ib_device_attr *attr) attr->max_srq_sge = dev->attr.max_srq_sge; attr->max_srq_wr = dev->attr.max_rqe; attr->local_ca_ack_delay = dev->attr.local_ca_ack_delay; - attr->max_fast_reg_page_list_len = 0; + attr->max_fast_reg_page_list_len = dev->attr.max_pages_per_frmr; attr->max_pkeys = 1; return 0; } @@ -2846,11 +2846,9 @@ int ocrdma_arm_cq(struct ib_cq *ibcq, enum ib_cq_notify_flags cq_flags) if (cq->first_arm) { ocrdma_ring_cq_db(dev, cq_id, arm_needed, sol_needed, 0); cq->first_arm = false; - goto skip_defer; } - cq->deferred_arm = true; -skip_defer: + cq->deferred_arm = true; cq->deferred_sol = sol_needed; spin_unlock_irqrestore(&cq->cq_lock, flags); diff --git a/drivers/infiniband/hw/qib/qib_debugfs.c b/drivers/infiniband/hw/qib/qib_debugfs.c index 799a0c3bffc4..6abd3ed3cd51 100644 --- a/drivers/infiniband/hw/qib/qib_debugfs.c +++ b/drivers/infiniband/hw/qib/qib_debugfs.c @@ -193,6 +193,7 @@ static void *_qp_stats_seq_start(struct seq_file *s, loff_t *pos) struct qib_qp_iter *iter; loff_t n = *pos; + rcu_read_lock(); iter = qib_qp_iter_init(s->private); if (!iter) return NULL; @@ -224,7 +225,7 @@ static void *_qp_stats_seq_next(struct seq_file *s, void *iter_ptr, static void _qp_stats_seq_stop(struct seq_file *s, void *iter_ptr) { - /* nothing for now */ + rcu_read_unlock(); } static int _qp_stats_seq_show(struct seq_file *s, void *iter_ptr) diff --git a/drivers/infiniband/hw/qib/qib_qp.c b/drivers/infiniband/hw/qib/qib_qp.c index 7fcc150d603c..6ddc0264aad2 100644 --- a/drivers/infiniband/hw/qib/qib_qp.c +++ b/drivers/infiniband/hw/qib/qib_qp.c @@ -1325,7 +1325,6 @@ int qib_qp_iter_next(struct qib_qp_iter *iter) struct qib_qp *pqp = iter->qp; struct qib_qp *qp; - rcu_read_lock(); for (; n < dev->qp_table_size; n++) { if (pqp) qp = rcu_dereference(pqp->next); @@ -1333,18 +1332,11 @@ int qib_qp_iter_next(struct qib_qp_iter *iter) qp = rcu_dereference(dev->qp_table[n]); pqp = qp; if (qp) { - if (iter->qp) - atomic_dec(&iter->qp->refcount); - atomic_inc(&qp->refcount); - rcu_read_unlock(); iter->qp = qp; iter->n = n; return 0; } } - rcu_read_unlock(); - if (iter->qp) - atomic_dec(&iter->qp->refcount); return ret; } diff --git a/drivers/infiniband/hw/qib/qib_user_pages.c b/drivers/infiniband/hw/qib/qib_user_pages.c index 2bc1d2b96298..74f90b2619f6 100644 --- a/drivers/infiniband/hw/qib/qib_user_pages.c +++ b/drivers/infiniband/hw/qib/qib_user_pages.c @@ -52,7 +52,7 @@ static void __qib_release_user_pages(struct page **p, size_t num_pages, * Call with current->mm->mmap_sem held. */ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages, - struct page **p, struct vm_area_struct **vma) + struct page **p) { unsigned long lock_limit; size_t got; @@ -69,7 +69,7 @@ static int __qib_get_user_pages(unsigned long start_page, size_t num_pages, ret = get_user_pages(current, current->mm, start_page + got * PAGE_SIZE, num_pages - got, 1, 1, - p + got, vma); + p + got, NULL); if (ret < 0) goto bail_release; } @@ -136,7 +136,7 @@ int qib_get_user_pages(unsigned long start_page, size_t num_pages, down_write(¤t->mm->mmap_sem); - ret = __qib_get_user_pages(start_page, num_pages, p, NULL); + ret = __qib_get_user_pages(start_page, num_pages, p); up_write(¤t->mm->mmap_sem); diff --git a/drivers/infiniband/ulp/ipoib/ipoib.h b/drivers/infiniband/ulp/ipoib/ipoib.h index 3edce617c31b..d7562beb5423 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib.h +++ b/drivers/infiniband/ulp/ipoib/ipoib.h @@ -131,6 +131,12 @@ struct ipoib_cb { u8 hwaddr[INFINIBAND_ALEN]; }; +static inline struct ipoib_cb *ipoib_skb_cb(const struct sk_buff *skb) +{ + BUILD_BUG_ON(sizeof(skb->cb) < sizeof(struct ipoib_cb)); + return (struct ipoib_cb *)skb->cb; +} + /* Used for all multicast joins (broadcast, IPv4 mcast and IPv6 mcast) */ struct ipoib_mcast { struct ib_sa_mcmember_rec mcmember; diff --git a/drivers/infiniband/ulp/ipoib/ipoib_main.c b/drivers/infiniband/ulp/ipoib/ipoib_main.c index 1310acf6bf92..13e6e0431592 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_main.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_main.c @@ -716,7 +716,7 @@ static int ipoib_start_xmit(struct sk_buff *skb, struct net_device *dev) { struct ipoib_dev_priv *priv = netdev_priv(dev); struct ipoib_neigh *neigh; - struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb; + struct ipoib_cb *cb = ipoib_skb_cb(skb); struct ipoib_header *header; unsigned long flags; @@ -813,7 +813,7 @@ static int ipoib_hard_header(struct sk_buff *skb, const void *daddr, const void *saddr, unsigned len) { struct ipoib_header *header; - struct ipoib_cb *cb = (struct ipoib_cb *) skb->cb; + struct ipoib_cb *cb = ipoib_skb_cb(skb); header = (struct ipoib_header *) skb_push(skb, sizeof *header); diff --git a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c index d4e005720d01..ffb83b5f7e80 100644 --- a/drivers/infiniband/ulp/ipoib/ipoib_multicast.c +++ b/drivers/infiniband/ulp/ipoib/ipoib_multicast.c @@ -529,21 +529,13 @@ void ipoib_mcast_join_task(struct work_struct *work) port_attr.state); return; } + priv->local_lid = port_attr.lid; if (ib_query_gid(priv->ca, priv->port, 0, &priv->local_gid)) ipoib_warn(priv, "ib_query_gid() failed\n"); else memcpy(priv->dev->dev_addr + 4, priv->local_gid.raw, sizeof (union ib_gid)); - { - struct ib_port_attr attr; - - if (!ib_query_port(priv->ca, priv->port, &attr)) - priv->local_lid = attr.lid; - else - ipoib_warn(priv, "ib_query_port failed\n"); - } - if (!priv->broadcast) { struct ipoib_mcast *broadcast; diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.c b/drivers/infiniband/ulp/iser/iscsi_iser.c index 61ee91d88380..93ce62fe1594 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.c +++ b/drivers/infiniband/ulp/iser/iscsi_iser.c @@ -344,7 +344,6 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, int is_leading) { struct iscsi_conn *conn = cls_conn->dd_data; - struct iscsi_session *session; struct iser_conn *ib_conn; struct iscsi_endpoint *ep; int error; @@ -363,9 +362,17 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, } ib_conn = ep->dd_data; - session = conn->session; - if (iser_alloc_rx_descriptors(ib_conn, session)) - return -ENOMEM; + mutex_lock(&ib_conn->state_mutex); + if (ib_conn->state != ISER_CONN_UP) { + error = -EINVAL; + iser_err("iser_conn %p state is %d, teardown started\n", + ib_conn, ib_conn->state); + goto out; + } + + error = iser_alloc_rx_descriptors(ib_conn, conn->session); + if (error) + goto out; /* binds the iSER connection retrieved from the previously * connected ep_handle to the iSCSI layer connection. exchanges @@ -375,7 +382,9 @@ iscsi_iser_conn_bind(struct iscsi_cls_session *cls_session, conn->dd_data = ib_conn; ib_conn->iscsi_conn = conn; - return 0; +out: + mutex_unlock(&ib_conn->state_mutex); + return error; } static int diff --git a/drivers/infiniband/ulp/iser/iscsi_iser.h b/drivers/infiniband/ulp/iser/iscsi_iser.h index c877dad381cb..9f0e0e34d6ca 100644 --- a/drivers/infiniband/ulp/iser/iscsi_iser.h +++ b/drivers/infiniband/ulp/iser/iscsi_iser.h @@ -69,7 +69,7 @@ #define DRV_NAME "iser" #define PFX DRV_NAME ": " -#define DRV_VER "1.4" +#define DRV_VER "1.4.1" #define iser_dbg(fmt, arg...) \ do { \ diff --git a/drivers/infiniband/ulp/iser/iser_verbs.c b/drivers/infiniband/ulp/iser/iser_verbs.c index 3ef167f97d6f..3bfec4bbda52 100644 --- a/drivers/infiniband/ulp/iser/iser_verbs.c +++ b/drivers/infiniband/ulp/iser/iser_verbs.c @@ -73,7 +73,7 @@ static int iser_create_device_ib_res(struct iser_device *device) { struct iser_cq_desc *cq_desc; struct ib_device_attr *dev_attr = &device->dev_attr; - int ret, i, j; + int ret, i; ret = ib_query_device(device->ib_device, dev_attr); if (ret) { @@ -125,16 +125,20 @@ static int iser_create_device_ib_res(struct iser_device *device) iser_cq_event_callback, (void *)&cq_desc[i], ISER_MAX_RX_CQ_LEN, i); - if (IS_ERR(device->rx_cq[i])) + if (IS_ERR(device->rx_cq[i])) { + device->rx_cq[i] = NULL; goto cq_err; + } device->tx_cq[i] = ib_create_cq(device->ib_device, NULL, iser_cq_event_callback, (void *)&cq_desc[i], ISER_MAX_TX_CQ_LEN, i); - if (IS_ERR(device->tx_cq[i])) + if (IS_ERR(device->tx_cq[i])) { + device->tx_cq[i] = NULL; goto cq_err; + } if (ib_req_notify_cq(device->rx_cq[i], IB_CQ_NEXT_COMP)) goto cq_err; @@ -160,14 +164,14 @@ static int iser_create_device_ib_res(struct iser_device *device) handler_err: ib_dereg_mr(device->mr); dma_mr_err: - for (j = 0; j < device->cqs_used; j++) - tasklet_kill(&device->cq_tasklet[j]); + for (i = 0; i < device->cqs_used; i++) + tasklet_kill(&device->cq_tasklet[i]); cq_err: - for (j = 0; j < i; j++) { - if (device->tx_cq[j]) - ib_destroy_cq(device->tx_cq[j]); - if (device->rx_cq[j]) - ib_destroy_cq(device->rx_cq[j]); + for (i = 0; i < device->cqs_used; i++) { + if (device->tx_cq[i]) + ib_destroy_cq(device->tx_cq[i]); + if (device->rx_cq[i]) + ib_destroy_cq(device->rx_cq[i]); } ib_dealloc_pd(device->pd); pd_err: diff --git a/drivers/message/fusion/Kconfig b/drivers/message/fusion/Kconfig index a34a11d2fef2..63ca9841db10 100644 --- a/drivers/message/fusion/Kconfig +++ b/drivers/message/fusion/Kconfig @@ -29,7 +29,7 @@ config FUSION_SPI config FUSION_FC tristate "Fusion MPT ScsiHost drivers for FC" depends on PCI && SCSI - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS ---help--- SCSI HOST support for a Fiber Channel host adapters. diff --git a/drivers/net/bonding/bond_main.c b/drivers/net/bonding/bond_main.c index f0f5eab0fab1..798ae69fb63c 100644 --- a/drivers/net/bonding/bond_main.c +++ b/drivers/net/bonding/bond_main.c @@ -175,7 +175,7 @@ MODULE_PARM_DESC(fail_over_mac, "For active-backup, do not set all slaves to " "the same MAC; 0 for none (default), " "1 for active, 2 for follow"); module_param(all_slaves_active, int, 0); -MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface" +MODULE_PARM_DESC(all_slaves_active, "Keep all frames received on an interface " "by setting active flag for all slaves; " "0 for never (default), 1 for always."); module_param(resend_igmp, int, 0); @@ -3659,8 +3659,14 @@ static int bond_xmit_roundrobin(struct sk_buff *skb, struct net_device *bond_dev else bond_xmit_slave_id(bond, skb, 0); } else { - slave_id = bond_rr_gen_slave_id(bond); - bond_xmit_slave_id(bond, skb, slave_id % bond->slave_cnt); + int slave_cnt = ACCESS_ONCE(bond->slave_cnt); + + if (likely(slave_cnt)) { + slave_id = bond_rr_gen_slave_id(bond); + bond_xmit_slave_id(bond, skb, slave_id % slave_cnt); + } else { + dev_kfree_skb_any(skb); + } } return NETDEV_TX_OK; @@ -3691,8 +3697,13 @@ static int bond_xmit_activebackup(struct sk_buff *skb, struct net_device *bond_d static int bond_xmit_xor(struct sk_buff *skb, struct net_device *bond_dev) { struct bonding *bond = netdev_priv(bond_dev); + int slave_cnt = ACCESS_ONCE(bond->slave_cnt); - bond_xmit_slave_id(bond, skb, bond_xmit_hash(bond, skb) % bond->slave_cnt); + if (likely(slave_cnt)) + bond_xmit_slave_id(bond, skb, + bond_xmit_hash(bond, skb) % slave_cnt); + else + dev_kfree_skb_any(skb); return NETDEV_TX_OK; } diff --git a/drivers/net/can/at91_can.c b/drivers/net/can/at91_can.c index f07fa89b5fd5..05e1aa090add 100644 --- a/drivers/net/can/at91_can.c +++ b/drivers/net/can/at91_can.c @@ -1123,7 +1123,9 @@ static int at91_open(struct net_device *dev) struct at91_priv *priv = netdev_priv(dev); int err; - clk_enable(priv->clk); + err = clk_prepare_enable(priv->clk); + if (err) + return err; /* check or determine and set bittime */ err = open_candev(dev); @@ -1149,7 +1151,7 @@ static int at91_open(struct net_device *dev) out_close: close_candev(dev); out: - clk_disable(priv->clk); + clk_disable_unprepare(priv->clk); return err; } @@ -1166,7 +1168,7 @@ static int at91_close(struct net_device *dev) at91_chip_stop(dev, CAN_STATE_STOPPED); free_irq(dev->irq, dev); - clk_disable(priv->clk); + clk_disable_unprepare(priv->clk); close_candev(dev); diff --git a/drivers/net/can/c_can/c_can_platform.c b/drivers/net/can/c_can/c_can_platform.c index 109cb44291f5..fb279d6ae484 100644 --- a/drivers/net/can/c_can/c_can_platform.c +++ b/drivers/net/can/c_can/c_can_platform.c @@ -97,14 +97,14 @@ static void c_can_hw_raminit_ti(const struct c_can_priv *priv, bool enable) ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); writel(ctrl, priv->raminit_ctrlreg); ctrl &= ~CAN_RAMINIT_DONE_MASK(priv->instance); - c_can_hw_raminit_wait_ti(priv, ctrl, mask); + c_can_hw_raminit_wait_ti(priv, mask, ctrl); if (enable) { /* Set start bit and wait for the done bit. */ ctrl |= CAN_RAMINIT_START_MASK(priv->instance); writel(ctrl, priv->raminit_ctrlreg); ctrl |= CAN_RAMINIT_DONE_MASK(priv->instance); - c_can_hw_raminit_wait_ti(priv, ctrl, mask); + c_can_hw_raminit_wait_ti(priv, mask, ctrl); } spin_unlock(&raminit_lock); } diff --git a/drivers/net/can/flexcan.c b/drivers/net/can/flexcan.c index 944aa5d3af6e..6586309329e6 100644 --- a/drivers/net/can/flexcan.c +++ b/drivers/net/can/flexcan.c @@ -62,7 +62,7 @@ #define FLEXCAN_MCR_BCC BIT(16) #define FLEXCAN_MCR_LPRIO_EN BIT(13) #define FLEXCAN_MCR_AEN BIT(12) -#define FLEXCAN_MCR_MAXMB(x) ((x) & 0x1f) +#define FLEXCAN_MCR_MAXMB(x) ((x) & 0x7f) #define FLEXCAN_MCR_IDAM_A (0 << 8) #define FLEXCAN_MCR_IDAM_B (1 << 8) #define FLEXCAN_MCR_IDAM_C (2 << 8) @@ -125,7 +125,9 @@ FLEXCAN_ESR_BOFF_INT | FLEXCAN_ESR_ERR_INT) /* FLEXCAN interrupt flag register (IFLAG) bits */ -#define FLEXCAN_TX_BUF_ID 8 +/* Errata ERR005829 step7: Reserve first valid MB */ +#define FLEXCAN_TX_BUF_RESERVED 8 +#define FLEXCAN_TX_BUF_ID 9 #define FLEXCAN_IFLAG_BUF(x) BIT(x) #define FLEXCAN_IFLAG_RX_FIFO_OVERFLOW BIT(7) #define FLEXCAN_IFLAG_RX_FIFO_WARN BIT(6) @@ -136,6 +138,17 @@ /* FLEXCAN message buffers */ #define FLEXCAN_MB_CNT_CODE(x) (((x) & 0xf) << 24) +#define FLEXCAN_MB_CODE_RX_INACTIVE (0x0 << 24) +#define FLEXCAN_MB_CODE_RX_EMPTY (0x4 << 24) +#define FLEXCAN_MB_CODE_RX_FULL (0x2 << 24) +#define FLEXCAN_MB_CODE_RX_OVERRRUN (0x6 << 24) +#define FLEXCAN_MB_CODE_RX_RANSWER (0xa << 24) + +#define FLEXCAN_MB_CODE_TX_INACTIVE (0x8 << 24) +#define FLEXCAN_MB_CODE_TX_ABORT (0x9 << 24) +#define FLEXCAN_MB_CODE_TX_DATA (0xc << 24) +#define FLEXCAN_MB_CODE_TX_TANSWER (0xe << 24) + #define FLEXCAN_MB_CNT_SRR BIT(22) #define FLEXCAN_MB_CNT_IDE BIT(21) #define FLEXCAN_MB_CNT_RTR BIT(20) @@ -298,7 +311,7 @@ static int flexcan_chip_enable(struct flexcan_priv *priv) flexcan_write(reg, ®s->mcr); while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) - usleep_range(10, 20); + udelay(10); if (flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK) return -ETIMEDOUT; @@ -317,7 +330,7 @@ static int flexcan_chip_disable(struct flexcan_priv *priv) flexcan_write(reg, ®s->mcr); while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) - usleep_range(10, 20); + udelay(10); if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_LPM_ACK)) return -ETIMEDOUT; @@ -336,7 +349,7 @@ static int flexcan_chip_freeze(struct flexcan_priv *priv) flexcan_write(reg, ®s->mcr); while (timeout-- && !(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) - usleep_range(100, 200); + udelay(100); if (!(flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) return -ETIMEDOUT; @@ -355,7 +368,7 @@ static int flexcan_chip_unfreeze(struct flexcan_priv *priv) flexcan_write(reg, ®s->mcr); while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK)) - usleep_range(10, 20); + udelay(10); if (flexcan_read(®s->mcr) & FLEXCAN_MCR_FRZ_ACK) return -ETIMEDOUT; @@ -370,7 +383,7 @@ static int flexcan_chip_softreset(struct flexcan_priv *priv) flexcan_write(FLEXCAN_MCR_SOFTRST, ®s->mcr); while (timeout-- && (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST)) - usleep_range(10, 20); + udelay(10); if (flexcan_read(®s->mcr) & FLEXCAN_MCR_SOFTRST) return -ETIMEDOUT; @@ -428,6 +441,14 @@ static int flexcan_start_xmit(struct sk_buff *skb, struct net_device *dev) flexcan_write(can_id, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_id); flexcan_write(ctrl, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); + /* Errata ERR005829 step8: + * Write twice INACTIVE(0x8) code to first MB. + */ + flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + return NETDEV_TX_OK; } @@ -744,6 +765,9 @@ static irqreturn_t flexcan_irq(int irq, void *dev_id) stats->tx_bytes += can_get_echo_skb(dev, 0); stats->tx_packets++; can_led_event(dev, CAN_LED_EVENT_TX); + /* after sending a RTR frame mailbox is in RX mode */ + flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); flexcan_write((1 << FLEXCAN_TX_BUF_ID), ®s->iflag1); netif_wake_queue(dev); } @@ -801,6 +825,7 @@ static int flexcan_chip_start(struct net_device *dev) struct flexcan_regs __iomem *regs = priv->base; int err; u32 reg_mcr, reg_ctrl; + int i; /* enable module */ err = flexcan_chip_enable(priv); @@ -867,8 +892,18 @@ static int flexcan_chip_start(struct net_device *dev) netdev_dbg(dev, "%s: writing ctrl=0x%08x", __func__, reg_ctrl); flexcan_write(reg_ctrl, ®s->ctrl); - /* Abort any pending TX, mark Mailbox as INACTIVE */ - flexcan_write(FLEXCAN_MB_CNT_CODE(0x4), + /* clear and invalidate all mailboxes first */ + for (i = FLEXCAN_TX_BUF_ID; i < ARRAY_SIZE(regs->cantxfg); i++) { + flexcan_write(FLEXCAN_MB_CODE_RX_INACTIVE, + ®s->cantxfg[i].can_ctrl); + } + + /* Errata ERR005829: mark first TX mailbox as INACTIVE */ + flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, + ®s->cantxfg[FLEXCAN_TX_BUF_RESERVED].can_ctrl); + + /* mark TX mailbox as INACTIVE */ + flexcan_write(FLEXCAN_MB_CODE_TX_INACTIVE, ®s->cantxfg[FLEXCAN_TX_BUF_ID].can_ctrl); /* acceptance mask/acceptance code (accept everything) */ diff --git a/drivers/net/can/sja1000/peak_pci.c b/drivers/net/can/sja1000/peak_pci.c index 7a85590fefb9..e5fac368068a 100644 --- a/drivers/net/can/sja1000/peak_pci.c +++ b/drivers/net/can/sja1000/peak_pci.c @@ -70,6 +70,8 @@ struct peak_pci_chan { #define PEAK_PC_104P_DEVICE_ID 0x0006 /* PCAN-PC/104+ cards */ #define PEAK_PCI_104E_DEVICE_ID 0x0007 /* PCAN-PCI/104 Express cards */ #define PEAK_MPCIE_DEVICE_ID 0x0008 /* The miniPCIe slot cards */ +#define PEAK_PCIE_OEM_ID 0x0009 /* PCAN-PCI Express OEM */ +#define PEAK_PCIEC34_DEVICE_ID 0x000A /* PCAN-PCI Express 34 (one channel) */ #define PEAK_PCI_CHAN_MAX 4 @@ -87,6 +89,7 @@ static const struct pci_device_id peak_pci_tbl[] = { {PEAK_PCI_VENDOR_ID, PEAK_CPCI_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #ifdef CONFIG_CAN_PEAK_PCIEC {PEAK_PCI_VENDOR_ID, PEAK_PCIEC_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, + {PEAK_PCI_VENDOR_ID, PEAK_PCIEC34_DEVICE_ID, PCI_ANY_ID, PCI_ANY_ID,}, #endif {0,} }; @@ -653,7 +656,8 @@ static int peak_pci_probe(struct pci_dev *pdev, const struct pci_device_id *ent) * This must be done *before* register_sja1000dev() but * *after* devices linkage */ - if (pdev->device == PEAK_PCIEC_DEVICE_ID) { + if (pdev->device == PEAK_PCIEC_DEVICE_ID || + pdev->device == PEAK_PCIEC34_DEVICE_ID) { err = peak_pciec_probe(pdev, dev); if (err) { dev_err(&pdev->dev, diff --git a/drivers/net/ethernet/3com/3c59x.c b/drivers/net/ethernet/3com/3c59x.c index 3fe45c705933..8ca49f04acec 100644 --- a/drivers/net/ethernet/3com/3c59x.c +++ b/drivers/net/ethernet/3com/3c59x.c @@ -2129,6 +2129,7 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) int entry = vp->cur_tx % TX_RING_SIZE; struct boom_tx_desc *prev_entry = &vp->tx_ring[(vp->cur_tx-1) % TX_RING_SIZE]; unsigned long flags; + dma_addr_t dma_addr; if (vortex_debug > 6) { pr_debug("boomerang_start_xmit()\n"); @@ -2163,24 +2164,48 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded | AddTCPChksum | AddUDPChksum); if (!skb_shinfo(skb)->nr_frags) { - vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, - skb->len, PCI_DMA_TODEVICE)); + dma_addr = pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, + PCI_DMA_TODEVICE); + if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) + goto out_dma_err; + + vp->tx_ring[entry].frag[0].addr = cpu_to_le32(dma_addr); vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb->len | LAST_FRAG); } else { int i; - vp->tx_ring[entry].frag[0].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, - skb_headlen(skb), PCI_DMA_TODEVICE)); + dma_addr = pci_map_single(VORTEX_PCI(vp), skb->data, + skb_headlen(skb), PCI_DMA_TODEVICE); + if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) + goto out_dma_err; + + vp->tx_ring[entry].frag[0].addr = cpu_to_le32(dma_addr); vp->tx_ring[entry].frag[0].length = cpu_to_le32(skb_headlen(skb)); for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) { skb_frag_t *frag = &skb_shinfo(skb)->frags[i]; + dma_addr = skb_frag_dma_map(&VORTEX_PCI(vp)->dev, frag, + 0, + frag->size, + DMA_TO_DEVICE); + if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) { + for(i = i-1; i >= 0; i--) + dma_unmap_page(&VORTEX_PCI(vp)->dev, + le32_to_cpu(vp->tx_ring[entry].frag[i+1].addr), + le32_to_cpu(vp->tx_ring[entry].frag[i+1].length), + DMA_TO_DEVICE); + + pci_unmap_single(VORTEX_PCI(vp), + le32_to_cpu(vp->tx_ring[entry].frag[0].addr), + le32_to_cpu(vp->tx_ring[entry].frag[0].length), + PCI_DMA_TODEVICE); + + goto out_dma_err; + } + vp->tx_ring[entry].frag[i+1].addr = - cpu_to_le32(skb_frag_dma_map( - &VORTEX_PCI(vp)->dev, - frag, - frag->page_offset, frag->size, DMA_TO_DEVICE)); + cpu_to_le32(dma_addr); if (i == skb_shinfo(skb)->nr_frags-1) vp->tx_ring[entry].frag[i+1].length = cpu_to_le32(skb_frag_size(frag)|LAST_FRAG); @@ -2189,7 +2214,10 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) } } #else - vp->tx_ring[entry].addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE)); + dma_addr = cpu_to_le32(pci_map_single(VORTEX_PCI(vp), skb->data, skb->len, PCI_DMA_TODEVICE)); + if (dma_mapping_error(&VORTEX_PCI(vp)->dev, dma_addr)) + goto out_dma_err; + vp->tx_ring[entry].addr = cpu_to_le32(dma_addr); vp->tx_ring[entry].length = cpu_to_le32(skb->len | LAST_FRAG); vp->tx_ring[entry].status = cpu_to_le32(skb->len | TxIntrUploaded); #endif @@ -2217,7 +2245,11 @@ boomerang_start_xmit(struct sk_buff *skb, struct net_device *dev) skb_tx_timestamp(skb); iowrite16(DownUnstall, ioaddr + EL3_CMD); spin_unlock_irqrestore(&vp->lock, flags); +out: return NETDEV_TX_OK; +out_dma_err: + dev_err(&VORTEX_PCI(vp)->dev, "Error mapping dma buffer\n"); + goto out; } /* The interrupt handler does all of the Rx thread work and cleans up diff --git a/drivers/net/ethernet/arc/emac_main.c b/drivers/net/ethernet/arc/emac_main.c index fe5cfeace6e3..5919394d9f58 100644 --- a/drivers/net/ethernet/arc/emac_main.c +++ b/drivers/net/ethernet/arc/emac_main.c @@ -30,6 +30,17 @@ #define DRV_VERSION "1.0" /** + * arc_emac_tx_avail - Return the number of available slots in the tx ring. + * @priv: Pointer to ARC EMAC private data structure. + * + * returns: the number of slots available for transmission in tx the ring. + */ +static inline int arc_emac_tx_avail(struct arc_emac_priv *priv) +{ + return (priv->txbd_dirty + TX_BD_NUM - priv->txbd_curr - 1) % TX_BD_NUM; +} + +/** * arc_emac_adjust_link - Adjust the PHY link duplex. * @ndev: Pointer to the net_device structure. * @@ -180,10 +191,15 @@ static void arc_emac_tx_clean(struct net_device *ndev) txbd->info = 0; *txbd_dirty = (*txbd_dirty + 1) % TX_BD_NUM; - - if (netif_queue_stopped(ndev)) - netif_wake_queue(ndev); } + + /* Ensure that txbd_dirty is visible to tx() before checking + * for queue stopped. + */ + smp_mb(); + + if (netif_queue_stopped(ndev) && arc_emac_tx_avail(priv)) + netif_wake_queue(ndev); } /** @@ -298,7 +314,7 @@ static int arc_emac_poll(struct napi_struct *napi, int budget) work_done = arc_emac_rx(ndev, budget); if (work_done < budget) { napi_complete(napi); - arc_reg_or(priv, R_ENABLE, RXINT_MASK); + arc_reg_or(priv, R_ENABLE, RXINT_MASK | TXINT_MASK); } return work_done; @@ -327,9 +343,9 @@ static irqreturn_t arc_emac_intr(int irq, void *dev_instance) /* Reset all flags except "MDIO complete" */ arc_reg_set(priv, R_STATUS, status); - if (status & RXINT_MASK) { + if (status & (RXINT_MASK | TXINT_MASK)) { if (likely(napi_schedule_prep(&priv->napi))) { - arc_reg_clr(priv, R_ENABLE, RXINT_MASK); + arc_reg_clr(priv, R_ENABLE, RXINT_MASK | TXINT_MASK); __napi_schedule(&priv->napi); } } @@ -440,7 +456,7 @@ static int arc_emac_open(struct net_device *ndev) arc_reg_set(priv, R_TX_RING, (unsigned int)priv->txbd_dma); /* Enable interrupts */ - arc_reg_set(priv, R_ENABLE, RXINT_MASK | ERR_MASK); + arc_reg_set(priv, R_ENABLE, RXINT_MASK | TXINT_MASK | ERR_MASK); /* Set CONTROL */ arc_reg_set(priv, R_CTRL, @@ -511,7 +527,7 @@ static int arc_emac_stop(struct net_device *ndev) netif_stop_queue(ndev); /* Disable interrupts */ - arc_reg_clr(priv, R_ENABLE, RXINT_MASK | ERR_MASK); + arc_reg_clr(priv, R_ENABLE, RXINT_MASK | TXINT_MASK | ERR_MASK); /* Disable EMAC */ arc_reg_clr(priv, R_CTRL, EN_MASK); @@ -574,11 +590,9 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) len = max_t(unsigned int, ETH_ZLEN, skb->len); - /* EMAC still holds this buffer in its possession. - * CPU must not modify this buffer descriptor - */ - if (unlikely((le32_to_cpu(*info) & OWN_MASK) == FOR_EMAC)) { + if (unlikely(!arc_emac_tx_avail(priv))) { netif_stop_queue(ndev); + netdev_err(ndev, "BUG! Tx Ring full when queue awake!\n"); return NETDEV_TX_BUSY; } @@ -607,12 +621,19 @@ static int arc_emac_tx(struct sk_buff *skb, struct net_device *ndev) /* Increment index to point to the next BD */ *txbd_curr = (*txbd_curr + 1) % TX_BD_NUM; - /* Get "info" of the next BD */ - info = &priv->txbd[*txbd_curr].info; + /* Ensure that tx_clean() sees the new txbd_curr before + * checking the queue status. This prevents an unneeded wake + * of the queue in tx_clean(). + */ + smp_mb(); - /* Check if if Tx BD ring is full - next BD is still owned by EMAC */ - if (unlikely((le32_to_cpu(*info) & OWN_MASK) == FOR_EMAC)) + if (!arc_emac_tx_avail(priv)) { netif_stop_queue(ndev); + /* Refresh tx_dirty */ + smp_mb(); + if (arc_emac_tx_avail(priv)) + netif_start_queue(ndev); + } arc_reg_set(priv, R_STATUS, TXPL_MASK); diff --git a/drivers/net/ethernet/broadcom/b44.c b/drivers/net/ethernet/broadcom/b44.c index 4a7028d65912..d588136b23b9 100644 --- a/drivers/net/ethernet/broadcom/b44.c +++ b/drivers/net/ethernet/broadcom/b44.c @@ -1697,7 +1697,7 @@ static struct rtnl_link_stats64 *b44_get_stats64(struct net_device *dev, hwstat->tx_underruns + hwstat->tx_excessive_cols + hwstat->tx_late_cols); - nstat->multicast = hwstat->tx_multicast_pkts; + nstat->multicast = hwstat->rx_multicast_pkts; nstat->collisions = hwstat->tx_total_cols; nstat->rx_length_errors = (hwstat->rx_oversize_pkts + diff --git a/drivers/net/ethernet/broadcom/bcmsysport.c b/drivers/net/ethernet/broadcom/bcmsysport.c index 6f4e18644bd4..d9b9170ed2fc 100644 --- a/drivers/net/ethernet/broadcom/bcmsysport.c +++ b/drivers/net/ethernet/broadcom/bcmsysport.c @@ -534,6 +534,25 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, while ((processed < to_process) && (processed < budget)) { cb = &priv->rx_cbs[priv->rx_read_ptr]; skb = cb->skb; + + processed++; + priv->rx_read_ptr++; + + if (priv->rx_read_ptr == priv->num_rx_bds) + priv->rx_read_ptr = 0; + + /* We do not have a backing SKB, so we do not a corresponding + * DMA mapping for this incoming packet since + * bcm_sysport_rx_refill always either has both skb and mapping + * or none. + */ + if (unlikely(!skb)) { + netif_err(priv, rx_err, ndev, "out of memory!\n"); + ndev->stats.rx_dropped++; + ndev->stats.rx_errors++; + goto refill; + } + dma_unmap_single(kdev, dma_unmap_addr(cb, dma_addr), RX_BUF_LENGTH, DMA_FROM_DEVICE); @@ -543,23 +562,11 @@ static unsigned int bcm_sysport_desc_rx(struct bcm_sysport_priv *priv, status = (rsb->rx_status_len >> DESC_STATUS_SHIFT) & DESC_STATUS_MASK; - processed++; - priv->rx_read_ptr++; - if (priv->rx_read_ptr == priv->num_rx_bds) - priv->rx_read_ptr = 0; - netif_dbg(priv, rx_status, ndev, "p=%d, c=%d, rd_ptr=%d, len=%d, flag=0x%04x\n", p_index, priv->rx_c_index, priv->rx_read_ptr, len, status); - if (unlikely(!skb)) { - netif_err(priv, rx_err, ndev, "out of memory!\n"); - ndev->stats.rx_dropped++; - ndev->stats.rx_errors++; - goto refill; - } - if (unlikely(!(status & DESC_EOP) || !(status & DESC_SOP))) { netif_err(priv, rx_status, ndev, "fragmented packet!\n"); ndev->stats.rx_dropped++; diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c index 3f9d4de8173c..5cc9cae21ed5 100644 --- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c +++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c @@ -875,6 +875,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, int last_tx_cn, last_c_index, num_tx_bds; struct enet_cb *tx_cb_ptr; struct netdev_queue *txq; + unsigned int bds_compl; unsigned int c_index; /* Compute how many buffers are transmitted since last xmit call */ @@ -899,7 +900,9 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, /* Reclaim transmitted buffers */ while (last_tx_cn-- > 0) { tx_cb_ptr = ring->cbs + last_c_index; + bds_compl = 0; if (tx_cb_ptr->skb) { + bds_compl = skb_shinfo(tx_cb_ptr->skb)->nr_frags + 1; dev->stats.tx_bytes += tx_cb_ptr->skb->len; dma_unmap_single(&dev->dev, dma_unmap_addr(tx_cb_ptr, dma_addr), @@ -916,7 +919,7 @@ static void __bcmgenet_tx_reclaim(struct net_device *dev, dma_unmap_addr_set(tx_cb_ptr, dma_addr, 0); } dev->stats.tx_packets++; - ring->free_bds += 1; + ring->free_bds += bds_compl; last_c_index++; last_c_index &= (num_tx_bds - 1); @@ -1274,12 +1277,29 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, while ((rxpktprocessed < rxpkttoprocess) && (rxpktprocessed < budget)) { + cb = &priv->rx_cbs[priv->rx_read_ptr]; + skb = cb->skb; + + rxpktprocessed++; + + priv->rx_read_ptr++; + priv->rx_read_ptr &= (priv->num_rx_bds - 1); + + /* We do not have a backing SKB, so we do not have a + * corresponding DMA mapping for this incoming packet since + * bcmgenet_rx_refill always either has both skb and mapping or + * none. + */ + if (unlikely(!skb)) { + dev->stats.rx_dropped++; + dev->stats.rx_errors++; + goto refill; + } + /* Unmap the packet contents such that we can use the * RSV from the 64 bytes descriptor when enabled and save * a 32-bits register read */ - cb = &priv->rx_cbs[priv->rx_read_ptr]; - skb = cb->skb; dma_unmap_single(&dev->dev, dma_unmap_addr(cb, dma_addr), priv->rx_buf_len, DMA_FROM_DEVICE); @@ -1307,18 +1327,6 @@ static unsigned int bcmgenet_desc_rx(struct bcmgenet_priv *priv, __func__, p_index, priv->rx_c_index, priv->rx_read_ptr, dma_length_status); - rxpktprocessed++; - - priv->rx_read_ptr++; - priv->rx_read_ptr &= (priv->num_rx_bds - 1); - - /* out of memory, just drop packets at the hardware level */ - if (unlikely(!skb)) { - dev->stats.rx_dropped++; - dev->stats.rx_errors++; - goto refill; - } - if (unlikely(!(dma_flag & DMA_EOP) || !(dma_flag & DMA_SOP))) { netif_err(priv, rx_status, dev, "dropping fragmented packet!\n"); @@ -1736,13 +1744,63 @@ static void bcmgenet_init_multiq(struct net_device *dev) bcmgenet_tdma_writel(priv, reg, DMA_CTRL); } +static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv) +{ + int ret = 0; + int timeout = 0; + u32 reg; + + /* Disable TDMA to stop add more frames in TX DMA */ + reg = bcmgenet_tdma_readl(priv, DMA_CTRL); + reg &= ~DMA_EN; + bcmgenet_tdma_writel(priv, reg, DMA_CTRL); + + /* Check TDMA status register to confirm TDMA is disabled */ + while (timeout++ < DMA_TIMEOUT_VAL) { + reg = bcmgenet_tdma_readl(priv, DMA_STATUS); + if (reg & DMA_DISABLED) + break; + + udelay(1); + } + + if (timeout == DMA_TIMEOUT_VAL) { + netdev_warn(priv->dev, "Timed out while disabling TX DMA\n"); + ret = -ETIMEDOUT; + } + + /* Wait 10ms for packet drain in both tx and rx dma */ + usleep_range(10000, 20000); + + /* Disable RDMA */ + reg = bcmgenet_rdma_readl(priv, DMA_CTRL); + reg &= ~DMA_EN; + bcmgenet_rdma_writel(priv, reg, DMA_CTRL); + + timeout = 0; + /* Check RDMA status register to confirm RDMA is disabled */ + while (timeout++ < DMA_TIMEOUT_VAL) { + reg = bcmgenet_rdma_readl(priv, DMA_STATUS); + if (reg & DMA_DISABLED) + break; + + udelay(1); + } + + if (timeout == DMA_TIMEOUT_VAL) { + netdev_warn(priv->dev, "Timed out while disabling RX DMA\n"); + ret = -ETIMEDOUT; + } + + return ret; +} + static void bcmgenet_fini_dma(struct bcmgenet_priv *priv) { int i; /* disable DMA */ - bcmgenet_rdma_writel(priv, 0, DMA_CTRL); - bcmgenet_tdma_writel(priv, 0, DMA_CTRL); + bcmgenet_dma_teardown(priv); for (i = 0; i < priv->num_tx_bds; i++) { if (priv->tx_cbs[i].skb != NULL) { @@ -2101,57 +2159,6 @@ err_clk_disable: return ret; } -static int bcmgenet_dma_teardown(struct bcmgenet_priv *priv) -{ - int ret = 0; - int timeout = 0; - u32 reg; - - /* Disable TDMA to stop add more frames in TX DMA */ - reg = bcmgenet_tdma_readl(priv, DMA_CTRL); - reg &= ~DMA_EN; - bcmgenet_tdma_writel(priv, reg, DMA_CTRL); - - /* Check TDMA status register to confirm TDMA is disabled */ - while (timeout++ < DMA_TIMEOUT_VAL) { - reg = bcmgenet_tdma_readl(priv, DMA_STATUS); - if (reg & DMA_DISABLED) - break; - - udelay(1); - } - - if (timeout == DMA_TIMEOUT_VAL) { - netdev_warn(priv->dev, "Timed out while disabling TX DMA\n"); - ret = -ETIMEDOUT; - } - - /* Wait 10ms for packet drain in both tx and rx dma */ - usleep_range(10000, 20000); - - /* Disable RDMA */ - reg = bcmgenet_rdma_readl(priv, DMA_CTRL); - reg &= ~DMA_EN; - bcmgenet_rdma_writel(priv, reg, DMA_CTRL); - - timeout = 0; - /* Check RDMA status register to confirm RDMA is disabled */ - while (timeout++ < DMA_TIMEOUT_VAL) { - reg = bcmgenet_rdma_readl(priv, DMA_STATUS); - if (reg & DMA_DISABLED) - break; - - udelay(1); - } - - if (timeout == DMA_TIMEOUT_VAL) { - netdev_warn(priv->dev, "Timed out while disabling RX DMA\n"); - ret = -ETIMEDOUT; - } - - return ret; -} - static void bcmgenet_netif_stop(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); diff --git a/drivers/net/ethernet/broadcom/tg3.c b/drivers/net/ethernet/broadcom/tg3.c index cb77ae93d89a..e7d3a620d96a 100644 --- a/drivers/net/ethernet/broadcom/tg3.c +++ b/drivers/net/ethernet/broadcom/tg3.c @@ -7914,8 +7914,6 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) entry = tnapi->tx_prod; base_flags = 0; - if (skb->ip_summed == CHECKSUM_PARTIAL) - base_flags |= TXD_FLAG_TCPUDP_CSUM; mss = skb_shinfo(skb)->gso_size; if (mss) { @@ -7929,6 +7927,13 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) hdr_len = skb_transport_offset(skb) + tcp_hdrlen(skb) - ETH_HLEN; + /* HW/FW can not correctly segment packets that have been + * vlan encapsulated. + */ + if (skb->protocol == htons(ETH_P_8021Q) || + skb->protocol == htons(ETH_P_8021AD)) + return tg3_tso_bug(tp, tnapi, txq, skb); + if (!skb_is_gso_v6(skb)) { if (unlikely((ETH_HLEN + hdr_len) > 80) && tg3_flag(tp, TSO_BUG)) @@ -7979,6 +7984,17 @@ static netdev_tx_t tg3_start_xmit(struct sk_buff *skb, struct net_device *dev) base_flags |= tsflags << 12; } } + } else if (skb->ip_summed == CHECKSUM_PARTIAL) { + /* HW/FW can not correctly checksum packets that have been + * vlan encapsulated. + */ + if (skb->protocol == htons(ETH_P_8021Q) || + skb->protocol == htons(ETH_P_8021AD)) { + if (skb_checksum_help(skb)) + goto drop; + } else { + base_flags |= TXD_FLAG_TCPUDP_CSUM; + } } if (tg3_flag(tp, USE_JUMBO_BDFLAG) && diff --git a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c index 8c34811a1128..e5be511a3c38 100644 --- a/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c +++ b/drivers/net/ethernet/chelsio/cxgb4/cxgb4_main.c @@ -6478,6 +6478,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) struct port_info *pi; bool highdma = false; struct adapter *adapter = NULL; + void __iomem *regs; printk_once(KERN_INFO "%s - version %s\n", DRV_DESC, DRV_VERSION); @@ -6494,19 +6495,35 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto out_release_regions; } + regs = pci_ioremap_bar(pdev, 0); + if (!regs) { + dev_err(&pdev->dev, "cannot map device registers\n"); + err = -ENOMEM; + goto out_disable_device; + } + + /* We control everything through one PF */ + func = SOURCEPF_GET(readl(regs + PL_WHOAMI)); + if (func != ent->driver_data) { + iounmap(regs); + pci_disable_device(pdev); + pci_save_state(pdev); /* to restore SR-IOV later */ + goto sriov; + } + if (!pci_set_dma_mask(pdev, DMA_BIT_MASK(64))) { highdma = true; err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(64)); if (err) { dev_err(&pdev->dev, "unable to obtain 64-bit DMA for " "coherent allocations\n"); - goto out_disable_device; + goto out_unmap_bar0; } } else { err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32)); if (err) { dev_err(&pdev->dev, "no usable DMA configuration\n"); - goto out_disable_device; + goto out_unmap_bar0; } } @@ -6518,7 +6535,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) adapter = kzalloc(sizeof(*adapter), GFP_KERNEL); if (!adapter) { err = -ENOMEM; - goto out_disable_device; + goto out_unmap_bar0; } adapter->workq = create_singlethread_workqueue("cxgb4"); @@ -6530,20 +6547,7 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) /* PCI device has been enabled */ adapter->flags |= DEV_ENABLED; - adapter->regs = pci_ioremap_bar(pdev, 0); - if (!adapter->regs) { - dev_err(&pdev->dev, "cannot map device registers\n"); - err = -ENOMEM; - goto out_free_adapter; - } - - /* We control everything through one PF */ - func = SOURCEPF_GET(readl(adapter->regs + PL_WHOAMI)); - if (func != ent->driver_data) { - pci_save_state(pdev); /* to restore SR-IOV later */ - goto sriov; - } - + adapter->regs = regs; adapter->pdev = pdev; adapter->pdev_dev = &pdev->dev; adapter->mbox = func; @@ -6560,7 +6564,8 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) err = t4_prep_adapter(adapter); if (err) - goto out_unmap_bar0; + goto out_free_adapter; + if (!is_t4(adapter->params.chip)) { s_qpp = QUEUESPERPAGEPF1 * adapter->fn; @@ -6577,14 +6582,14 @@ static int init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev_err(&pdev->dev, "Incorrect number of egress queues per page\n"); err = -EINVAL; - goto out_unmap_bar0; + goto out_free_adapter; } adapter->bar2 = ioremap_wc(pci_resource_start(pdev, 2), pci_resource_len(pdev, 2)); if (!adapter->bar2) { dev_err(&pdev->dev, "cannot map device bar2 region\n"); err = -ENOMEM; - goto out_unmap_bar0; + goto out_free_adapter; } } @@ -6722,13 +6727,13 @@ sriov: out_unmap_bar: if (!is_t4(adapter->params.chip)) iounmap(adapter->bar2); - out_unmap_bar0: - iounmap(adapter->regs); out_free_adapter: if (adapter->workq) destroy_workqueue(adapter->workq); kfree(adapter); + out_unmap_bar0: + iounmap(regs); out_disable_device: pci_disable_pcie_error_reporting(pdev); pci_disable_device(pdev); diff --git a/drivers/net/ethernet/davicom/dm9000.c b/drivers/net/ethernet/davicom/dm9000.c index 9b33057a9477..70089c29d307 100644 --- a/drivers/net/ethernet/davicom/dm9000.c +++ b/drivers/net/ethernet/davicom/dm9000.c @@ -1399,7 +1399,7 @@ static struct dm9000_plat_data *dm9000_parse_dt(struct device *dev) const void *mac_addr; if (!IS_ENABLED(CONFIG_OF) || !np) - return NULL; + return ERR_PTR(-ENXIO); pdata = devm_kzalloc(dev, sizeof(*pdata), GFP_KERNEL); if (!pdata) diff --git a/drivers/net/ethernet/mellanox/mlx4/cmd.c b/drivers/net/ethernet/mellanox/mlx4/cmd.c index 65a4a0f88ea0..02a2e90d581a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/cmd.c +++ b/drivers/net/ethernet/mellanox/mlx4/cmd.c @@ -2389,6 +2389,22 @@ struct mlx4_slaves_pport mlx4_phys_to_slaves_pport_actv( } EXPORT_SYMBOL_GPL(mlx4_phys_to_slaves_pport_actv); +static int mlx4_slaves_closest_port(struct mlx4_dev *dev, int slave, int port) +{ + struct mlx4_active_ports actv_ports = mlx4_get_active_ports(dev, slave); + int min_port = find_first_bit(actv_ports.ports, dev->caps.num_ports) + + 1; + int max_port = min_port + + bitmap_weight(actv_ports.ports, dev->caps.num_ports); + + if (port < min_port) + port = min_port; + else if (port >= max_port) + port = max_port - 1; + + return port; +} + int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) { struct mlx4_priv *priv = mlx4_priv(dev); @@ -2402,6 +2418,7 @@ int mlx4_set_vf_mac(struct mlx4_dev *dev, int port, int vf, u64 mac) if (slave < 0) return -EINVAL; + port = mlx4_slaves_closest_port(dev, slave, port); s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; s_info->mac = mac; mlx4_info(dev, "default mac on vf %d port %d to %llX will take afect only after vf restart\n", @@ -2428,6 +2445,7 @@ int mlx4_set_vf_vlan(struct mlx4_dev *dev, int port, int vf, u16 vlan, u8 qos) if (slave < 0) return -EINVAL; + port = mlx4_slaves_closest_port(dev, slave, port); vf_admin = &priv->mfunc.master.vf_admin[slave].vport[port]; if ((0 == vlan) && (0 == qos)) @@ -2455,6 +2473,7 @@ bool mlx4_get_slave_default_vlan(struct mlx4_dev *dev, int port, int slave, struct mlx4_priv *priv; priv = mlx4_priv(dev); + port = mlx4_slaves_closest_port(dev, slave, port); vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; if (MLX4_VGT != vp_oper->state.default_vlan) { @@ -2482,6 +2501,7 @@ int mlx4_set_vf_spoofchk(struct mlx4_dev *dev, int port, int vf, bool setting) if (slave < 0) return -EINVAL; + port = mlx4_slaves_closest_port(dev, slave, port); s_info = &priv->mfunc.master.vf_admin[slave].vport[port]; s_info->spoofchk = setting; @@ -2535,6 +2555,7 @@ int mlx4_set_vf_link_state(struct mlx4_dev *dev, int port, int vf, int link_stat if (slave < 0) return -EINVAL; + port = mlx4_slaves_closest_port(dev, slave, port); switch (link_state) { case IFLA_VF_LINK_STATE_AUTO: /* get current link state */ diff --git a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c index e22f24f784fc..35ff2925110a 100644 --- a/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c +++ b/drivers/net/ethernet/mellanox/mlx4/en_ethtool.c @@ -487,6 +487,9 @@ static int mlx4_en_set_pauseparam(struct net_device *dev, struct mlx4_en_dev *mdev = priv->mdev; int err; + if (pause->autoneg) + return -EINVAL; + priv->prof->tx_pause = pause->tx_pause != 0; priv->prof->rx_pause = pause->rx_pause != 0; err = mlx4_SET_PORT_general(mdev->dev, priv->port, diff --git a/drivers/net/ethernet/mellanox/mlx4/mr.c b/drivers/net/ethernet/mellanox/mlx4/mr.c index 7d717eccb7b0..193a6adb5d04 100644 --- a/drivers/net/ethernet/mellanox/mlx4/mr.c +++ b/drivers/net/ethernet/mellanox/mlx4/mr.c @@ -298,6 +298,7 @@ static int mlx4_HW2SW_MPT(struct mlx4_dev *dev, struct mlx4_cmd_mailbox *mailbox MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); } +/* Must protect against concurrent access */ int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr, struct mlx4_mpt_entry ***mpt_entry) { @@ -305,13 +306,10 @@ int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr, int key = key_to_hw_index(mmr->key) & (dev->caps.num_mpts - 1); struct mlx4_cmd_mailbox *mailbox = NULL; - /* Make sure that at this point we have single-threaded access only */ - if (mmr->enabled != MLX4_MPT_EN_HW) return -EINVAL; err = mlx4_HW2SW_MPT(dev, NULL, key); - if (err) { mlx4_warn(dev, "HW2SW_MPT failed (%d).", err); mlx4_warn(dev, "Most likely the MR has MWs bound to it.\n"); @@ -333,7 +331,6 @@ int mlx4_mr_hw_get_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr, 0, MLX4_CMD_QUERY_MPT, MLX4_CMD_TIME_CLASS_B, MLX4_CMD_WRAPPED); - if (err) goto free_mailbox; @@ -378,9 +375,10 @@ int mlx4_mr_hw_write_mpt(struct mlx4_dev *dev, struct mlx4_mr *mmr, err = mlx4_SW2HW_MPT(dev, mailbox, key); } - mmr->pd = be32_to_cpu((*mpt_entry)->pd_flags) & MLX4_MPT_PD_MASK; - if (!err) + if (!err) { + mmr->pd = be32_to_cpu((*mpt_entry)->pd_flags) & MLX4_MPT_PD_MASK; mmr->enabled = MLX4_MPT_EN_HW; + } return err; } EXPORT_SYMBOL_GPL(mlx4_mr_hw_write_mpt); @@ -400,11 +398,12 @@ EXPORT_SYMBOL_GPL(mlx4_mr_hw_put_mpt); int mlx4_mr_hw_change_pd(struct mlx4_dev *dev, struct mlx4_mpt_entry *mpt_entry, u32 pdn) { - u32 pd_flags = be32_to_cpu(mpt_entry->pd_flags); + u32 pd_flags = be32_to_cpu(mpt_entry->pd_flags) & ~MLX4_MPT_PD_MASK; /* The wrapper function will put the slave's id here */ if (mlx4_is_mfunc(dev)) pd_flags &= ~MLX4_MPT_PD_VF_MASK; - mpt_entry->pd_flags = cpu_to_be32((pd_flags & ~MLX4_MPT_PD_MASK) | + + mpt_entry->pd_flags = cpu_to_be32(pd_flags | (pdn & MLX4_MPT_PD_MASK) | MLX4_MPT_PD_FLAG_EN_INV); return 0; @@ -600,14 +599,18 @@ int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr, { int err; - mpt_entry->start = cpu_to_be64(mr->iova); - mpt_entry->length = cpu_to_be64(mr->size); - mpt_entry->entity_size = cpu_to_be32(mr->mtt.page_shift); + mpt_entry->start = cpu_to_be64(iova); + mpt_entry->length = cpu_to_be64(size); + mpt_entry->entity_size = cpu_to_be32(page_shift); err = mlx4_mtt_init(dev, npages, page_shift, &mr->mtt); if (err) return err; + mpt_entry->pd_flags &= cpu_to_be32(MLX4_MPT_PD_MASK | + MLX4_MPT_PD_FLAG_EN_INV); + mpt_entry->flags &= cpu_to_be32(MLX4_MPT_FLAG_FREE | + MLX4_MPT_FLAG_SW_OWNS); if (mr->mtt.order < 0) { mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_PHYSICAL); mpt_entry->mtt_addr = 0; @@ -617,6 +620,14 @@ int mlx4_mr_rereg_mem_write(struct mlx4_dev *dev, struct mlx4_mr *mr, if (mr->mtt.page_shift == 0) mpt_entry->mtt_sz = cpu_to_be32(1 << mr->mtt.order); } + if (mr->mtt.order >= 0 && mr->mtt.page_shift == 0) { + /* fast register MR in free state */ + mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_FREE); + mpt_entry->pd_flags |= cpu_to_be32(MLX4_MPT_PD_FLAG_FAST_REG | + MLX4_MPT_PD_FLAG_RAE); + } else { + mpt_entry->flags |= cpu_to_be32(MLX4_MPT_FLAG_SW_OWNS); + } mr->enabled = MLX4_MPT_EN_SW; return 0; diff --git a/drivers/net/ethernet/mellanox/mlx4/port.c b/drivers/net/ethernet/mellanox/mlx4/port.c index 9ba0c1ca10d5..94eeb2c7d7e4 100644 --- a/drivers/net/ethernet/mellanox/mlx4/port.c +++ b/drivers/net/ethernet/mellanox/mlx4/port.c @@ -103,7 +103,8 @@ static int find_index(struct mlx4_dev *dev, int i; for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { - if ((mac & MLX4_MAC_MASK) == + if (table->refs[i] && + (MLX4_MAC_MASK & mac) == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) return i; } @@ -165,12 +166,14 @@ int __mlx4_register_mac(struct mlx4_dev *dev, u8 port, u64 mac) mutex_lock(&table->mutex); for (i = 0; i < MLX4_MAX_MAC_NUM; i++) { - if (free < 0 && !table->entries[i]) { - free = i; + if (!table->refs[i]) { + if (free < 0) + free = i; continue; } - if (mac == (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { + if ((MLX4_MAC_MASK & mac) == + (MLX4_MAC_MASK & be64_to_cpu(table->entries[i]))) { /* MAC already registered, increment ref count */ err = i; ++table->refs[i]; diff --git a/drivers/net/ethernet/mellanox/mlx4/qp.c b/drivers/net/ethernet/mellanox/mlx4/qp.c index 0dc31d85fc3b..2301365c79c7 100644 --- a/drivers/net/ethernet/mellanox/mlx4/qp.c +++ b/drivers/net/ethernet/mellanox/mlx4/qp.c @@ -390,13 +390,14 @@ err_icm: EXPORT_SYMBOL_GPL(mlx4_qp_alloc); #define MLX4_UPDATE_QP_SUPPORTED_ATTRS MLX4_UPDATE_QP_SMAC -int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp, +int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, enum mlx4_update_qp_attr attr, struct mlx4_update_qp_params *params) { struct mlx4_cmd_mailbox *mailbox; struct mlx4_update_qp_context *cmd; u64 pri_addr_path_mask = 0; + u64 qp_mask = 0; int err = 0; mailbox = mlx4_alloc_cmd_mailbox(dev); @@ -413,9 +414,16 @@ int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp, cmd->qp_context.pri_path.grh_mylmc = params->smac_index; } + if (attr & MLX4_UPDATE_QP_VSD) { + qp_mask |= 1ULL << MLX4_UPD_QP_MASK_VSD; + if (params->flags & MLX4_UPDATE_QP_PARAMS_FLAGS_VSD_ENABLE) + cmd->qp_context.param3 |= cpu_to_be32(MLX4_STRIP_VLAN); + } + cmd->primary_addr_path_mask = cpu_to_be64(pri_addr_path_mask); + cmd->qp_mask = cpu_to_be64(qp_mask); - err = mlx4_cmd(dev, mailbox->dma, qp->qpn & 0xffffff, 0, + err = mlx4_cmd(dev, mailbox->dma, qpn & 0xffffff, 0, MLX4_CMD_UPDATE_QP, MLX4_CMD_TIME_CLASS_A, MLX4_CMD_NATIVE); diff --git a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c index 1089367fed22..5d2498dcf536 100644 --- a/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c +++ b/drivers/net/ethernet/mellanox/mlx4/resource_tracker.c @@ -702,11 +702,13 @@ static int update_vport_qp_param(struct mlx4_dev *dev, struct mlx4_qp_context *qpc = inbox->buf + 8; struct mlx4_vport_oper_state *vp_oper; struct mlx4_priv *priv; + u32 qp_type; int port; port = (qpc->pri_path.sched_queue & 0x40) ? 2 : 1; priv = mlx4_priv(dev); vp_oper = &priv->mfunc.master.vf_oper[slave].vport[port]; + qp_type = (be32_to_cpu(qpc->flags) >> 16) & 0xff; if (MLX4_VGT != vp_oper->state.default_vlan) { /* the reserved QPs (special, proxy, tunnel) @@ -715,8 +717,20 @@ static int update_vport_qp_param(struct mlx4_dev *dev, if (mlx4_is_qp_reserved(dev, qpn)) return 0; - /* force strip vlan by clear vsd */ - qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN); + /* force strip vlan by clear vsd, MLX QP refers to Raw Ethernet */ + if (qp_type == MLX4_QP_ST_UD || + (qp_type == MLX4_QP_ST_MLX && mlx4_is_eth(dev, port))) { + if (dev->caps.bmme_flags & MLX4_BMME_FLAG_VSD_INIT2RTR) { + *(__be32 *)inbox->buf = + cpu_to_be32(be32_to_cpu(*(__be32 *)inbox->buf) | + MLX4_QP_OPTPAR_VLAN_STRIPPING); + qpc->param3 &= ~cpu_to_be32(MLX4_STRIP_VLAN); + } else { + struct mlx4_update_qp_params params = {.flags = 0}; + + mlx4_update_qp(dev, qpn, MLX4_UPDATE_QP_VSD, ¶ms); + } + } if (vp_oper->state.link_state == IFLA_VF_LINK_STATE_DISABLE && dev->caps.flags2 & MLX4_DEV_CAP_FLAG2_UPDATE_QP) { @@ -3998,13 +4012,17 @@ int mlx4_UPDATE_QP_wrapper(struct mlx4_dev *dev, int slave, } port = (rqp->sched_queue >> 6 & 1) + 1; - smac_index = cmd->qp_context.pri_path.grh_mylmc; - err = mac_find_smac_ix_in_slave(dev, slave, port, - smac_index, &mac); - if (err) { - mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n", - qpn, smac_index); - goto err_mac; + + if (pri_addr_path_mask & (1ULL << MLX4_UPD_QP_PATH_MASK_MAC_INDEX)) { + smac_index = cmd->qp_context.pri_path.grh_mylmc; + err = mac_find_smac_ix_in_slave(dev, slave, port, + smac_index, &mac); + + if (err) { + mlx4_err(dev, "Failed to update qpn 0x%x, MAC is invalid. smac_ix: %d\n", + qpn, smac_index); + goto err_mac; + } } err = mlx4_cmd(dev, inbox->dma, @@ -4818,7 +4836,7 @@ void mlx4_vf_immed_vlan_work_handler(struct work_struct *_work) MLX4_VLAN_CTRL_ETH_RX_BLOCK_UNTAGGED; upd_context = mailbox->buf; - upd_context->qp_mask = cpu_to_be64(MLX4_UPD_QP_MASK_VSD); + upd_context->qp_mask = cpu_to_be64(1ULL << MLX4_UPD_QP_MASK_VSD); spin_lock_irq(mlx4_tlock(dev)); list_for_each_entry_safe(qp, tmp, qp_list, com.list) { diff --git a/drivers/net/ethernet/octeon/octeon_mgmt.c b/drivers/net/ethernet/octeon/octeon_mgmt.c index 979c6980639f..a42293092ea4 100644 --- a/drivers/net/ethernet/octeon/octeon_mgmt.c +++ b/drivers/net/ethernet/octeon/octeon_mgmt.c @@ -290,9 +290,11 @@ static void octeon_mgmt_clean_tx_buffers(struct octeon_mgmt *p) /* Read the hardware TX timestamp if one was recorded */ if (unlikely(re.s.tstamp)) { struct skb_shared_hwtstamps ts; + u64 ns; + memset(&ts, 0, sizeof(ts)); /* Read the timestamp */ - u64 ns = cvmx_read_csr(CVMX_MIXX_TSTAMP(p->port)); + ns = cvmx_read_csr(CVMX_MIXX_TSTAMP(p->port)); /* Remove the timestamp from the FIFO */ cvmx_write_csr(CVMX_MIXX_TSCTL(p->port), 0); /* Tell the kernel about the timestamp */ diff --git a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig index 44c8be1c6805..5f7a35212796 100644 --- a/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig +++ b/drivers/net/ethernet/oki-semi/pch_gbe/Kconfig @@ -7,6 +7,7 @@ config PCH_GBE depends on PCI && (X86_32 || COMPILE_TEST) select MII select PTP_1588_CLOCK_PCH + select NET_PTP_CLASSIFY ---help--- This is a gigabit ethernet driver for EG20T PCH. EG20T PCH is the platform controller hub that is used in Intel's diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c index 91652e7235e4..0921302553c6 100644 --- a/drivers/net/ethernet/realtek/r8169.c +++ b/drivers/net/ethernet/realtek/r8169.c @@ -1783,33 +1783,31 @@ static void __rtl8169_set_features(struct net_device *dev, netdev_features_t features) { struct rtl8169_private *tp = netdev_priv(dev); - netdev_features_t changed = features ^ dev->features; void __iomem *ioaddr = tp->mmio_addr; + u32 rx_config; - if (!(changed & (NETIF_F_RXALL | NETIF_F_RXCSUM | - NETIF_F_HW_VLAN_CTAG_RX))) - return; + rx_config = RTL_R32(RxConfig); + if (features & NETIF_F_RXALL) + rx_config |= (AcceptErr | AcceptRunt); + else + rx_config &= ~(AcceptErr | AcceptRunt); - if (changed & (NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX)) { - if (features & NETIF_F_RXCSUM) - tp->cp_cmd |= RxChkSum; - else - tp->cp_cmd &= ~RxChkSum; + RTL_W32(RxConfig, rx_config); - if (dev->features & NETIF_F_HW_VLAN_CTAG_RX) - tp->cp_cmd |= RxVlan; - else - tp->cp_cmd &= ~RxVlan; + if (features & NETIF_F_RXCSUM) + tp->cp_cmd |= RxChkSum; + else + tp->cp_cmd &= ~RxChkSum; - RTL_W16(CPlusCmd, tp->cp_cmd); - RTL_R16(CPlusCmd); - } - if (changed & NETIF_F_RXALL) { - int tmp = (RTL_R32(RxConfig) & ~(AcceptErr | AcceptRunt)); - if (features & NETIF_F_RXALL) - tmp |= (AcceptErr | AcceptRunt); - RTL_W32(RxConfig, tmp); - } + if (features & NETIF_F_HW_VLAN_CTAG_RX) + tp->cp_cmd |= RxVlan; + else + tp->cp_cmd &= ~RxVlan; + + tp->cp_cmd |= RTL_R16(CPlusCmd) & ~(RxVlan | RxChkSum); + + RTL_W16(CPlusCmd, tp->cp_cmd); + RTL_R16(CPlusCmd); } static int rtl8169_set_features(struct net_device *dev, @@ -1817,8 +1815,11 @@ static int rtl8169_set_features(struct net_device *dev, { struct rtl8169_private *tp = netdev_priv(dev); + features &= NETIF_F_RXALL | NETIF_F_RXCSUM | NETIF_F_HW_VLAN_CTAG_RX; + rtl_lock_work(tp); - __rtl8169_set_features(dev, features); + if (features ^ dev->features) + __rtl8169_set_features(dev, features); rtl_unlock_work(tp); return 0; @@ -7118,8 +7119,7 @@ static void rtl_hw_initialize(struct rtl8169_private *tp) } } -static int -rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) +static int rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) { const struct rtl_cfg_info *cfg = rtl_cfg_infos + ent->driver_data; const unsigned int region = cfg->region; @@ -7194,7 +7194,7 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) goto err_out_mwi_2; } - tp->cp_cmd = RxChkSum; + tp->cp_cmd = 0; if ((sizeof(dma_addr_t) > 4) && !pci_set_dma_mask(pdev, DMA_BIT_MASK(64)) && use_dac) { @@ -7235,13 +7235,6 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) pci_set_master(pdev); - /* - * Pretend we are using VLANs; This bypasses a nasty bug where - * Interrupts stop flowing on high load on 8110SCd controllers. - */ - if (tp->mac_version == RTL_GIGA_MAC_VER_05) - tp->cp_cmd |= RxVlan; - rtl_init_mdio_ops(tp); rtl_init_pll_power_ops(tp); rtl_init_jumbo_ops(tp); @@ -7302,8 +7295,14 @@ rtl_init_one(struct pci_dev *pdev, const struct pci_device_id *ent) dev->vlan_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_TSO | NETIF_F_HIGHDMA; + tp->cp_cmd |= RxChkSum | RxVlan; + + /* + * Pretend we are using VLANs; This bypasses a nasty bug where + * Interrupts stop flowing on high load on 8110SCd controllers. + */ if (tp->mac_version == RTL_GIGA_MAC_VER_05) - /* 8110SCd requires hardware Rx VLAN - disallow toggling */ + /* Disallow toggling */ dev->hw_features &= ~NETIF_F_HW_VLAN_CTAG_RX; if (tp->txd_version == RTL_TD_0) diff --git a/drivers/net/ethernet/sfc/farch.c b/drivers/net/ethernet/sfc/farch.c index 0537381cd2f6..6859437b59fb 100644 --- a/drivers/net/ethernet/sfc/farch.c +++ b/drivers/net/ethernet/sfc/farch.c @@ -2933,6 +2933,9 @@ void efx_farch_filter_sync_rx_mode(struct efx_nic *efx) u32 crc; int bit; + if (!efx_dev_registered(efx)) + return; + netif_addr_lock_bh(net_dev); efx->unicast_filter = !(net_dev->flags & IFF_PROMISC); diff --git a/drivers/net/ethernet/sun/sunvnet.c b/drivers/net/ethernet/sun/sunvnet.c index 23c89ab5a6ad..f67539650c38 100644 --- a/drivers/net/ethernet/sun/sunvnet.c +++ b/drivers/net/ethernet/sun/sunvnet.c @@ -350,14 +350,17 @@ static int vnet_walk_rx_one(struct vnet_port *port, if (IS_ERR(desc)) return PTR_ERR(desc); + if (desc->hdr.state != VIO_DESC_READY) + return 1; + + rmb(); + viodbg(DATA, "vio_walk_rx_one desc[%02x:%02x:%08x:%08x:%llx:%llx]\n", desc->hdr.state, desc->hdr.ack, desc->size, desc->ncookies, desc->cookies[0].cookie_addr, desc->cookies[0].cookie_size); - if (desc->hdr.state != VIO_DESC_READY) - return 1; err = vnet_rx_one(port, desc->size, desc->cookies, desc->ncookies); if (err == -ECONNRESET) return err; diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c index 999fb72688d2..e2a00287f8eb 100644 --- a/drivers/net/ethernet/ti/cpsw.c +++ b/drivers/net/ethernet/ti/cpsw.c @@ -699,6 +699,28 @@ static void cpsw_rx_handler(void *token, int len, int status) cpsw_dual_emac_src_port_detect(status, priv, ndev, skb); if (unlikely(status < 0) || unlikely(!netif_running(ndev))) { + bool ndev_status = false; + struct cpsw_slave *slave = priv->slaves; + int n; + + if (priv->data.dual_emac) { + /* In dual emac mode check for all interfaces */ + for (n = priv->data.slaves; n; n--, slave++) + if (netif_running(slave->ndev)) + ndev_status = true; + } + + if (ndev_status && (status >= 0)) { + /* The packet received is for the interface which + * is already down and the other interface is up + * and running, intead of freeing which results + * in reducing of the number of rx descriptor in + * DMA engine, requeue skb back to cpdma. + */ + new_skb = skb; + goto requeue; + } + /* the interface is going down, skbs are purged */ dev_kfree_skb_any(skb); return; @@ -717,6 +739,7 @@ static void cpsw_rx_handler(void *token, int len, int status) new_skb = skb; } +requeue: ret = cpdma_chan_submit(priv->rxch, new_skb, new_skb->data, skb_tailroom(new_skb), 0); if (WARN_ON(ret < 0)) @@ -2311,10 +2334,19 @@ static int cpsw_suspend(struct device *dev) struct net_device *ndev = platform_get_drvdata(pdev); struct cpsw_priv *priv = netdev_priv(ndev); - if (netif_running(ndev)) - cpsw_ndo_stop(ndev); + if (priv->data.dual_emac) { + int i; - for_each_slave(priv, soft_reset_slave); + for (i = 0; i < priv->data.slaves; i++) { + if (netif_running(priv->slaves[i].ndev)) + cpsw_ndo_stop(priv->slaves[i].ndev); + soft_reset_slave(priv->slaves + i); + } + } else { + if (netif_running(ndev)) + cpsw_ndo_stop(ndev); + for_each_slave(priv, soft_reset_slave); + } pm_runtime_put_sync(&pdev->dev); @@ -2328,14 +2360,24 @@ static int cpsw_resume(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct net_device *ndev = platform_get_drvdata(pdev); + struct cpsw_priv *priv = netdev_priv(ndev); pm_runtime_get_sync(&pdev->dev); /* Select default pin state */ pinctrl_pm_select_default_state(&pdev->dev); - if (netif_running(ndev)) - cpsw_ndo_open(ndev); + if (priv->data.dual_emac) { + int i; + + for (i = 0; i < priv->data.slaves; i++) { + if (netif_running(priv->slaves[i].ndev)) + cpsw_ndo_open(priv->slaves[i].ndev); + } + } else { + if (netif_running(ndev)) + cpsw_ndo_open(ndev); + } return 0; } diff --git a/drivers/net/macvlan.c b/drivers/net/macvlan.c index a96955597755..726edabff26b 100644 --- a/drivers/net/macvlan.c +++ b/drivers/net/macvlan.c @@ -36,6 +36,7 @@ #include <linux/netpoll.h> #define MACVLAN_HASH_SIZE (1 << BITS_PER_BYTE) +#define MACVLAN_BC_QUEUE_LEN 1000 struct macvlan_port { struct net_device *dev; @@ -248,7 +249,7 @@ static void macvlan_broadcast_enqueue(struct macvlan_port *port, goto err; spin_lock(&port->bc_queue.lock); - if (skb_queue_len(&port->bc_queue) < skb->dev->tx_queue_len) { + if (skb_queue_len(&port->bc_queue) < MACVLAN_BC_QUEUE_LEN) { __skb_queue_tail(&port->bc_queue, nskb); err = 0; } @@ -806,6 +807,7 @@ static netdev_features_t macvlan_fix_features(struct net_device *dev, features, mask); features |= ALWAYS_ON_FEATURES; + features &= ~NETIF_F_NETNS_LOCAL; return features; } diff --git a/drivers/net/phy/micrel.c b/drivers/net/phy/micrel.c index fd0ea7c50ee6..011dbda2b2f1 100644 --- a/drivers/net/phy/micrel.c +++ b/drivers/net/phy/micrel.c @@ -592,8 +592,7 @@ static struct phy_driver ksphy_driver[] = { .phy_id = PHY_ID_KSZ9031, .phy_id_mask = 0x00fffff0, .name = "Micrel KSZ9031 Gigabit PHY", - .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause - | SUPPORTED_Asym_Pause), + .features = (PHY_GBIT_FEATURES | SUPPORTED_Pause), .flags = PHY_HAS_MAGICANEG | PHY_HAS_INTERRUPT, .config_init = ksz9031_config_init, .config_aneg = genphy_config_aneg, diff --git a/drivers/net/usb/r8152.c b/drivers/net/usb/r8152.c index 87f710476217..74760e8143e3 100644 --- a/drivers/net/usb/r8152.c +++ b/drivers/net/usb/r8152.c @@ -2019,7 +2019,7 @@ static int rtl8153_enable(struct r8152 *tp) return rtl_enable(tp); } -static void rtl8152_disable(struct r8152 *tp) +static void rtl_disable(struct r8152 *tp) { u32 ocp_data; int i; @@ -2232,6 +2232,13 @@ static inline void r8152b_enable_aldps(struct r8152 *tp) LINKENA | DIS_SDSAVE); } +static void rtl8152_disable(struct r8152 *tp) +{ + r8152b_disable_aldps(tp); + rtl_disable(tp); + r8152b_enable_aldps(tp); +} + static void r8152b_hw_phy_cfg(struct r8152 *tp) { u16 data; @@ -2242,11 +2249,8 @@ static void r8152b_hw_phy_cfg(struct r8152 *tp) r8152_mdio_write(tp, MII_BMCR, data); } - r8152b_disable_aldps(tp); - rtl_clear_bp(tp); - r8152b_enable_aldps(tp); set_bit(PHY_RESET, &tp->flags); } @@ -2255,9 +2259,6 @@ static void r8152b_exit_oob(struct r8152 *tp) u32 ocp_data; int i; - if (test_bit(RTL8152_UNPLUG, &tp->flags)) - return; - ocp_data = ocp_read_dword(tp, MCU_TYPE_PLA, PLA_RCR); ocp_data &= ~RCR_ACPT_ALL; ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RCR, ocp_data); @@ -2347,7 +2348,7 @@ static void r8152b_enter_oob(struct r8152 *tp) ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL1, RXFIFO_THR2_OOB); ocp_write_dword(tp, MCU_TYPE_PLA, PLA_RXFIFO_CTRL2, RXFIFO_THR3_OOB); - rtl8152_disable(tp); + rtl_disable(tp); for (i = 0; i < 1000; i++) { ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); @@ -2485,9 +2486,6 @@ static void r8153_first_init(struct r8152 *tp) u32 ocp_data; int i; - if (test_bit(RTL8152_UNPLUG, &tp->flags)) - return; - rxdy_gated_en(tp, true); r8153_teredo_off(tp); @@ -2560,7 +2558,7 @@ static void r8153_enter_oob(struct r8152 *tp) ocp_data &= ~NOW_IS_OOB; ocp_write_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL, ocp_data); - rtl8152_disable(tp); + rtl_disable(tp); for (i = 0; i < 1000; i++) { ocp_data = ocp_read_byte(tp, MCU_TYPE_PLA, PLA_OOB_CTRL); @@ -2624,6 +2622,13 @@ static void r8153_enable_aldps(struct r8152 *tp) ocp_reg_write(tp, OCP_POWER_CFG, data); } +static void rtl8153_disable(struct r8152 *tp) +{ + r8153_disable_aldps(tp); + rtl_disable(tp); + r8153_enable_aldps(tp); +} + static int rtl8152_set_speed(struct r8152 *tp, u8 autoneg, u16 speed, u8 duplex) { u16 bmcr, anar, gbcr; @@ -2714,6 +2719,16 @@ out: return ret; } +static void rtl8152_up(struct r8152 *tp) +{ + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + + r8152b_disable_aldps(tp); + r8152b_exit_oob(tp); + r8152b_enable_aldps(tp); +} + static void rtl8152_down(struct r8152 *tp) { if (test_bit(RTL8152_UNPLUG, &tp->flags)) { @@ -2727,6 +2742,16 @@ static void rtl8152_down(struct r8152 *tp) r8152b_enable_aldps(tp); } +static void rtl8153_up(struct r8152 *tp) +{ + if (test_bit(RTL8152_UNPLUG, &tp->flags)) + return; + + r8153_disable_aldps(tp); + r8153_first_init(tp); + r8153_enable_aldps(tp); +} + static void rtl8153_down(struct r8152 *tp) { if (test_bit(RTL8152_UNPLUG, &tp->flags)) { @@ -2946,6 +2971,8 @@ static void r8152b_init(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; + r8152b_disable_aldps(tp); + if (tp->version == RTL_VER_01) { ocp_data = ocp_read_word(tp, MCU_TYPE_PLA, PLA_LED_FEATURE); ocp_data &= ~LED_MODE_MASK; @@ -2984,6 +3011,7 @@ static void r8153_init(struct r8152 *tp) if (test_bit(RTL8152_UNPLUG, &tp->flags)) return; + r8153_disable_aldps(tp); r8153_u1u2en(tp, false); for (i = 0; i < 500; i++) { @@ -3392,7 +3420,7 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) ops->init = r8152b_init; ops->enable = rtl8152_enable; ops->disable = rtl8152_disable; - ops->up = r8152b_exit_oob; + ops->up = rtl8152_up; ops->down = rtl8152_down; ops->unload = rtl8152_unload; ret = 0; @@ -3400,8 +3428,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) case PRODUCT_ID_RTL8153: ops->init = r8153_init; ops->enable = rtl8153_enable; - ops->disable = rtl8152_disable; - ops->up = r8153_first_init; + ops->disable = rtl8153_disable; + ops->up = rtl8153_up; ops->down = rtl8153_down; ops->unload = rtl8153_unload; ret = 0; @@ -3416,8 +3444,8 @@ static int rtl_ops_init(struct r8152 *tp, const struct usb_device_id *id) case PRODUCT_ID_SAMSUNG: ops->init = r8153_init; ops->enable = rtl8153_enable; - ops->disable = rtl8152_disable; - ops->up = r8153_first_init; + ops->disable = rtl8153_disable; + ops->up = rtl8153_up; ops->down = rtl8153_down; ops->unload = rtl8153_unload; ret = 0; diff --git a/drivers/net/wireless/ath/ath9k/common-beacon.c b/drivers/net/wireless/ath/ath9k/common-beacon.c index 733be5178481..6ad44470d0f2 100644 --- a/drivers/net/wireless/ath/ath9k/common-beacon.c +++ b/drivers/net/wireless/ath/ath9k/common-beacon.c @@ -57,7 +57,7 @@ int ath9k_cmn_beacon_config_sta(struct ath_hw *ah, struct ath9k_beacon_state *bs) { struct ath_common *common = ath9k_hw_common(ah); - int dtim_intval, sleepduration; + int dtim_intval; u64 tsf; /* No need to configure beacon if we are not associated */ @@ -75,7 +75,6 @@ int ath9k_cmn_beacon_config_sta(struct ath_hw *ah, * last beacon we received (which may be none). */ dtim_intval = conf->intval * conf->dtim_period; - sleepduration = ah->hw->conf.listen_interval * conf->intval; /* * Pull nexttbtt forward to reflect the current @@ -113,7 +112,7 @@ int ath9k_cmn_beacon_config_sta(struct ath_hw *ah, */ bs->bs_sleepduration = TU_TO_USEC(roundup(IEEE80211_MS_TO_TU(100), - sleepduration)); + conf->intval)); if (bs->bs_sleepduration > bs->bs_dtimperiod) bs->bs_sleepduration = bs->bs_dtimperiod; diff --git a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c index bb86eb2ffc95..f0484b1b617e 100644 --- a/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c +++ b/drivers/net/wireless/ath/ath9k/htc_drv_txrx.c @@ -978,7 +978,7 @@ static bool ath9k_rx_prepare(struct ath9k_htc_priv *priv, struct ath_hw *ah = common->ah; struct ath_htc_rx_status *rxstatus; struct ath_rx_status rx_stats; - bool decrypt_error; + bool decrypt_error = false; if (skb->len < HTC_RX_FRAME_HEADER_SIZE) { ath_err(common, "Corrupted RX frame, dropping (len: %d)\n", diff --git a/drivers/net/wireless/brcm80211/Kconfig b/drivers/net/wireless/brcm80211/Kconfig index b8e2561ea645..fe3dc126b149 100644 --- a/drivers/net/wireless/brcm80211/Kconfig +++ b/drivers/net/wireless/brcm80211/Kconfig @@ -27,10 +27,17 @@ config BRCMFMAC one of the bus interface support. If you choose to build a module, it'll be called brcmfmac.ko. +config BRCMFMAC_PROTO_BCDC + bool + +config BRCMFMAC_PROTO_MSGBUF + bool + config BRCMFMAC_SDIO bool "SDIO bus interface support for FullMAC driver" depends on (MMC = y || MMC = BRCMFMAC) depends on BRCMFMAC + select BRCMFMAC_PROTO_BCDC select FW_LOADER default y ---help--- @@ -42,6 +49,7 @@ config BRCMFMAC_USB bool "USB bus interface support for FullMAC driver" depends on (USB = y || USB = BRCMFMAC) depends on BRCMFMAC + select BRCMFMAC_PROTO_BCDC select FW_LOADER ---help--- This option enables the USB bus interface support for Broadcom @@ -52,6 +60,8 @@ config BRCMFMAC_PCIE bool "PCIE bus interface support for FullMAC driver" depends on BRCMFMAC depends on PCI + depends on HAS_DMA + select BRCMFMAC_PROTO_MSGBUF select FW_LOADER ---help--- This option enables the PCIE bus interface support for Broadcom diff --git a/drivers/net/wireless/brcm80211/brcmfmac/Makefile b/drivers/net/wireless/brcm80211/brcmfmac/Makefile index c35adf4bc70b..90a977fe9a64 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/Makefile +++ b/drivers/net/wireless/brcm80211/brcmfmac/Makefile @@ -30,16 +30,18 @@ brcmfmac-objs += \ fwsignal.o \ p2p.o \ proto.o \ - bcdc.o \ - commonring.o \ - flowring.o \ - msgbuf.o \ dhd_common.o \ dhd_linux.o \ firmware.o \ feature.o \ btcoex.o \ vendor.o +brcmfmac-$(CONFIG_BRCMFMAC_PROTO_BCDC) += \ + bcdc.o +brcmfmac-$(CONFIG_BRCMFMAC_PROTO_MSGBUF) += \ + commonring.o \ + flowring.o \ + msgbuf.o brcmfmac-$(CONFIG_BRCMFMAC_SDIO) += \ dhd_sdio.o \ bcmsdh.o diff --git a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h index 17e8c039ff32..6003179c0ceb 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/bcdc.h @@ -16,9 +16,12 @@ #ifndef BRCMFMAC_BCDC_H #define BRCMFMAC_BCDC_H - +#ifdef CONFIG_BRCMFMAC_PROTO_BCDC int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr); void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr); - +#else +static inline int brcmf_proto_bcdc_attach(struct brcmf_pub *drvr) { return 0; } +static inline void brcmf_proto_bcdc_detach(struct brcmf_pub *drvr) {} +#endif #endif /* BRCMFMAC_BCDC_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c index 4f1daabc551b..44fc85f68f7a 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.c @@ -185,7 +185,13 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, ifevent->action, ifevent->ifidx, ifevent->bssidx, ifevent->flags, ifevent->role); - if (ifevent->flags & BRCMF_E_IF_FLAG_NOIF) { + /* The P2P Device interface event must not be ignored + * contrary to what firmware tells us. The only way to + * distinguish the P2P Device is by looking at the ifidx + * and bssidx received. + */ + if (!(ifevent->ifidx == 0 && ifevent->bssidx == 1) && + (ifevent->flags & BRCMF_E_IF_FLAG_NOIF)) { brcmf_dbg(EVENT, "event can be ignored\n"); return; } @@ -210,12 +216,12 @@ static void brcmf_fweh_handle_if_event(struct brcmf_pub *drvr, return; } - if (ifevent->action == BRCMF_E_IF_CHANGE) + if (ifp && ifevent->action == BRCMF_E_IF_CHANGE) brcmf_fws_reset_interface(ifp); err = brcmf_fweh_call_event_handler(ifp, emsg->event_code, emsg, data); - if (ifevent->action == BRCMF_E_IF_DEL) { + if (ifp && ifevent->action == BRCMF_E_IF_DEL) { brcmf_fws_del_interface(ifp); brcmf_del_if(drvr, ifevent->bssidx); } diff --git a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h index dd20b1862d44..cbf033f59109 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/fweh.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/fweh.h @@ -172,6 +172,8 @@ enum brcmf_fweh_event_code { #define BRCMF_E_IF_ROLE_STA 0 #define BRCMF_E_IF_ROLE_AP 1 #define BRCMF_E_IF_ROLE_WDS 2 +#define BRCMF_E_IF_ROLE_P2P_GO 3 +#define BRCMF_E_IF_ROLE_P2P_CLIENT 4 /** * definitions for event packet validation. diff --git a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h index f901ae52bf2b..77a51b8c1e12 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h +++ b/drivers/net/wireless/brcm80211/brcmfmac/msgbuf.h @@ -15,6 +15,7 @@ #ifndef BRCMFMAC_MSGBUF_H #define BRCMFMAC_MSGBUF_H +#ifdef CONFIG_BRCMFMAC_PROTO_MSGBUF #define BRCMF_H2D_MSGRING_CONTROL_SUBMIT_MAX_ITEM 20 #define BRCMF_H2D_MSGRING_RXPOST_SUBMIT_MAX_ITEM 256 @@ -32,9 +33,15 @@ int brcmf_proto_msgbuf_rx_trigger(struct device *dev); +void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid); int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr); void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr); -void brcmf_msgbuf_delete_flowring(struct brcmf_pub *drvr, u8 flowid); - +#else +static inline int brcmf_proto_msgbuf_attach(struct brcmf_pub *drvr) +{ + return 0; +} +static inline void brcmf_proto_msgbuf_detach(struct brcmf_pub *drvr) {} +#endif #endif /* BRCMFMAC_MSGBUF_H */ diff --git a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c index 02fe706fc9ec..f3a9804988a6 100644 --- a/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c +++ b/drivers/net/wireless/brcm80211/brcmfmac/wl_cfg80211.c @@ -497,8 +497,11 @@ brcmf_configure_arp_offload(struct brcmf_if *ifp, bool enable) static void brcmf_cfg80211_update_proto_addr_mode(struct wireless_dev *wdev) { - struct net_device *ndev = wdev->netdev; - struct brcmf_if *ifp = netdev_priv(ndev); + struct brcmf_cfg80211_vif *vif; + struct brcmf_if *ifp; + + vif = container_of(wdev, struct brcmf_cfg80211_vif, wdev); + ifp = vif->ifp; if ((wdev->iftype == NL80211_IFTYPE_ADHOC) || (wdev->iftype == NL80211_IFTYPE_AP) || @@ -5143,6 +5146,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) ch.band = BRCMU_CHAN_BAND_2G; ch.bw = BRCMU_CHAN_BW_40; + ch.sb = BRCMU_CHAN_SB_NONE; ch.chnum = 0; cfg->d11inf.encchspec(&ch); @@ -5176,6 +5180,7 @@ static int brcmf_enable_bw40_2g(struct brcmf_cfg80211_info *cfg) brcmf_update_bw40_channel_flag(&band->channels[j], &ch); } + kfree(pbuf); } return err; } diff --git a/drivers/net/wireless/iwlwifi/dvm/power.c b/drivers/net/wireless/iwlwifi/dvm/power.c index 760c45c34ef3..1513dbc79c14 100644 --- a/drivers/net/wireless/iwlwifi/dvm/power.c +++ b/drivers/net/wireless/iwlwifi/dvm/power.c @@ -40,7 +40,7 @@ #include "commands.h" #include "power.h" -static bool force_cam; +static bool force_cam = true; module_param(force_cam, bool, 0644); MODULE_PARM_DESC(force_cam, "force continuously aware mode (no power saving at all)"); diff --git a/drivers/net/wireless/iwlwifi/iwl-7000.c b/drivers/net/wireless/iwlwifi/iwl-7000.c index d67a37a786aa..d53adc245497 100644 --- a/drivers/net/wireless/iwlwifi/iwl-7000.c +++ b/drivers/net/wireless/iwlwifi/iwl-7000.c @@ -83,6 +83,8 @@ #define IWL7260_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL3160_NVM_VERSION 0x709 #define IWL3160_TX_POWER_VERSION 0xffff /* meaningless */ +#define IWL3165_NVM_VERSION 0x709 +#define IWL3165_TX_POWER_VERSION 0xffff /* meaningless */ #define IWL7265_NVM_VERSION 0x0a1d #define IWL7265_TX_POWER_VERSION 0xffff /* meaningless */ @@ -92,6 +94,9 @@ #define IWL3160_FW_PRE "iwlwifi-3160-" #define IWL3160_MODULE_FIRMWARE(api) IWL3160_FW_PRE __stringify(api) ".ucode" +#define IWL3165_FW_PRE "iwlwifi-3165-" +#define IWL3165_MODULE_FIRMWARE(api) IWL3165_FW_PRE __stringify(api) ".ucode" + #define IWL7265_FW_PRE "iwlwifi-7265-" #define IWL7265_MODULE_FIRMWARE(api) IWL7265_FW_PRE __stringify(api) ".ucode" @@ -213,6 +218,16 @@ static const struct iwl_pwr_tx_backoff iwl7265_pwr_tx_backoffs[] = { {0}, }; +const struct iwl_cfg iwl3165_2ac_cfg = { + .name = "Intel(R) Dual Band Wireless AC 3165", + .fw_name_pre = IWL3165_FW_PRE, + IWL_DEVICE_7000, + .ht_params = &iwl7000_ht_params, + .nvm_ver = IWL3165_NVM_VERSION, + .nvm_calib_ver = IWL3165_TX_POWER_VERSION, + .pwr_tx_backoffs = iwl7265_pwr_tx_backoffs, +}; + const struct iwl_cfg iwl7265_2ac_cfg = { .name = "Intel(R) Dual Band Wireless AC 7265", .fw_name_pre = IWL7265_FW_PRE, @@ -245,4 +260,5 @@ const struct iwl_cfg iwl7265_n_cfg = { MODULE_FIRMWARE(IWL7260_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); MODULE_FIRMWARE(IWL3160_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); +MODULE_FIRMWARE(IWL3165_MODULE_FIRMWARE(IWL3160_UCODE_API_OK)); MODULE_FIRMWARE(IWL7265_MODULE_FIRMWARE(IWL7260_UCODE_API_OK)); diff --git a/drivers/net/wireless/iwlwifi/iwl-config.h b/drivers/net/wireless/iwlwifi/iwl-config.h index 8da596db9abe..3d7cc37420ae 100644 --- a/drivers/net/wireless/iwlwifi/iwl-config.h +++ b/drivers/net/wireless/iwlwifi/iwl-config.h @@ -120,6 +120,8 @@ enum iwl_led_mode { #define IWL_LONG_WD_TIMEOUT 10000 #define IWL_MAX_WD_TIMEOUT 120000 +#define IWL_DEFAULT_MAX_TX_POWER 22 + /* Antenna presence definitions */ #define ANT_NONE 0x0 #define ANT_A BIT(0) @@ -335,6 +337,7 @@ extern const struct iwl_cfg iwl7260_n_cfg; extern const struct iwl_cfg iwl3160_2ac_cfg; extern const struct iwl_cfg iwl3160_2n_cfg; extern const struct iwl_cfg iwl3160_n_cfg; +extern const struct iwl_cfg iwl3165_2ac_cfg; extern const struct iwl_cfg iwl7265_2ac_cfg; extern const struct iwl_cfg iwl7265_2n_cfg; extern const struct iwl_cfg iwl7265_n_cfg; diff --git a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c index 018af2957d3b..354255f08754 100644 --- a/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c +++ b/drivers/net/wireless/iwlwifi/iwl-nvm-parse.c @@ -146,8 +146,6 @@ static const u8 iwl_nvm_channels_family_8000[] = { #define LAST_2GHZ_HT_PLUS 9 #define LAST_5GHZ_HT 161 -#define DEFAULT_MAX_TX_POWER 16 - /* rate data (static) */ static struct ieee80211_rate iwl_cfg80211_rates[] = { { .bitrate = 1 * 10, .hw_value = 0, .hw_value_short = 0, }, @@ -295,7 +293,7 @@ static int iwl_init_channel_map(struct device *dev, const struct iwl_cfg *cfg, * Default value - highest tx power value. max_power * is not used in mvm, and is used for backwards compatibility */ - channel->max_power = DEFAULT_MAX_TX_POWER; + channel->max_power = IWL_DEFAULT_MAX_TX_POWER; is_5ghz = channel->band == IEEE80211_BAND_5GHZ; IWL_DEBUG_EEPROM(dev, "Ch. %d [%sGHz] %s%s%s%s%s%s%s(0x%02x %ddBm): Ad-Hoc %ssupported\n", diff --git a/drivers/net/wireless/iwlwifi/mvm/coex.c b/drivers/net/wireless/iwlwifi/mvm/coex.c index 2291bbcaaeab..ce71625f497f 100644 --- a/drivers/net/wireless/iwlwifi/mvm/coex.c +++ b/drivers/net/wireless/iwlwifi/mvm/coex.c @@ -585,8 +585,6 @@ int iwl_send_bt_init_conf(struct iwl_mvm *mvm) lockdep_assert_held(&mvm->mutex); if (unlikely(mvm->bt_force_ant_mode != BT_FORCE_ANT_DIS)) { - u32 mode; - switch (mvm->bt_force_ant_mode) { case BT_FORCE_ANT_BT: mode = BT_COEX_BT; @@ -756,7 +754,8 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, struct iwl_bt_iterator_data *data = _data; struct iwl_mvm *mvm = data->mvm; struct ieee80211_chanctx_conf *chanctx_conf; - enum ieee80211_smps_mode smps_mode; + /* default smps_mode is AUTOMATIC - only used for client modes */ + enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_AUTOMATIC; u32 bt_activity_grading; int ave_rssi; @@ -764,8 +763,6 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, switch (vif->type) { case NL80211_IFTYPE_STATION: - /* default smps_mode for BSS / P2P client is AUTOMATIC */ - smps_mode = IEEE80211_SMPS_AUTOMATIC; break; case NL80211_IFTYPE_AP: if (!mvmvif->ap_ibss_active) @@ -797,7 +794,7 @@ static void iwl_mvm_bt_notif_iterator(void *_data, u8 *mac, else if (bt_activity_grading >= BT_LOW_TRAFFIC) smps_mode = IEEE80211_SMPS_DYNAMIC; - /* relax SMPS contraints for next association */ + /* relax SMPS constraints for next association */ if (!vif->bss_conf.assoc) smps_mode = IEEE80211_SMPS_AUTOMATIC; diff --git a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c index 2e90ff795c13..87e517bffedc 100644 --- a/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c +++ b/drivers/net/wireless/iwlwifi/mvm/debugfs-vif.c @@ -74,8 +74,7 @@ static void iwl_dbgfs_update_pm(struct iwl_mvm *mvm, switch (param) { case MVM_DEBUGFS_PM_KEEP_ALIVE: { - struct ieee80211_hw *hw = mvm->hw; - int dtimper = hw->conf.ps_dtim_period ?: 1; + int dtimper = vif->bss_conf.dtim_period ?: 1; int dtimper_msec = dtimper * vif->bss_conf.beacon_int; IWL_DEBUG_POWER(mvm, "debugfs: set keep_alive= %d sec\n", val); diff --git a/drivers/net/wireless/iwlwifi/mvm/fw-api.h b/drivers/net/wireless/iwlwifi/mvm/fw-api.h index 95f5b3274efb..9a922f3bd16b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/fw-api.h +++ b/drivers/net/wireless/iwlwifi/mvm/fw-api.h @@ -1563,14 +1563,14 @@ enum iwl_sf_scenario { /** * Smart Fifo configuration command. - * @state: smart fifo state, types listed in iwl_sf_sate. + * @state: smart fifo state, types listed in enum %iwl_sf_sate. * @watermark: Minimum allowed availabe free space in RXF for transient state. * @long_delay_timeouts: aging and idle timer values for each scenario * in long delay state. * @full_on_timeouts: timer values for each scenario in full on state. */ struct iwl_sf_cfg_cmd { - enum iwl_sf_state state; + __le32 state; __le32 watermark[SF_TRANSIENT_STATES_NUMBER]; __le32 long_delay_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; __le32 full_on_timeouts[SF_NUM_SCENARIO][SF_NUM_TIMEOUT_TYPES]; diff --git a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c index 0e523e28cabf..8242e689ddb1 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac-ctxt.c @@ -721,11 +721,6 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, !force_assoc_off) { u32 dtim_offs; - /* Allow beacons to pass through as long as we are not - * associated, or we do not have dtim period information. - */ - cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); - /* * The DTIM count counts down, so when it is N that means N * more beacon intervals happen until the DTIM TBTT. Therefore @@ -759,6 +754,11 @@ static int iwl_mvm_mac_ctxt_cmd_sta(struct iwl_mvm *mvm, ctxt_sta->is_assoc = cpu_to_le32(1); } else { ctxt_sta->is_assoc = cpu_to_le32(0); + + /* Allow beacons to pass through as long as we are not + * associated, or we do not have dtim period information. + */ + cmd.filter_flags |= cpu_to_le32(MAC_FILTER_IN_BEACON); } ctxt_sta->bi = cpu_to_le32(vif->bss_conf.beacon_int); diff --git a/drivers/net/wireless/iwlwifi/mvm/mac80211.c b/drivers/net/wireless/iwlwifi/mvm/mac80211.c index 7c8796584c25..cdc272d776e7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/mac80211.c +++ b/drivers/net/wireless/iwlwifi/mvm/mac80211.c @@ -396,12 +396,14 @@ int iwl_mvm_mac_setup_register(struct iwl_mvm *mvm) else hw->wiphy->flags &= ~WIPHY_FLAG_PS_ON_BY_DEFAULT; - /* TODO: enable that only for firmwares that don't crash */ - /* hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; */ - hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; - hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; - /* we create the 802.11 header and zero length SSID IE. */ - hw->wiphy->max_sched_scan_ie_len = SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; + if (IWL_UCODE_API(mvm->fw->ucode_ver) >= 10) { + hw->wiphy->flags |= WIPHY_FLAG_SUPPORTS_SCHED_SCAN; + hw->wiphy->max_sched_scan_ssids = PROBE_OPTION_MAX; + hw->wiphy->max_match_sets = IWL_SCAN_MAX_PROFILES; + /* we create the 802.11 header and zero length SSID IE. */ + hw->wiphy->max_sched_scan_ie_len = + SCAN_OFFLOAD_PROBE_REQ_SIZE - 24 - 2; + } hw->wiphy->features |= NL80211_FEATURE_P2P_GO_CTWIN | NL80211_FEATURE_LOW_PRIORITY_SCAN | @@ -1524,11 +1526,6 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, */ iwl_mvm_remove_time_event(mvm, mvmvif, &mvmvif->time_event_data); - } else if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | - BSS_CHANGED_QOS)) { - ret = iwl_mvm_power_update_mac(mvm); - if (ret) - IWL_ERR(mvm, "failed to update power mode\n"); } if (changes & BSS_CHANGED_BEACON_INFO) { @@ -1536,6 +1533,12 @@ static void iwl_mvm_bss_info_changed_station(struct iwl_mvm *mvm, WARN_ON(iwl_mvm_enable_beacon_filter(mvm, vif, 0)); } + if (changes & (BSS_CHANGED_PS | BSS_CHANGED_P2P_PS | BSS_CHANGED_QOS)) { + ret = iwl_mvm_power_update_mac(mvm); + if (ret) + IWL_ERR(mvm, "failed to update power mode\n"); + } + if (changes & BSS_CHANGED_TXPOWER) { IWL_DEBUG_CALIB(mvm, "Changing TX Power to %d\n", bss_conf->txpower); diff --git a/drivers/net/wireless/iwlwifi/mvm/power.c b/drivers/net/wireless/iwlwifi/mvm/power.c index 2b2d10800a55..d9769a23c68b 100644 --- a/drivers/net/wireless/iwlwifi/mvm/power.c +++ b/drivers/net/wireless/iwlwifi/mvm/power.c @@ -281,7 +281,6 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, struct ieee80211_vif *vif, struct iwl_mac_power_cmd *cmd) { - struct ieee80211_hw *hw = mvm->hw; struct ieee80211_chanctx_conf *chanctx_conf; struct ieee80211_channel *chan; int dtimper, dtimper_msec; @@ -292,7 +291,7 @@ static void iwl_mvm_power_build_cmd(struct iwl_mvm *mvm, cmd->id_and_color = cpu_to_le32(FW_CMD_ID_AND_COLOR(mvmvif->id, mvmvif->color)); - dtimper = hw->conf.ps_dtim_period ?: 1; + dtimper = vif->bss_conf.dtim_period; /* * Regardless of power management state the driver must set @@ -885,7 +884,7 @@ int iwl_mvm_update_d0i3_power_mode(struct iwl_mvm *mvm, iwl_mvm_power_build_cmd(mvm, vif, &cmd); if (enable) { /* configure skip over dtim up to 300 msec */ - int dtimper = mvm->hw->conf.ps_dtim_period ?: 1; + int dtimper = vif->bss_conf.dtim_period ?: 1; int dtimper_msec = dtimper * vif->bss_conf.beacon_int; if (WARN_ON(!dtimper_msec)) diff --git a/drivers/net/wireless/iwlwifi/mvm/rx.c b/drivers/net/wireless/iwlwifi/mvm/rx.c index 4b98987fc413..bf5cd8c8b0f7 100644 --- a/drivers/net/wireless/iwlwifi/mvm/rx.c +++ b/drivers/net/wireless/iwlwifi/mvm/rx.c @@ -149,13 +149,13 @@ static void iwl_mvm_get_signal_strength(struct iwl_mvm *mvm, le32_to_cpu(phy_info->non_cfg_phy[IWL_RX_INFO_ENERGY_ANT_ABC_IDX]); energy_a = (val & IWL_RX_INFO_ENERGY_ANT_A_MSK) >> IWL_RX_INFO_ENERGY_ANT_A_POS; - energy_a = energy_a ? -energy_a : -256; + energy_a = energy_a ? -energy_a : S8_MIN; energy_b = (val & IWL_RX_INFO_ENERGY_ANT_B_MSK) >> IWL_RX_INFO_ENERGY_ANT_B_POS; - energy_b = energy_b ? -energy_b : -256; + energy_b = energy_b ? -energy_b : S8_MIN; energy_c = (val & IWL_RX_INFO_ENERGY_ANT_C_MSK) >> IWL_RX_INFO_ENERGY_ANT_C_POS; - energy_c = energy_c ? -energy_c : -256; + energy_c = energy_c ? -energy_c : S8_MIN; max_energy = max(energy_a, energy_b); max_energy = max(max_energy, energy_c); diff --git a/drivers/net/wireless/iwlwifi/mvm/sf.c b/drivers/net/wireless/iwlwifi/mvm/sf.c index 7edfd15efc9d..e843b67f2201 100644 --- a/drivers/net/wireless/iwlwifi/mvm/sf.c +++ b/drivers/net/wireless/iwlwifi/mvm/sf.c @@ -172,7 +172,7 @@ static int iwl_mvm_sf_config(struct iwl_mvm *mvm, u8 sta_id, enum iwl_sf_state new_state) { struct iwl_sf_cfg_cmd sf_cmd = { - .state = new_state, + .state = cpu_to_le32(new_state), }; struct ieee80211_sta *sta; int ret = 0; diff --git a/drivers/net/wireless/iwlwifi/mvm/tx.c b/drivers/net/wireless/iwlwifi/mvm/tx.c index dbc870713882..9ee410bf6da2 100644 --- a/drivers/net/wireless/iwlwifi/mvm/tx.c +++ b/drivers/net/wireless/iwlwifi/mvm/tx.c @@ -168,10 +168,14 @@ static void iwl_mvm_set_tx_cmd_rate(struct iwl_mvm *mvm, /* * for data packets, rate info comes from the table inside the fw. This - * table is controlled by LINK_QUALITY commands + * table is controlled by LINK_QUALITY commands. Exclude ctrl port + * frames like EAPOLs which should be treated as mgmt frames. This + * avoids them being sent initially in high rates which increases the + * chances for completion of the 4-Way handshake. */ - if (ieee80211_is_data(fc) && sta) { + if (ieee80211_is_data(fc) && sta && + !(info->control.flags & IEEE80211_TX_CTRL_PORT_CTRL_PROTO)) { tx_cmd->initial_rate_index = 0; tx_cmd->tx_flags |= cpu_to_le32(TX_CMD_FLG_STA_RATE); return; diff --git a/drivers/net/wireless/iwlwifi/pcie/drv.c b/drivers/net/wireless/iwlwifi/pcie/drv.c index f0e722ced080..073a68b97a72 100644 --- a/drivers/net/wireless/iwlwifi/pcie/drv.c +++ b/drivers/net/wireless/iwlwifi/pcie/drv.c @@ -352,11 +352,17 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x08B3, 0x8060, iwl3160_2n_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8062, iwl3160_n_cfg)}, {IWL_PCI_DEVICE(0x08B4, 0x8270, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x8370, iwl3160_2ac_cfg)}, + {IWL_PCI_DEVICE(0x08B4, 0x8272, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8470, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x8570, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x1070, iwl3160_2ac_cfg)}, {IWL_PCI_DEVICE(0x08B3, 0x1170, iwl3160_2ac_cfg)}, +/* 3165 Series */ + {IWL_PCI_DEVICE(0x3165, 0x4010, iwl3165_2ac_cfg)}, + {IWL_PCI_DEVICE(0x3165, 0x4210, iwl3165_2ac_cfg)}, + /* 7265 Series */ {IWL_PCI_DEVICE(0x095A, 0x5010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x5110, iwl7265_2ac_cfg)}, @@ -378,6 +384,7 @@ static const struct pci_device_id iwl_hw_card_ids[] = { {IWL_PCI_DEVICE(0x095B, 0x5202, iwl7265_n_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9010, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9012, iwl7265_2ac_cfg)}, + {IWL_PCI_DEVICE(0x095A, 0x900A, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9110, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9112, iwl7265_2ac_cfg)}, {IWL_PCI_DEVICE(0x095A, 0x9210, iwl7265_2ac_cfg)}, diff --git a/drivers/parisc/pdc_stable.c b/drivers/parisc/pdc_stable.c index 0f54ab6260df..3651c3871d5b 100644 --- a/drivers/parisc/pdc_stable.c +++ b/drivers/parisc/pdc_stable.c @@ -278,7 +278,7 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun { struct hardware_path hwpath; unsigned short i; - char in[count+1], *temp; + char in[64], *temp; struct device *dev; int ret; @@ -286,8 +286,9 @@ pdcspath_hwpath_write(struct pdcspath_entry *entry, const char *buf, size_t coun return -EINVAL; /* We'll use a local copy of buf */ - memset(in, 0, count+1); + count = min_t(size_t, count, sizeof(in)-1); strncpy(in, buf, count); + in[count] = '\0'; /* Let's clean up the target. 0xff is a blank pattern */ memset(&hwpath, 0xff, sizeof(hwpath)); @@ -393,14 +394,15 @@ pdcspath_layer_write(struct pdcspath_entry *entry, const char *buf, size_t count { unsigned int layers[6]; /* device-specific info (ctlr#, unit#, ...) */ unsigned short i; - char in[count+1], *temp; + char in[64], *temp; if (!entry || !buf || !count) return -EINVAL; /* We'll use a local copy of buf */ - memset(in, 0, count+1); + count = min_t(size_t, count, sizeof(in)-1); strncpy(in, buf, count); + in[count] = '\0'; /* Let's clean up the target. 0 is a blank pattern */ memset(&layers, 0, sizeof(layers)); @@ -755,7 +757,7 @@ static ssize_t pdcs_auto_write(struct kobject *kobj, { struct pdcspath_entry *pathentry; unsigned char flags; - char in[count+1], *temp; + char in[8], *temp; char c; if (!capable(CAP_SYS_ADMIN)) @@ -765,8 +767,9 @@ static ssize_t pdcs_auto_write(struct kobject *kobj, return -EINVAL; /* We'll use a local copy of buf */ - memset(in, 0, count+1); + count = min_t(size_t, count, sizeof(in)-1); strncpy(in, buf, count); + in[count] = '\0'; /* Current flags are stored in primary boot path entry */ pathentry = &pdcspath_entry_primary; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index f833aa271a2e..2a436e607f99 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -48,6 +48,13 @@ config PHY_MIPHY365X Enable this to support the miphy transceiver (for SATA/PCIE) that is part of STMicroelectronics STiH41x SoC series. +config PHY_RCAR_GEN2 + tristate "Renesas R-Car generation 2 USB PHY driver" + depends on ARCH_SHMOBILE + depends on GENERIC_PHY + help + Support for USB PHY found on Renesas R-Car generation 2 SoCs. + config OMAP_CONTROL_PHY tristate "OMAP CONTROL PHY Driver" depends on ARCH_OMAP2PLUS || COMPILE_TEST @@ -232,4 +239,21 @@ config PHY_XGENE help This option enables support for APM X-Gene SoC multi-purpose PHY. +config PHY_STIH407_USB + tristate "STMicroelectronics USB2 picoPHY driver for STiH407 family" + depends on RESET_CONTROLLER + depends on ARCH_STI || COMPILE_TEST + select GENERIC_PHY + help + Enable this support to enable the picoPHY device used by USB2 + and USB3 controllers on STMicroelectronics STiH407 SoC families. + +config PHY_STIH41X_USB + tristate "STMicroelectronics USB2 PHY driver for STiH41x series" + depends on ARCH_STI + select GENERIC_PHY + help + Enable this to support the USB transceiver that is part of + STMicroelectronics STiH41x SoC series. + endmenu diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 95c69ed5ed45..c4590fce082f 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -9,6 +9,7 @@ obj-$(CONFIG_PHY_EXYNOS_DP_VIDEO) += phy-exynos-dp-video.o obj-$(CONFIG_PHY_EXYNOS_MIPI_VIDEO) += phy-exynos-mipi-video.o obj-$(CONFIG_PHY_MVEBU_SATA) += phy-mvebu-sata.o obj-$(CONFIG_PHY_MIPHY365X) += phy-miphy365x.o +obj-$(CONFIG_PHY_RCAR_GEN2) += phy-rcar-gen2.o obj-$(CONFIG_OMAP_CONTROL_PHY) += phy-omap-control.o obj-$(CONFIG_OMAP_USB2) += phy-omap-usb2.o obj-$(CONFIG_TI_PIPE3) += phy-ti-pipe3.o @@ -28,3 +29,5 @@ obj-$(CONFIG_PHY_QCOM_IPQ806X_SATA) += phy-qcom-ipq806x-sata.o obj-$(CONFIG_PHY_ST_SPEAR1310_MIPHY) += phy-spear1310-miphy.o obj-$(CONFIG_PHY_ST_SPEAR1340_MIPHY) += phy-spear1340-miphy.o obj-$(CONFIG_PHY_XGENE) += phy-xgene.o +obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o +obj-$(CONFIG_PHY_STIH41X_USB) += phy-stih41x-usb.o diff --git a/drivers/phy/phy-bcm-kona-usb2.c b/drivers/phy/phy-bcm-kona-usb2.c index 894fe74c1e44..c1e0ca335c0e 100644 --- a/drivers/phy/phy-bcm-kona-usb2.c +++ b/drivers/phy/phy-bcm-kona-usb2.c @@ -143,7 +143,6 @@ static struct platform_driver bcm_kona_usb2_driver = { .probe = bcm_kona_usb2_probe, .driver = { .name = "bcm-kona-usb2", - .owner = THIS_MODULE, .of_match_table = bcm_kona_usb2_dt_ids, }, }; diff --git a/drivers/phy/phy-berlin-sata.c b/drivers/phy/phy-berlin-sata.c index 5c3a0424aeb4..69ced52d72aa 100644 --- a/drivers/phy/phy-berlin-sata.c +++ b/drivers/phy/phy-berlin-sata.c @@ -273,7 +273,6 @@ static struct platform_driver phy_berlin_sata_driver = { .probe = phy_berlin_sata_probe, .driver = { .name = "phy-berlin-sata", - .owner = THIS_MODULE, .of_match_table = phy_berlin_sata_of_match, }, }; diff --git a/drivers/phy/phy-exynos-dp-video.c b/drivers/phy/phy-exynos-dp-video.c index 8b3026e2af7f..84f49e5a3f24 100644 --- a/drivers/phy/phy-exynos-dp-video.c +++ b/drivers/phy/phy-exynos-dp-video.c @@ -13,44 +13,55 @@ #include <linux/io.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/mfd/syscon.h> +#include <linux/mfd/syscon/exynos5-pmu.h> #include <linux/of.h> #include <linux/of_address.h> #include <linux/phy/phy.h> #include <linux/platform_device.h> +#include <linux/regmap.h> -/* DPTX_PHY_CONTROL register */ -#define EXYNOS_DPTX_PHY_ENABLE (1 << 0) +struct exynos_dp_video_phy_drvdata { + u32 phy_ctrl_offset; +}; struct exynos_dp_video_phy { - void __iomem *regs; + struct regmap *regs; + const struct exynos_dp_video_phy_drvdata *drvdata; }; -static int __set_phy_state(struct exynos_dp_video_phy *state, unsigned int on) +static void exynos_dp_video_phy_pwr_isol(struct exynos_dp_video_phy *state, + unsigned int on) { - u32 reg; + unsigned int val; + + if (IS_ERR(state->regs)) + return; - reg = readl(state->regs); - if (on) - reg |= EXYNOS_DPTX_PHY_ENABLE; - else - reg &= ~EXYNOS_DPTX_PHY_ENABLE; - writel(reg, state->regs); + val = on ? 0 : EXYNOS5_PHY_ENABLE; - return 0; + regmap_update_bits(state->regs, state->drvdata->phy_ctrl_offset, + EXYNOS5_PHY_ENABLE, val); } static int exynos_dp_video_phy_power_on(struct phy *phy) { struct exynos_dp_video_phy *state = phy_get_drvdata(phy); - return __set_phy_state(state, 1); + /* Disable power isolation on DP-PHY */ + exynos_dp_video_phy_pwr_isol(state, 0); + + return 0; } static int exynos_dp_video_phy_power_off(struct phy *phy) { struct exynos_dp_video_phy *state = phy_get_drvdata(phy); - return __set_phy_state(state, 0); + /* Enable power isolation on DP-PHY */ + exynos_dp_video_phy_pwr_isol(state, 1); + + return 0; } static struct phy_ops exynos_dp_video_phy_ops = { @@ -59,11 +70,31 @@ static struct phy_ops exynos_dp_video_phy_ops = { .owner = THIS_MODULE, }; +static const struct exynos_dp_video_phy_drvdata exynos5250_dp_video_phy = { + .phy_ctrl_offset = EXYNOS5_DPTX_PHY_CONTROL, +}; + +static const struct exynos_dp_video_phy_drvdata exynos5420_dp_video_phy = { + .phy_ctrl_offset = EXYNOS5420_DPTX_PHY_CONTROL, +}; + +static const struct of_device_id exynos_dp_video_phy_of_match[] = { + { + .compatible = "samsung,exynos5250-dp-video-phy", + .data = &exynos5250_dp_video_phy, + }, { + .compatible = "samsung,exynos5420-dp-video-phy", + .data = &exynos5420_dp_video_phy, + }, + { }, +}; +MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match); + static int exynos_dp_video_phy_probe(struct platform_device *pdev) { struct exynos_dp_video_phy *state; struct device *dev = &pdev->dev; - struct resource *res; + const struct of_device_id *match; struct phy_provider *phy_provider; struct phy *phy; @@ -71,11 +102,15 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) if (!state) return -ENOMEM; - res = platform_get_resource(pdev, IORESOURCE_MEM, 0); - - state->regs = devm_ioremap_resource(dev, res); - if (IS_ERR(state->regs)) + state->regs = syscon_regmap_lookup_by_phandle(dev->of_node, + "samsung,pmu-syscon"); + if (IS_ERR(state->regs)) { + dev_err(dev, "Failed to lookup PMU regmap\n"); return PTR_ERR(state->regs); + } + + match = of_match_node(exynos_dp_video_phy_of_match, dev->of_node); + state->drvdata = match->data; phy = devm_phy_create(dev, NULL, &exynos_dp_video_phy_ops, NULL); if (IS_ERR(phy)) { @@ -89,17 +124,10 @@ static int exynos_dp_video_phy_probe(struct platform_device *pdev) return PTR_ERR_OR_ZERO(phy_provider); } -static const struct of_device_id exynos_dp_video_phy_of_match[] = { - { .compatible = "samsung,exynos5250-dp-video-phy" }, - { }, -}; -MODULE_DEVICE_TABLE(of, exynos_dp_video_phy_of_match); - static struct platform_driver exynos_dp_video_phy_driver = { .probe = exynos_dp_video_phy_probe, .driver = { .name = "exynos-dp-video-phy", - .owner = THIS_MODULE, .of_match_table = exynos_dp_video_phy_of_match, } }; diff --git a/drivers/phy/phy-exynos-mipi-video.c b/drivers/phy/phy-exynos-mipi-video.c index b55a92e12496..6a9bef138617 100644 --- a/drivers/phy/phy-exynos-mipi-video.c +++ b/drivers/phy/phy-exynos-mipi-video.c @@ -165,7 +165,6 @@ static struct platform_driver exynos_mipi_video_phy_driver = { .driver = { .of_match_table = exynos_mipi_video_phy_of_match, .name = "exynos-mipi-video-phy", - .owner = THIS_MODULE, } }; module_platform_driver(exynos_mipi_video_phy_driver); diff --git a/drivers/phy/phy-exynos5-usbdrd.c b/drivers/phy/phy-exynos5-usbdrd.c index 392101c8d6b0..f756aca871db 100644 --- a/drivers/phy/phy-exynos5-usbdrd.c +++ b/drivers/phy/phy-exynos5-usbdrd.c @@ -667,7 +667,6 @@ static struct platform_driver exynos5_usb3drd_phy = { .driver = { .of_match_table = exynos5_usbdrd_phy_of_match, .name = "exynos5_usb3drd_phy", - .owner = THIS_MODULE, } }; diff --git a/drivers/phy/phy-exynos5250-sata.c b/drivers/phy/phy-exynos5250-sata.c index 19a679aca4ac..54cf4ae60d29 100644 --- a/drivers/phy/phy-exynos5250-sata.c +++ b/drivers/phy/phy-exynos5250-sata.c @@ -240,7 +240,6 @@ static struct platform_driver exynos_sata_phy_driver = { .driver = { .of_match_table = exynos_sata_phy_of_match, .name = "samsung,sata-phy", - .owner = THIS_MODULE, } }; module_platform_driver(exynos_sata_phy_driver); diff --git a/drivers/phy/phy-hix5hd2-sata.c b/drivers/phy/phy-hix5hd2-sata.c index 6a08fa5f81eb..d5d978085c6d 100644 --- a/drivers/phy/phy-hix5hd2-sata.c +++ b/drivers/phy/phy-hix5hd2-sata.c @@ -180,7 +180,6 @@ static struct platform_driver hix5hd2_sata_phy_driver = { .probe = hix5hd2_sata_phy_probe, .driver = { .name = "hix5hd2-sata-phy", - .owner = THIS_MODULE, .of_match_table = hix5hd2_sata_phy_of_match, } }; diff --git a/drivers/phy/phy-miphy365x.c b/drivers/phy/phy-miphy365x.c index e0fb7a1e5a5a..801afaf2d449 100644 --- a/drivers/phy/phy-miphy365x.c +++ b/drivers/phy/phy-miphy365x.c @@ -626,7 +626,6 @@ static struct platform_driver miphy365x_driver = { .probe = miphy365x_probe, .driver = { .name = "miphy365x-phy", - .owner = THIS_MODULE, .of_match_table = miphy365x_of_match, } }; diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c index cc3c0e166daf..d395558cb12e 100644 --- a/drivers/phy/phy-mvebu-sata.c +++ b/drivers/phy/phy-mvebu-sata.c @@ -89,6 +89,8 @@ static int phy_mvebu_sata_probe(struct platform_device *pdev) struct phy *phy; priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL); + if (!priv) + return -ENOMEM; res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(&pdev->dev, res); @@ -126,7 +128,6 @@ static struct platform_driver phy_mvebu_sata_driver = { .probe = phy_mvebu_sata_probe, .driver = { .name = "phy-mvebu-sata", - .owner = THIS_MODULE, .of_match_table = phy_mvebu_sata_of_match, } }; diff --git a/drivers/phy/phy-omap-control.c b/drivers/phy/phy-omap-control.c index 9487bf112267..c96e8183a8ff 100644 --- a/drivers/phy/phy-omap-control.c +++ b/drivers/phy/phy-omap-control.c @@ -295,10 +295,8 @@ static int omap_control_phy_probe(struct platform_device *pdev) control_phy = devm_kzalloc(&pdev->dev, sizeof(*control_phy), GFP_KERNEL); - if (!control_phy) { - dev_err(&pdev->dev, "unable to alloc memory for control phy\n"); + if (!control_phy) return -ENOMEM; - } control_phy->dev = &pdev->dev; control_phy->type = *(enum omap_control_phy_type *)of_id->data; @@ -347,7 +345,6 @@ static struct platform_driver omap_control_phy_driver = { .probe = omap_control_phy_probe, .driver = { .name = "omap-control-phy", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(omap_control_phy_id_table), }, }; diff --git a/drivers/phy/phy-omap-usb2.c b/drivers/phy/phy-omap-usb2.c index 93d78359246c..8c842980834a 100644 --- a/drivers/phy/phy-omap-usb2.c +++ b/drivers/phy/phy-omap-usb2.c @@ -212,16 +212,12 @@ static int omap_usb2_probe(struct platform_device *pdev) phy_data = (struct usb_phy_data *)of_id->data; phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); - if (!phy) { - dev_err(&pdev->dev, "unable to allocate memory for USB2 PHY\n"); + if (!phy) return -ENOMEM; - } otg = devm_kzalloc(&pdev->dev, sizeof(*otg), GFP_KERNEL); - if (!otg) { - dev_err(&pdev->dev, "unable to allocate memory for USB OTG\n"); + if (!otg) return -ENOMEM; - } phy->dev = &pdev->dev; @@ -382,7 +378,6 @@ static struct platform_driver omap_usb2_driver = { .remove = omap_usb2_remove, .driver = { .name = "omap-usb2", - .owner = THIS_MODULE, .pm = DEV_PM_OPS, .of_match_table = of_match_ptr(omap_usb2_id_table), }, diff --git a/drivers/phy/phy-qcom-apq8064-sata.c b/drivers/phy/phy-qcom-apq8064-sata.c index b3ef7d805765..7b3ddfb65898 100644 --- a/drivers/phy/phy-qcom-apq8064-sata.c +++ b/drivers/phy/phy-qcom-apq8064-sata.c @@ -279,7 +279,6 @@ static struct platform_driver qcom_apq8064_sata_phy_driver = { .remove = qcom_apq8064_sata_phy_remove, .driver = { .name = "qcom-apq8064-sata-phy", - .owner = THIS_MODULE, .of_match_table = qcom_apq8064_sata_phy_of_match, } }; diff --git a/drivers/phy/phy-qcom-ipq806x-sata.c b/drivers/phy/phy-qcom-ipq806x-sata.c index 909b5a87fc6a..759b0bf5b6b3 100644 --- a/drivers/phy/phy-qcom-ipq806x-sata.c +++ b/drivers/phy/phy-qcom-ipq806x-sata.c @@ -201,7 +201,6 @@ static struct platform_driver qcom_ipq806x_sata_phy_driver = { .remove = qcom_ipq806x_sata_phy_remove, .driver = { .name = "qcom-ipq806x-sata-phy", - .owner = THIS_MODULE, .of_match_table = qcom_ipq806x_sata_phy_of_match, } }; diff --git a/drivers/phy/phy-rcar-gen2.c b/drivers/phy/phy-rcar-gen2.c new file mode 100644 index 000000000000..2793af17799f --- /dev/null +++ b/drivers/phy/phy-rcar-gen2.c @@ -0,0 +1,341 @@ +/* + * Renesas R-Car Gen2 PHY driver + * + * Copyright (C) 2014 Renesas Solutions Corp. + * Copyright (C) 2014 Cogent Embedded, Inc. + * + * 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 + * published by the Free Software Foundation. + */ + +#include <linux/clk.h> +#include <linux/delay.h> +#include <linux/io.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/phy/phy.h> +#include <linux/platform_device.h> +#include <linux/spinlock.h> + +#include <asm/cmpxchg.h> + +#define USBHS_LPSTS 0x02 +#define USBHS_UGCTRL 0x80 +#define USBHS_UGCTRL2 0x84 +#define USBHS_UGSTS 0x88 /* The manuals have 0x90 */ + +/* Low Power Status register (LPSTS) */ +#define USBHS_LPSTS_SUSPM 0x4000 + +/* USB General control register (UGCTRL) */ +#define USBHS_UGCTRL_CONNECT 0x00000004 +#define USBHS_UGCTRL_PLLRESET 0x00000001 + +/* USB General control register 2 (UGCTRL2) */ +#define USBHS_UGCTRL2_USB2SEL 0x80000000 +#define USBHS_UGCTRL2_USB2SEL_PCI 0x00000000 +#define USBHS_UGCTRL2_USB2SEL_USB30 0x80000000 +#define USBHS_UGCTRL2_USB0SEL 0x00000030 +#define USBHS_UGCTRL2_USB0SEL_PCI 0x00000010 +#define USBHS_UGCTRL2_USB0SEL_HS_USB 0x00000030 + +/* USB General status register (UGSTS) */ +#define USBHS_UGSTS_LOCK 0x00000300 /* The manuals have 0x3 */ + +#define PHYS_PER_CHANNEL 2 + +struct rcar_gen2_phy { + struct phy *phy; + struct rcar_gen2_channel *channel; + int number; + u32 select_value; +}; + +struct rcar_gen2_channel { + struct device_node *of_node; + struct rcar_gen2_phy_driver *drv; + struct rcar_gen2_phy phys[PHYS_PER_CHANNEL]; + int selected_phy; + u32 select_mask; +}; + +struct rcar_gen2_phy_driver { + void __iomem *base; + struct clk *clk; + spinlock_t lock; + int num_channels; + struct rcar_gen2_channel *channels; +}; + +static int rcar_gen2_phy_init(struct phy *p) +{ + struct rcar_gen2_phy *phy = phy_get_drvdata(p); + struct rcar_gen2_channel *channel = phy->channel; + struct rcar_gen2_phy_driver *drv = channel->drv; + unsigned long flags; + u32 ugctrl2; + + /* + * Try to acquire exclusive access to PHY. The first driver calling + * phy_init() on a given channel wins, and all attempts to use another + * PHY on this channel will fail until phy_exit() is called by the first + * driver. Achieving this with cmpxcgh() should be SMP-safe. + */ + if (cmpxchg(&channel->selected_phy, -1, phy->number) != -1) + return -EBUSY; + + clk_prepare_enable(drv->clk); + + spin_lock_irqsave(&drv->lock, flags); + ugctrl2 = readl(drv->base + USBHS_UGCTRL2); + ugctrl2 &= ~channel->select_mask; + ugctrl2 |= phy->select_value; + writel(ugctrl2, drv->base + USBHS_UGCTRL2); + spin_unlock_irqrestore(&drv->lock, flags); + return 0; +} + +static int rcar_gen2_phy_exit(struct phy *p) +{ + struct rcar_gen2_phy *phy = phy_get_drvdata(p); + struct rcar_gen2_channel *channel = phy->channel; + + clk_disable_unprepare(channel->drv->clk); + + channel->selected_phy = -1; + + return 0; +} + +static int rcar_gen2_phy_power_on(struct phy *p) +{ + struct rcar_gen2_phy *phy = phy_get_drvdata(p); + struct rcar_gen2_phy_driver *drv = phy->channel->drv; + void __iomem *base = drv->base; + unsigned long flags; + u32 value; + int err = 0, i; + + /* Skip if it's not USBHS */ + if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) + return 0; + + spin_lock_irqsave(&drv->lock, flags); + + /* Power on USBHS PHY */ + value = readl(base + USBHS_UGCTRL); + value &= ~USBHS_UGCTRL_PLLRESET; + writel(value, base + USBHS_UGCTRL); + + value = readw(base + USBHS_LPSTS); + value |= USBHS_LPSTS_SUSPM; + writew(value, base + USBHS_LPSTS); + + for (i = 0; i < 20; i++) { + value = readl(base + USBHS_UGSTS); + if ((value & USBHS_UGSTS_LOCK) == USBHS_UGSTS_LOCK) { + value = readl(base + USBHS_UGCTRL); + value |= USBHS_UGCTRL_CONNECT; + writel(value, base + USBHS_UGCTRL); + goto out; + } + udelay(1); + } + + /* Timed out waiting for the PLL lock */ + err = -ETIMEDOUT; + +out: + spin_unlock_irqrestore(&drv->lock, flags); + + return err; +} + +static int rcar_gen2_phy_power_off(struct phy *p) +{ + struct rcar_gen2_phy *phy = phy_get_drvdata(p); + struct rcar_gen2_phy_driver *drv = phy->channel->drv; + void __iomem *base = drv->base; + unsigned long flags; + u32 value; + + /* Skip if it's not USBHS */ + if (phy->select_value != USBHS_UGCTRL2_USB0SEL_HS_USB) + return 0; + + spin_lock_irqsave(&drv->lock, flags); + + /* Power off USBHS PHY */ + value = readl(base + USBHS_UGCTRL); + value &= ~USBHS_UGCTRL_CONNECT; + writel(value, base + USBHS_UGCTRL); + + value = readw(base + USBHS_LPSTS); + value &= ~USBHS_LPSTS_SUSPM; + writew(value, base + USBHS_LPSTS); + + value = readl(base + USBHS_UGCTRL); + value |= USBHS_UGCTRL_PLLRESET; + writel(value, base + USBHS_UGCTRL); + + spin_unlock_irqrestore(&drv->lock, flags); + + return 0; +} + +static struct phy_ops rcar_gen2_phy_ops = { + .init = rcar_gen2_phy_init, + .exit = rcar_gen2_phy_exit, + .power_on = rcar_gen2_phy_power_on, + .power_off = rcar_gen2_phy_power_off, + .owner = THIS_MODULE, +}; + +static const struct of_device_id rcar_gen2_phy_match_table[] = { + { .compatible = "renesas,usb-phy-r8a7790" }, + { .compatible = "renesas,usb-phy-r8a7791" }, + { } +}; +MODULE_DEVICE_TABLE(of, rcar_gen2_phy_match_table); + +static struct phy *rcar_gen2_phy_xlate(struct device *dev, + struct of_phandle_args *args) +{ + struct rcar_gen2_phy_driver *drv; + struct device_node *np = args->np; + int i; + + if (!of_device_is_available(np)) { + dev_warn(dev, "Requested PHY is disabled\n"); + return ERR_PTR(-ENODEV); + } + + drv = dev_get_drvdata(dev); + if (!drv) + return ERR_PTR(-EINVAL); + + for (i = 0; i < drv->num_channels; i++) { + if (np == drv->channels[i].of_node) + break; + } + + if (i >= drv->num_channels || args->args[0] >= 2) + return ERR_PTR(-ENODEV); + + return drv->channels[i].phys[args->args[0]].phy; +} + +static const u32 select_mask[] = { + [0] = USBHS_UGCTRL2_USB0SEL, + [2] = USBHS_UGCTRL2_USB2SEL, +}; + +static const u32 select_value[][PHYS_PER_CHANNEL] = { + [0] = { USBHS_UGCTRL2_USB0SEL_PCI, USBHS_UGCTRL2_USB0SEL_HS_USB }, + [2] = { USBHS_UGCTRL2_USB2SEL_PCI, USBHS_UGCTRL2_USB2SEL_USB30 }, +}; + +static int rcar_gen2_phy_probe(struct platform_device *pdev) +{ + struct device *dev = &pdev->dev; + struct rcar_gen2_phy_driver *drv; + struct phy_provider *provider; + struct device_node *np; + struct resource *res; + void __iomem *base; + struct clk *clk; + int i = 0; + + if (!dev->of_node) { + dev_err(dev, + "This driver is required to be instantiated from device tree\n"); + return -EINVAL; + } + + clk = devm_clk_get(dev, "usbhs"); + if (IS_ERR(clk)) { + dev_err(dev, "Can't get USBHS clock\n"); + return PTR_ERR(clk); + } + + res = platform_get_resource(pdev, IORESOURCE_MEM, 0); + base = devm_ioremap_resource(dev, res); + if (IS_ERR(base)) + return PTR_ERR(base); + + drv = devm_kzalloc(dev, sizeof(*drv), GFP_KERNEL); + if (!drv) + return -ENOMEM; + + spin_lock_init(&drv->lock); + + drv->clk = clk; + drv->base = base; + + drv->num_channels = of_get_child_count(dev->of_node); + drv->channels = devm_kcalloc(dev, drv->num_channels, + sizeof(struct rcar_gen2_channel), + GFP_KERNEL); + if (!drv->channels) + return -ENOMEM; + + for_each_child_of_node(dev->of_node, np) { + struct rcar_gen2_channel *channel = drv->channels + i; + u32 channel_num; + int error, n; + + channel->of_node = np; + channel->drv = drv; + channel->selected_phy = -1; + + error = of_property_read_u32(np, "reg", &channel_num); + if (error || channel_num > 2) { + dev_err(dev, "Invalid \"reg\" property\n"); + return error; + } + channel->select_mask = select_mask[channel_num]; + + for (n = 0; n < PHYS_PER_CHANNEL; n++) { + struct rcar_gen2_phy *phy = &channel->phys[n]; + + phy->channel = channel; + phy->number = n; + phy->select_value = select_value[channel_num][n]; + + phy->phy = devm_phy_create(dev, NULL, + &rcar_gen2_phy_ops, NULL); + if (IS_ERR(phy->phy)) { + dev_err(dev, "Failed to create PHY\n"); + return PTR_ERR(phy->phy); + } + phy_set_drvdata(phy->phy, phy); + } + + i++; + } + + provider = devm_of_phy_provider_register(dev, rcar_gen2_phy_xlate); + if (IS_ERR(provider)) { + dev_err(dev, "Failed to register PHY provider\n"); + return PTR_ERR(provider); + } + + dev_set_drvdata(dev, drv); + + return 0; +} + +static struct platform_driver rcar_gen2_phy_driver = { + .driver = { + .name = "phy_rcar_gen2", + .of_match_table = rcar_gen2_phy_match_table, + }, + .probe = rcar_gen2_phy_probe, +}; + +module_platform_driver(rcar_gen2_phy_driver); + +MODULE_LICENSE("GPL v2"); +MODULE_DESCRIPTION("Renesas R-Car Gen2 PHY"); +MODULE_AUTHOR("Sergei Shtylyov <sergei.shtylyov@cogentembedded.com>"); diff --git a/drivers/phy/phy-samsung-usb2.c b/drivers/phy/phy-samsung-usb2.c index 3732ca25e09f..908949dfb4db 100644 --- a/drivers/phy/phy-samsung-usb2.c +++ b/drivers/phy/phy-samsung-usb2.c @@ -231,7 +231,6 @@ static struct platform_driver samsung_usb2_phy_driver = { .driver = { .of_match_table = samsung_usb2_phy_of_match, .name = "samsung-usb2-phy", - .owner = THIS_MODULE, } }; diff --git a/drivers/phy/phy-spear1310-miphy.c b/drivers/phy/phy-spear1310-miphy.c index 6dcbfcddb372..5f4c586ee951 100644 --- a/drivers/phy/phy-spear1310-miphy.c +++ b/drivers/phy/phy-spear1310-miphy.c @@ -212,10 +212,8 @@ static int spear1310_miphy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(dev, "can't alloc spear1310_miphy private date memory\n"); + if (!priv) return -ENOMEM; - } priv->misc = syscon_regmap_lookup_by_phandle(dev->of_node, "misc"); @@ -252,22 +250,11 @@ static struct platform_driver spear1310_miphy_driver = { .probe = spear1310_miphy_probe, .driver = { .name = "spear1310-miphy", - .owner = THIS_MODULE, .of_match_table = of_match_ptr(spear1310_miphy_of_match), }, }; -static int __init spear1310_miphy_phy_init(void) -{ - return platform_driver_register(&spear1310_miphy_driver); -} -module_init(spear1310_miphy_phy_init); - -static void __exit spear1310_miphy_phy_exit(void) -{ - platform_driver_unregister(&spear1310_miphy_driver); -} -module_exit(spear1310_miphy_phy_exit); +module_platform_driver(spear1310_miphy_driver); MODULE_DESCRIPTION("ST SPEAR1310-MIPHY driver"); MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); diff --git a/drivers/phy/phy-spear1340-miphy.c b/drivers/phy/phy-spear1340-miphy.c index 7135ba2603b6..1ecd0945bad3 100644 --- a/drivers/phy/phy-spear1340-miphy.c +++ b/drivers/phy/phy-spear1340-miphy.c @@ -249,10 +249,8 @@ static int spear1340_miphy_probe(struct platform_device *pdev) struct phy_provider *phy_provider; priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); - if (!priv) { - dev_err(dev, "can't alloc spear1340_miphy private date memory\n"); + if (!priv) return -ENOMEM; - } priv->misc = syscon_regmap_lookup_by_phandle(dev->of_node, "misc"); @@ -284,23 +282,12 @@ static struct platform_driver spear1340_miphy_driver = { .probe = spear1340_miphy_probe, .driver = { .name = "spear1340-miphy", - .owner = THIS_MODULE, .pm = &spear1340_miphy_pm_ops, .of_match_table = of_match_ptr(spear1340_miphy_of_match), }, }; -static int __init spear1340_miphy_phy_init(void) -{ - return platform_driver_register(&spear1340_miphy_driver); -} -module_init(spear1340_miphy_phy_init); - -static void __exit spear1340_miphy_phy_exit(void) -{ - platform_driver_unregister(&spear1340_miphy_driver); -} -module_exit(spear1340_miphy_phy_exit); +module_platform_driver(spear1340_miphy_driver); MODULE_DESCRIPTION("ST SPEAR1340-MIPHY driver"); MODULE_AUTHOR("Pratyush Anand <pratyush.anand@st.com>"); diff --git a/drivers/phy/phy-stih407-usb.c b/drivers/phy/phy-stih407-usb.c new file mode 100644 index 000000000000..42428d4181ea --- /dev/null +++ b/drivers/phy/phy-stih407-usb.c @@ -0,0 +1,177 @@ +/* + * Copyright (C) 2014 STMicroelectronics + * + * STMicroelectronics Generic PHY driver for STiH407 USB2. + * + * Author: Giuseppe Cavallaro <peppe.cavallaro@st.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 + * published by the Free Software Foundation. + * + */ +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/clk.h> +#include <linux/regmap.h> +#include <linux/reset.h> +#include <linux/mfd/syscon.h> +#include <linux/phy/phy.h> + +/* Default PHY_SEL and REFCLKSEL configuration */ +#define STIH407_USB_PICOPHY_CTRL_PORT_CONF 0x6 +#define STIH407_USB_PICOPHY_CTRL_PORT_MASK 0x1f + +/* ports parameters overriding */ +#define STIH407_USB_PICOPHY_PARAM_DEF 0x39a4dc +#define STIH407_USB_PICOPHY_PARAM_MASK 0xffffffff + +struct stih407_usb2_picophy { + struct phy *phy; + struct regmap *regmap; + struct device *dev; + struct reset_control *rstc; + struct reset_control *rstport; + int ctrl; + int param; +}; + +static int stih407_usb2_pico_ctrl(struct stih407_usb2_picophy *phy_dev) +{ + reset_control_deassert(phy_dev->rstc); + + return regmap_update_bits(phy_dev->regmap, phy_dev->ctrl, + STIH407_USB_PICOPHY_CTRL_PORT_MASK, + STIH407_USB_PICOPHY_CTRL_PORT_CONF); +} + +static int stih407_usb2_init_port(struct phy *phy) +{ + int ret; + struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy); + + stih407_usb2_pico_ctrl(phy_dev); + + ret = regmap_update_bits(phy_dev->regmap, + phy_dev->param, + STIH407_USB_PICOPHY_PARAM_MASK, + STIH407_USB_PICOPHY_PARAM_DEF); + if (ret) + return ret; + + return reset_control_deassert(phy_dev->rstport); +} + +static int stih407_usb2_exit_port(struct phy *phy) +{ + struct stih407_usb2_picophy *phy_dev = phy_get_drvdata(phy); + + /* + * Only port reset is asserted, phy global reset is kept untouched + * as other ports may still be active. When all ports are in reset + * state, assumption is made that power will be cut off on the phy, in + * case of suspend for instance. Theoretically, asserting individual + * reset (like here) or global reset should be equivalent. + */ + return reset_control_assert(phy_dev->rstport); +} + +static const struct phy_ops stih407_usb2_picophy_data = { + .init = stih407_usb2_init_port, + .exit = stih407_usb2_exit_port, + .owner = THIS_MODULE, +}; + +static int stih407_usb2_picophy_probe(struct platform_device *pdev) +{ + struct stih407_usb2_picophy *phy_dev; + struct device *dev = &pdev->dev; + struct device_node *np = dev->of_node; + struct phy_provider *phy_provider; + struct phy *phy; + struct resource *res; + + phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); + if (!phy_dev) + return -ENOMEM; + + phy_dev->dev = dev; + dev_set_drvdata(dev, phy_dev); + + phy_dev->rstc = devm_reset_control_get(dev, "global"); + if (IS_ERR(phy_dev->rstc)) { + dev_err(dev, "failed to ctrl picoPHY reset\n"); + return PTR_ERR(phy_dev->rstc); + } + + phy_dev->rstport = devm_reset_control_get(dev, "port"); + if (IS_ERR(phy_dev->rstport)) { + dev_err(dev, "failed to ctrl picoPHY reset\n"); + return PTR_ERR(phy_dev->rstport); + } + + /* Reset port by default: only deassert it in phy init */ + reset_control_assert(phy_dev->rstport); + + phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(phy_dev->regmap)) { + dev_err(dev, "No syscfg phandle specified\n"); + return PTR_ERR(phy_dev->regmap); + } + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "ctrl"); + if (!res) { + dev_err(dev, "No ctrl reg found\n"); + return -ENXIO; + } + phy_dev->ctrl = res->start; + + res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "param"); + if (!res) { + dev_err(dev, "No param reg found\n"); + return -ENXIO; + } + phy_dev->param = res->start; + + phy = devm_phy_create(dev, NULL, &stih407_usb2_picophy_data, NULL); + if (IS_ERR(phy)) { + dev_err(dev, "failed to create Display Port PHY\n"); + return PTR_ERR(phy); + } + + phy_dev->phy = phy; + phy_set_drvdata(phy, phy_dev); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + dev_info(dev, "STiH407 USB Generic picoPHY driver probed!"); + + return 0; +} + +static const struct of_device_id stih407_usb2_picophy_of_match[] = { + { .compatible = "st,stih407-usb2-phy" }, + { /*sentinel */ }, +}; + +MODULE_DEVICE_TABLE(of, stih407_usb2_picophy_of_match); + +static struct platform_driver stih407_usb2_picophy_driver = { + .probe = stih407_usb2_picophy_probe, + .driver = { + .name = "stih407-usb-genphy", + .of_match_table = stih407_usb2_picophy_of_match, + } +}; + +module_platform_driver(stih407_usb2_picophy_driver); + +MODULE_AUTHOR("Giuseppe Cavallaro <peppe.cavallaro@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics Generic picoPHY driver for STiH407"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-stih41x-usb.c b/drivers/phy/phy-stih41x-usb.c new file mode 100644 index 000000000000..9f16cb8e01f4 --- /dev/null +++ b/drivers/phy/phy-stih41x-usb.c @@ -0,0 +1,187 @@ +/* + * Copyright (C) 2014 STMicroelectronics + * + * STMicroelectronics PHY driver for STiH41x USB. + * + * Author: Maxime Coquelin <maxime.coquelin@st.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 + * published by the Free Software Foundation. + * + */ + +#include <linux/platform_device.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/module.h> +#include <linux/of.h> +#include <linux/of_platform.h> +#include <linux/clk.h> +#include <linux/phy/phy.h> +#include <linux/regmap.h> +#include <linux/mfd/syscon.h> + +#define SYSCFG332 0x80 +#define SYSCFG2520 0x820 + +/** + * struct stih41x_usb_cfg - SoC specific PHY register mapping + * @syscfg: Offset in syscfg registers bank + * @cfg_mask: Bits mask for PHY configuration + * @cfg: Static configuration value for PHY + * @oscok: Notify the PHY oscillator clock is ready + * Setting this bit enable the PHY + */ +struct stih41x_usb_cfg { + u32 syscfg; + u32 cfg_mask; + u32 cfg; + u32 oscok; +}; + +/** + * struct stih41x_usb_phy - Private data for the PHY + * @dev: device for this controller + * @regmap: Syscfg registers bank in which PHY is configured + * @cfg: SoC specific PHY register mapping + * @clk: Oscillator used by the PHY + */ +struct stih41x_usb_phy { + struct device *dev; + struct regmap *regmap; + const struct stih41x_usb_cfg *cfg; + struct clk *clk; +}; + +static struct stih41x_usb_cfg stih415_usb_phy_cfg = { + .syscfg = SYSCFG332, + .cfg_mask = 0x3f, + .cfg = 0x38, + .oscok = BIT(6), +}; + +static struct stih41x_usb_cfg stih416_usb_phy_cfg = { + .syscfg = SYSCFG2520, + .cfg_mask = 0x33f, + .cfg = 0x238, + .oscok = BIT(6), +}; + +static int stih41x_usb_phy_init(struct phy *phy) +{ + struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); + + return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->cfg_mask, phy_dev->cfg->cfg); +} + +static int stih41x_usb_phy_power_on(struct phy *phy) +{ + struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); + int ret; + + ret = clk_prepare_enable(phy_dev->clk); + if (ret) { + dev_err(phy_dev->dev, "Failed to enable osc_phy clock\n"); + return ret; + } + + return regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->oscok, phy_dev->cfg->oscok); +} + +static int stih41x_usb_phy_power_off(struct phy *phy) +{ + struct stih41x_usb_phy *phy_dev = phy_get_drvdata(phy); + int ret; + + ret = regmap_update_bits(phy_dev->regmap, phy_dev->cfg->syscfg, + phy_dev->cfg->oscok, 0); + if (ret) { + dev_err(phy_dev->dev, "Failed to clear oscok bit\n"); + return ret; + } + + clk_disable_unprepare(phy_dev->clk); + + return 0; +} + +static struct phy_ops stih41x_usb_phy_ops = { + .init = stih41x_usb_phy_init, + .power_on = stih41x_usb_phy_power_on, + .power_off = stih41x_usb_phy_power_off, + .owner = THIS_MODULE, +}; + +static const struct of_device_id stih41x_usb_phy_of_match[]; + +static int stih41x_usb_phy_probe(struct platform_device *pdev) +{ + struct device_node *np = pdev->dev.of_node; + const struct of_device_id *match; + struct stih41x_usb_phy *phy_dev; + struct device *dev = &pdev->dev; + struct phy_provider *phy_provider; + struct phy *phy; + + phy_dev = devm_kzalloc(dev, sizeof(*phy_dev), GFP_KERNEL); + if (!phy_dev) + return -ENOMEM; + + match = of_match_device(stih41x_usb_phy_of_match, &pdev->dev); + if (!match) + return -ENODEV; + + phy_dev->cfg = match->data; + + phy_dev->regmap = syscon_regmap_lookup_by_phandle(np, "st,syscfg"); + if (IS_ERR(phy_dev->regmap)) { + dev_err(dev, "No syscfg phandle specified\n"); + return PTR_ERR(phy_dev->regmap); + } + + phy_dev->clk = devm_clk_get(dev, "osc_phy"); + if (IS_ERR(phy_dev->clk)) { + dev_err(dev, "osc_phy clk not found\n"); + return PTR_ERR(phy_dev->clk); + } + + phy = devm_phy_create(dev, NULL, &stih41x_usb_phy_ops, NULL); + + if (IS_ERR(phy)) { + dev_err(dev, "failed to create phy\n"); + return PTR_ERR(phy); + } + + phy_dev->dev = dev; + + phy_set_drvdata(phy, phy_dev); + + phy_provider = devm_of_phy_provider_register(dev, of_phy_simple_xlate); + if (IS_ERR(phy_provider)) + return PTR_ERR(phy_provider); + + return 0; +} + +static const struct of_device_id stih41x_usb_phy_of_match[] = { + { .compatible = "st,stih415-usb-phy", .data = &stih415_usb_phy_cfg }, + { .compatible = "st,stih416-usb-phy", .data = &stih416_usb_phy_cfg }, + { /* sentinel */ }, +}; +MODULE_DEVICE_TABLE(of, stih41x_usb_phy_of_match); + +static struct platform_driver stih41x_usb_phy_driver = { + .probe = stih41x_usb_phy_probe, + .driver = { + .name = "stih41x-usb-phy", + .of_match_table = stih41x_usb_phy_of_match, + } +}; +module_platform_driver(stih41x_usb_phy_driver); + +MODULE_AUTHOR("Maxime Coquelin <maxime.coquelin@st.com>"); +MODULE_DESCRIPTION("STMicroelectronics USB PHY driver for STiH41x series"); +MODULE_LICENSE("GPL v2"); diff --git a/drivers/phy/phy-sun4i-usb.c b/drivers/phy/phy-sun4i-usb.c index 61ebea49709b..0baf5efc8a40 100644 --- a/drivers/phy/phy-sun4i-usb.c +++ b/drivers/phy/phy-sun4i-usb.c @@ -325,7 +325,6 @@ static struct platform_driver sun4i_usb_phy_driver = { .driver = { .of_match_table = sun4i_usb_phy_of_match, .name = "sun4i-usb-phy", - .owner = THIS_MODULE, } }; module_platform_driver(sun4i_usb_phy_driver); diff --git a/drivers/phy/phy-ti-pipe3.c b/drivers/phy/phy-ti-pipe3.c index b964aa967b46..ab1e22d9a1e8 100644 --- a/drivers/phy/phy-ti-pipe3.c +++ b/drivers/phy/phy-ti-pipe3.c @@ -299,10 +299,9 @@ static int ti_pipe3_probe(struct platform_device *pdev) struct clk *clk; phy = devm_kzalloc(&pdev->dev, sizeof(*phy), GFP_KERNEL); - if (!phy) { - dev_err(&pdev->dev, "unable to alloc mem for TI PIPE3 PHY\n"); + if (!phy) return -ENOMEM; - } + phy->dev = &pdev->dev; if (!of_device_is_compatible(node, "ti,phy-pipe3-pcie")) { @@ -519,7 +518,6 @@ static struct platform_driver ti_pipe3_driver = { .remove = ti_pipe3_remove, .driver = { .name = "ti-pipe3", - .owner = THIS_MODULE, .pm = DEV_PM_OPS, .of_match_table = of_match_ptr(ti_pipe3_id_table), }, diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c index 9cd33a4bcfb1..7b04befd5271 100644 --- a/drivers/phy/phy-twl4030-usb.c +++ b/drivers/phy/phy-twl4030-usb.c @@ -28,7 +28,6 @@ #include <linux/init.h> #include <linux/interrupt.h> #include <linux/platform_device.h> -#include <linux/spinlock.h> #include <linux/workqueue.h> #include <linux/io.h> #include <linux/delay.h> @@ -155,7 +154,7 @@ struct twl4030_usb { struct regulator *usb3v1; /* for vbus reporting with irqs disabled */ - spinlock_t lock; + struct mutex lock; /* pin configuration */ enum twl4030_usb_mode usb_mode; @@ -163,8 +162,6 @@ struct twl4030_usb { int irq; enum omap_musb_vbus_id_status linkstat; bool vbus_supplied; - u8 asleep; - bool irq_enabled; struct delayed_work id_workaround_work; }; @@ -384,55 +381,18 @@ static void __twl4030_phy_power(struct twl4030_usb *twl, int on) WARN_ON(twl4030_usb_write_verify(twl, PHY_PWR_CTRL, pwr) < 0); } -static void twl4030_phy_power(struct twl4030_usb *twl, int on) -{ - int ret; - - if (on) { - ret = regulator_enable(twl->usb3v1); - if (ret) - dev_err(twl->dev, "Failed to enable usb3v1\n"); - - ret = regulator_enable(twl->usb1v8); - if (ret) - dev_err(twl->dev, "Failed to enable usb1v8\n"); - - /* - * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP - * in twl4030) resets the VUSB_DEDICATED2 register. This reset - * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to - * SLEEP. We work around this by clearing the bit after usv3v1 - * is re-activated. This ensures that VUSB3V1 is really active. - */ - twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); - - ret = regulator_enable(twl->usb1v5); - if (ret) - dev_err(twl->dev, "Failed to enable usb1v5\n"); - - __twl4030_phy_power(twl, 1); - twl4030_usb_write(twl, PHY_CLK_CTRL, - twl4030_usb_read(twl, PHY_CLK_CTRL) | - (PHY_CLK_CTRL_CLOCKGATING_EN | - PHY_CLK_CTRL_CLK32K_EN)); - } else { - __twl4030_phy_power(twl, 0); - regulator_disable(twl->usb1v5); - regulator_disable(twl->usb1v8); - regulator_disable(twl->usb3v1); - } -} - static int twl4030_usb_runtime_suspend(struct device *dev) { struct twl4030_usb *twl = dev_get_drvdata(dev); dev_dbg(twl->dev, "%s\n", __func__); - if (twl->asleep) + if (pm_runtime_suspended(dev)) return 0; - twl4030_phy_power(twl, 0); - twl->asleep = 1; + __twl4030_phy_power(twl, 0); + regulator_disable(twl->usb1v5); + regulator_disable(twl->usb1v8); + regulator_disable(twl->usb3v1); return 0; } @@ -440,13 +400,38 @@ static int twl4030_usb_runtime_suspend(struct device *dev) static int twl4030_usb_runtime_resume(struct device *dev) { struct twl4030_usb *twl = dev_get_drvdata(dev); + int res; dev_dbg(twl->dev, "%s\n", __func__); - if (!twl->asleep) + if (pm_runtime_active(dev)) return 0; - twl4030_phy_power(twl, 1); - twl->asleep = 0; + res = regulator_enable(twl->usb3v1); + if (res) + dev_err(twl->dev, "Failed to enable usb3v1\n"); + + res = regulator_enable(twl->usb1v8); + if (res) + dev_err(twl->dev, "Failed to enable usb1v8\n"); + + /* + * Disabling usb3v1 regulator (= writing 0 to VUSB3V1_DEV_GRP + * in twl4030) resets the VUSB_DEDICATED2 register. This reset + * enables VUSB3V1_SLEEP bit that remaps usb3v1 ACTIVE state to + * SLEEP. We work around this by clearing the bit after usv3v1 + * is re-activated. This ensures that VUSB3V1 is really active. + */ + twl_i2c_write_u8(TWL_MODULE_PM_RECEIVER, 0, VUSB_DEDICATED2); + + res = regulator_enable(twl->usb1v5); + if (res) + dev_err(twl->dev, "Failed to enable usb1v5\n"); + + __twl4030_phy_power(twl, 1); + twl4030_usb_write(twl, PHY_CLK_CTRL, + twl4030_usb_read(twl, PHY_CLK_CTRL) | + (PHY_CLK_CTRL_CLOCKGATING_EN | + PHY_CLK_CTRL_CLK32K_EN)); return 0; } @@ -472,16 +457,8 @@ static int twl4030_phy_power_on(struct phy *phy) twl4030_usb_set_mode(twl, twl->usb_mode); if (twl->usb_mode == T2_USB_MODE_ULPI) twl4030_i2c_access(twl, 0); + schedule_delayed_work(&twl->id_workaround_work, 0); - /* - * XXX When VBUS gets driven after musb goes to A mode, - * ID_PRES related interrupts no longer arrive, why? - * Register itself is updated fine though, so we must poll. - */ - if (twl->linkstat == OMAP_MUSB_ID_GROUND) { - cancel_delayed_work(&twl->id_workaround_work); - schedule_delayed_work(&twl->id_workaround_work, HZ); - } return 0; } @@ -538,13 +515,12 @@ static ssize_t twl4030_usb_vbus_show(struct device *dev, struct device_attribute *attr, char *buf) { struct twl4030_usb *twl = dev_get_drvdata(dev); - unsigned long flags; int ret = -EINVAL; - spin_lock_irqsave(&twl->lock, flags); + mutex_lock(&twl->lock); ret = sprintf(buf, "%s\n", twl->vbus_supplied ? "on" : "off"); - spin_unlock_irqrestore(&twl->lock, flags); + mutex_unlock(&twl->lock); return ret; } @@ -558,12 +534,12 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) status = twl4030_usb_linkstat(twl); - spin_lock_irq(&twl->lock); + mutex_lock(&twl->lock); if (status >= 0 && status != twl->linkstat) { twl->linkstat = status; status_changed = true; } - spin_unlock_irq(&twl->lock); + mutex_unlock(&twl->lock); if (status_changed) { /* FIXME add a set_power() method so that B-devices can @@ -579,10 +555,10 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) */ if ((status == OMAP_MUSB_VBUS_VALID) || (status == OMAP_MUSB_ID_GROUND)) { - if (twl->asleep) + if (pm_runtime_suspended(twl->dev)) pm_runtime_get_sync(twl->dev); } else { - if (!twl->asleep) { + if (pm_runtime_active(twl->dev)) { pm_runtime_mark_last_busy(twl->dev); pm_runtime_put_autosuspend(twl->dev); } @@ -591,7 +567,7 @@ static irqreturn_t twl4030_usb_irq(int irq, void *_twl) } /* don't schedule during sleep - irq works right then */ - if (status == OMAP_MUSB_ID_GROUND && !twl->asleep) { + if (status == OMAP_MUSB_ID_GROUND && pm_runtime_active(twl->dev)) { cancel_delayed_work(&twl->id_workaround_work); schedule_delayed_work(&twl->id_workaround_work, HZ); } @@ -613,16 +589,9 @@ static void twl4030_id_workaround_work(struct work_struct *work) static int twl4030_phy_init(struct phy *phy) { struct twl4030_usb *twl = phy_get_drvdata(phy); - enum omap_musb_vbus_id_status status; pm_runtime_get_sync(twl->dev); - status = twl4030_usb_linkstat(twl); - twl->linkstat = status; - - if (status == OMAP_MUSB_ID_GROUND || status == OMAP_MUSB_VBUS_VALID) - omap_musb_mailbox(twl->linkstat); - - sysfs_notify(&twl->dev->kobj, NULL, "vbus"); + schedule_delayed_work(&twl->id_workaround_work, 0); pm_runtime_mark_last_busy(twl->dev); pm_runtime_put_autosuspend(twl->dev); @@ -699,7 +668,7 @@ static int twl4030_usb_probe(struct platform_device *pdev) twl->dev = &pdev->dev; twl->irq = platform_get_irq(pdev, 0); twl->vbus_supplied = false; - twl->asleep = 1; + twl->linkstat = -EINVAL; twl->linkstat = OMAP_MUSB_UNKNOWN; twl->phy.dev = twl->dev; @@ -724,8 +693,8 @@ static int twl4030_usb_probe(struct platform_device *pdev) if (IS_ERR(phy_provider)) return PTR_ERR(phy_provider); - /* init spinlock for workqueue */ - spin_lock_init(&twl->lock); + /* init mutex for workqueue */ + mutex_init(&twl->lock); INIT_DELAYED_WORK(&twl->id_workaround_work, twl4030_id_workaround_work); @@ -755,7 +724,6 @@ static int twl4030_usb_probe(struct platform_device *pdev) * set_host() and/or set_peripheral() ... OTG_capable boards * need both handles, otherwise just one suffices. */ - twl->irq_enabled = true; status = devm_request_threaded_irq(twl->dev, twl->irq, NULL, twl4030_usb_irq, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING | IRQF_ONESHOT, "twl4030_usb", twl); @@ -817,7 +785,6 @@ static struct platform_driver twl4030_usb_driver = { .driver = { .name = "twl4030_usb", .pm = &twl4030_usb_pm_ops, - .owner = THIS_MODULE, .of_match_table = of_match_ptr(twl4030_usb_id_table), }, }; diff --git a/drivers/phy/phy-xgene.c b/drivers/phy/phy-xgene.c index db809b97219e..f8a51b16ade8 100644 --- a/drivers/phy/phy-xgene.c +++ b/drivers/phy/phy-xgene.c @@ -1738,7 +1738,6 @@ static struct platform_driver xgene_phy_driver = { .probe = xgene_phy_probe, .driver = { .name = "xgene-phy", - .owner = THIS_MODULE, .of_match_table = xgene_phy_of_match, }, }; diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig index 18a3358eb1d4..bd85fb4978e0 100644 --- a/drivers/scsi/Kconfig +++ b/drivers/scsi/Kconfig @@ -43,7 +43,7 @@ config SCSI_DMA config SCSI_NETLINK bool default n - select NET + depends on NET config SCSI_PROC_FS bool "legacy /proc/scsi/ support" @@ -257,7 +257,7 @@ config SCSI_SPI_ATTRS config SCSI_FC_ATTRS tristate "FiberChannel Transport Attributes" - depends on SCSI + depends on SCSI && NET select SCSI_NETLINK help If you wish to export transport-specific information about @@ -585,28 +585,28 @@ config HYPERV_STORAGE config LIBFC tristate "LibFC module" - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS select CRC32 ---help--- Fibre Channel library module config LIBFCOE tristate "LibFCoE module" - select LIBFC + depends on LIBFC ---help--- Library for Fibre Channel over Ethernet module config FCOE tristate "FCoE module" depends on PCI - select LIBFCOE + depends on LIBFCOE ---help--- Fibre Channel over Ethernet module config FCOE_FNIC tristate "Cisco FNIC Driver" depends on PCI && X86 - select LIBFCOE + depends on LIBFCOE help This is support for the Cisco PCI-Express FCoE HBA. @@ -816,7 +816,7 @@ config SCSI_IBMVSCSI config SCSI_IBMVFC tristate "IBM Virtual FC support" depends on PPC_PSERIES && SCSI - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS help This is the IBM POWER Virtual FC Client @@ -1266,7 +1266,7 @@ source "drivers/scsi/qla4xxx/Kconfig" config SCSI_LPFC tristate "Emulex LightPulse Fibre Channel Support" depends on PCI && SCSI - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS select CRC_T10DIF help This lpfc driver supports the Emulex LightPulse @@ -1676,7 +1676,7 @@ config SCSI_SUNESP config ZFCP tristate "FCP host bus adapter driver for IBM eServer zSeries" depends on S390 && QDIO && SCSI - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS help If you want to access SCSI devices attached to your IBM eServer zSeries by means of Fibre Channel interfaces say Y. @@ -1704,7 +1704,7 @@ config SCSI_PM8001 config SCSI_BFA_FC tristate "Brocade BFA Fibre Channel Support" depends on PCI && SCSI - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS help This bfa driver supports all Brocade PCIe FC/FCOE host adapters. diff --git a/drivers/scsi/bnx2fc/Kconfig b/drivers/scsi/bnx2fc/Kconfig index f245d543d7b1..097882882649 100644 --- a/drivers/scsi/bnx2fc/Kconfig +++ b/drivers/scsi/bnx2fc/Kconfig @@ -1,11 +1,12 @@ config SCSI_BNX2X_FCOE tristate "QLogic NetXtreme II FCoE support" depends on PCI + depends on (IPV6 || IPV6=n) + depends on LIBFC + depends on LIBFCOE select NETDEVICES select ETHERNET select NET_VENDOR_BROADCOM - select LIBFC - select LIBFCOE select CNIC ---help--- This driver supports FCoE offload for the QLogic NetXtreme II diff --git a/drivers/scsi/bnx2i/Kconfig b/drivers/scsi/bnx2i/Kconfig index 44ce54e536e5..ba30ff86d581 100644 --- a/drivers/scsi/bnx2i/Kconfig +++ b/drivers/scsi/bnx2i/Kconfig @@ -2,6 +2,7 @@ config SCSI_BNX2_ISCSI tristate "QLogic NetXtreme II iSCSI support" depends on NET depends on PCI + depends on (IPV6 || IPV6=n) select SCSI_ISCSI_ATTRS select NETDEVICES select ETHERNET diff --git a/drivers/scsi/csiostor/Kconfig b/drivers/scsi/csiostor/Kconfig index 4d03b032aa10..7c7e5085968b 100644 --- a/drivers/scsi/csiostor/Kconfig +++ b/drivers/scsi/csiostor/Kconfig @@ -1,7 +1,7 @@ config SCSI_CHELSIO_FCOE tristate "Chelsio Communications FCoE support" depends on PCI && SCSI - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS select FW_LOADER help This driver supports FCoE Offload functionality over diff --git a/drivers/scsi/qla2xxx/Kconfig b/drivers/scsi/qla2xxx/Kconfig index 23d607218ae8..113e6c9826a1 100644 --- a/drivers/scsi/qla2xxx/Kconfig +++ b/drivers/scsi/qla2xxx/Kconfig @@ -1,7 +1,7 @@ config SCSI_QLA_FC tristate "QLogic QLA2XXX Fibre Channel Support" depends on PCI && SCSI - select SCSI_FC_ATTRS + depends on SCSI_FC_ATTRS select FW_LOADER ---help--- This qla2xxx driver supports all QLogic Fibre Channel @@ -31,7 +31,7 @@ config SCSI_QLA_FC config TCM_QLA2XXX tristate "TCM_QLA2XXX fabric module for Qlogic 2xxx series target mode HBAs" depends on SCSI_QLA_FC && TARGET_CORE - select LIBFC + depends on LIBFC select BTREE default n ---help--- diff --git a/fs/buffer.c b/fs/buffer.c index 8f05111bbb8b..3588a80854b2 100644 --- a/fs/buffer.c +++ b/fs/buffer.c @@ -1022,7 +1022,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, bh = page_buffers(page); if (bh->b_size == size) { end_block = init_page_buffers(page, bdev, - index << sizebits, size); + (sector_t)index << sizebits, + size); goto done; } if (!try_to_free_buffers(page)) @@ -1043,7 +1044,8 @@ grow_dev_page(struct block_device *bdev, sector_t block, */ spin_lock(&inode->i_mapping->private_lock); link_dev_buffers(page, bh); - end_block = init_page_buffers(page, bdev, index << sizebits, size); + end_block = init_page_buffers(page, bdev, (sector_t)index << sizebits, + size); spin_unlock(&inode->i_mapping->private_lock); done: ret = (block < end_block) ? 1 : -ENXIO; diff --git a/fs/cachefiles/namei.c b/fs/cachefiles/namei.c index 5bf2b41e66d3..83e9c94ca2cf 100644 --- a/fs/cachefiles/namei.c +++ b/fs/cachefiles/namei.c @@ -779,7 +779,8 @@ struct dentry *cachefiles_get_directory(struct cachefiles_cache *cache, !subdir->d_inode->i_op->lookup || !subdir->d_inode->i_op->mkdir || !subdir->d_inode->i_op->create || - !subdir->d_inode->i_op->rename || + (!subdir->d_inode->i_op->rename && + !subdir->d_inode->i_op->rename2) || !subdir->d_inode->i_op->rmdir || !subdir->d_inode->i_op->unlink) goto check_error; diff --git a/fs/cachefiles/rdwr.c b/fs/cachefiles/rdwr.c index 4b1fb5ca65b8..25e745b8eb1b 100644 --- a/fs/cachefiles/rdwr.c +++ b/fs/cachefiles/rdwr.c @@ -151,7 +151,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op) struct cachefiles_one_read *monitor; struct cachefiles_object *object; struct fscache_retrieval *op; - struct pagevec pagevec; int error, max; op = container_of(_op, struct fscache_retrieval, op); @@ -160,8 +159,6 @@ static void cachefiles_read_copier(struct fscache_operation *_op) _enter("{ino=%lu}", object->backer->d_inode->i_ino); - pagevec_init(&pagevec, 0); - max = 8; spin_lock_irq(&object->work_lock); @@ -396,7 +393,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, { struct cachefiles_object *object; struct cachefiles_cache *cache; - struct pagevec pagevec; struct inode *inode; sector_t block0, block; unsigned shift; @@ -427,8 +423,6 @@ int cachefiles_read_or_alloc_page(struct fscache_retrieval *op, op->op.flags |= FSCACHE_OP_ASYNC; op->op.processor = cachefiles_read_copier; - pagevec_init(&pagevec, 0); - /* we assume the absence or presence of the first block is a good * enough indication for the page as a whole * - TODO: don't use bmap() for this as it is _not_ actually good diff --git a/fs/fscache/object.c b/fs/fscache/object.c index d3b4539f1651..da032daf0e0d 100644 --- a/fs/fscache/object.c +++ b/fs/fscache/object.c @@ -982,6 +982,7 @@ nomem: submit_op_failed: clear_bit(FSCACHE_OBJECT_IS_LIVE, &object->flags); spin_unlock(&cookie->lock); + fscache_unuse_cookie(object); kfree(op); _leave(" [EIO]"); return transit_to(KILL_OBJECT); diff --git a/fs/fscache/page.c b/fs/fscache/page.c index 85332b9d19d1..de33b3fccca6 100644 --- a/fs/fscache/page.c +++ b/fs/fscache/page.c @@ -44,6 +44,19 @@ void __fscache_wait_on_page_write(struct fscache_cookie *cookie, struct page *pa EXPORT_SYMBOL(__fscache_wait_on_page_write); /* + * wait for a page to finish being written to the cache. Put a timeout here + * since we might be called recursively via parent fs. + */ +static +bool release_page_wait_timeout(struct fscache_cookie *cookie, struct page *page) +{ + wait_queue_head_t *wq = bit_waitqueue(&cookie->flags, 0); + + return wait_event_timeout(*wq, !__fscache_check_page_write(cookie, page), + HZ); +} + +/* * decide whether a page can be released, possibly by cancelling a store to it * - we're allowed to sleep if __GFP_WAIT is flagged */ @@ -115,7 +128,10 @@ page_busy: } fscache_stat(&fscache_n_store_vmscan_wait); - __fscache_wait_on_page_write(cookie, page); + if (!release_page_wait_timeout(cookie, page)) + _debug("fscache writeout timeout page: %p{%lx}", + page, page->index); + gfp &= ~__GFP_WAIT; goto try_again; } @@ -182,7 +198,7 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) { struct fscache_operation *op; struct fscache_object *object; - bool wake_cookie; + bool wake_cookie = false; _enter("%p", cookie); @@ -212,15 +228,16 @@ int __fscache_attr_changed(struct fscache_cookie *cookie) __fscache_use_cookie(cookie); if (fscache_submit_exclusive_op(object, op) < 0) - goto nobufs; + goto nobufs_dec; spin_unlock(&cookie->lock); fscache_stat(&fscache_n_attr_changed_ok); fscache_put_operation(op); _leave(" = 0"); return 0; -nobufs: +nobufs_dec: wake_cookie = __fscache_unuse_cookie(cookie); +nobufs: spin_unlock(&cookie->lock); kfree(op); if (wake_cookie) diff --git a/include/linux/mlx4/device.h b/include/linux/mlx4/device.h index 511c6e0d21a9..a5b7d7cfcedf 100644 --- a/include/linux/mlx4/device.h +++ b/include/linux/mlx4/device.h @@ -209,6 +209,7 @@ enum { MLX4_BMME_FLAG_TYPE_2_WIN = 1 << 9, MLX4_BMME_FLAG_RESERVED_LKEY = 1 << 10, MLX4_BMME_FLAG_FAST_REG_WR = 1 << 11, + MLX4_BMME_FLAG_VSD_INIT2RTR = 1 << 28, }; enum mlx4_event { diff --git a/include/linux/mlx4/qp.h b/include/linux/mlx4/qp.h index 7040dc98ff8b..5f4e36cf0091 100644 --- a/include/linux/mlx4/qp.h +++ b/include/linux/mlx4/qp.h @@ -56,7 +56,8 @@ enum mlx4_qp_optpar { MLX4_QP_OPTPAR_RNR_RETRY = 1 << 13, MLX4_QP_OPTPAR_ACK_TIMEOUT = 1 << 14, MLX4_QP_OPTPAR_SCHED_QUEUE = 1 << 16, - MLX4_QP_OPTPAR_COUNTER_INDEX = 1 << 20 + MLX4_QP_OPTPAR_COUNTER_INDEX = 1 << 20, + MLX4_QP_OPTPAR_VLAN_STRIPPING = 1 << 21, }; enum mlx4_qp_state { @@ -423,13 +424,20 @@ struct mlx4_wqe_inline_seg { enum mlx4_update_qp_attr { MLX4_UPDATE_QP_SMAC = 1 << 0, + MLX4_UPDATE_QP_VSD = 1 << 2, + MLX4_UPDATE_QP_SUPPORTED_ATTRS = (1 << 2) - 1 +}; + +enum mlx4_update_qp_params_flags { + MLX4_UPDATE_QP_PARAMS_FLAGS_VSD_ENABLE = 1 << 0, }; struct mlx4_update_qp_params { u8 smac_index; + u32 flags; }; -int mlx4_update_qp(struct mlx4_dev *dev, struct mlx4_qp *qp, +int mlx4_update_qp(struct mlx4_dev *dev, u32 qpn, enum mlx4_update_qp_attr attr, struct mlx4_update_qp_params *params); int mlx4_qp_modify(struct mlx4_dev *dev, struct mlx4_mtt *mtt, diff --git a/include/linux/workqueue.h b/include/linux/workqueue.h index a0cc2e95ed1b..b996e6cde6bb 100644 --- a/include/linux/workqueue.h +++ b/include/linux/workqueue.h @@ -419,7 +419,7 @@ __alloc_workqueue_key(const char *fmt, unsigned int flags, int max_active, alloc_workqueue("%s", WQ_FREEZABLE | WQ_UNBOUND | WQ_MEM_RECLAIM, \ 1, (name)) #define create_singlethread_workqueue(name) \ - alloc_workqueue("%s", WQ_UNBOUND | WQ_MEM_RECLAIM, 1, (name)) + alloc_ordered_workqueue("%s", WQ_MEM_RECLAIM, name) extern void destroy_workqueue(struct workqueue_struct *wq); diff --git a/include/net/addrconf.h b/include/net/addrconf.h index f679877bb601..ec51e673b4b6 100644 --- a/include/net/addrconf.h +++ b/include/net/addrconf.h @@ -204,6 +204,7 @@ void ipv6_sock_ac_close(struct sock *sk); int ipv6_dev_ac_inc(struct net_device *dev, const struct in6_addr *addr); int __ipv6_dev_ac_dec(struct inet6_dev *idev, const struct in6_addr *addr); +void ipv6_ac_destroy_dev(struct inet6_dev *idev); bool ipv6_chk_acast_addr(struct net *net, struct net_device *dev, const struct in6_addr *addr); bool ipv6_chk_acast_addr_src(struct net *net, struct net_device *dev, diff --git a/include/net/dst.h b/include/net/dst.h index 71c60f42be48..a8ae4e760778 100644 --- a/include/net/dst.h +++ b/include/net/dst.h @@ -480,6 +480,7 @@ void dst_init(void); /* Flags for xfrm_lookup flags argument. */ enum { XFRM_LOOKUP_ICMP = 1 << 0, + XFRM_LOOKUP_QUEUE = 1 << 1, }; struct flowi; @@ -490,7 +491,16 @@ static inline struct dst_entry *xfrm_lookup(struct net *net, int flags) { return dst_orig; -} +} + +static inline struct dst_entry *xfrm_lookup_route(struct net *net, + struct dst_entry *dst_orig, + const struct flowi *fl, + struct sock *sk, + int flags) +{ + return dst_orig; +} static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) { @@ -502,6 +512,10 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, const struct flowi *fl, struct sock *sk, int flags); +struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, + const struct flowi *fl, struct sock *sk, + int flags); + /* skb attached with this dst needs transformation if dst->xfrm is valid */ static inline struct xfrm_state *dst_xfrm(const struct dst_entry *dst) { diff --git a/include/net/genetlink.h b/include/net/genetlink.h index 93695f0e22a5..af10c2cf8a1d 100644 --- a/include/net/genetlink.h +++ b/include/net/genetlink.h @@ -394,4 +394,12 @@ static inline int genl_set_err(struct genl_family *family, struct net *net, return netlink_set_err(net->genl_sock, portid, group, code); } +static inline int genl_has_listeners(struct genl_family *family, + struct sock *sk, unsigned int group) +{ + if (WARN_ON_ONCE(group >= family->n_mcgrps)) + return -EINVAL; + group = family->mcgrp_offset + group; + return netlink_has_listeners(sk, group); +} #endif /* __NET_GENERIC_NETLINK_H */ diff --git a/include/net/sch_generic.h b/include/net/sch_generic.h index a3cfb8ebeb53..620e086c0cbe 100644 --- a/include/net/sch_generic.h +++ b/include/net/sch_generic.h @@ -231,7 +231,8 @@ struct qdisc_skb_cb { unsigned int pkt_len; u16 slave_dev_queue_mapping; u16 _pad; - unsigned char data[24]; +#define QDISC_CB_PRIV_LEN 20 + unsigned char data[QDISC_CB_PRIV_LEN]; }; static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz) diff --git a/include/rdma/ib_umem.h b/include/rdma/ib_umem.h index 1ea0b65c4cfb..a2bf41e0bde9 100644 --- a/include/rdma/ib_umem.h +++ b/include/rdma/ib_umem.h @@ -47,6 +47,7 @@ struct ib_umem { int writable; int hugetlb; struct work_struct work; + struct pid *pid; struct mm_struct *mm; unsigned long diff; struct sg_table sg_head; diff --git a/kernel/cgroup.c b/kernel/cgroup.c index 940aced4ed00..3a73f995a81e 100644 --- a/kernel/cgroup.c +++ b/kernel/cgroup.c @@ -3985,7 +3985,6 @@ static int pidlist_array_load(struct cgroup *cgrp, enum cgroup_filetype type, l = cgroup_pidlist_find_create(cgrp, type); if (!l) { - mutex_unlock(&cgrp->pidlist_mutex); pidlist_free(array); return -ENOMEM; } diff --git a/lib/rhashtable.c b/lib/rhashtable.c index a2c78810ebc1..7b36e4d40ed7 100644 --- a/lib/rhashtable.c +++ b/lib/rhashtable.c @@ -23,7 +23,6 @@ #include <linux/hash.h> #include <linux/random.h> #include <linux/rhashtable.h> -#include <linux/log2.h> #define HASH_DEFAULT_SIZE 64UL #define HASH_MIN_SIZE 4UL diff --git a/mm/memory.c b/mm/memory.c index adeac306610f..d17f1bcd2a91 100644 --- a/mm/memory.c +++ b/mm/memory.c @@ -118,6 +118,8 @@ __setup("norandmaps", disable_randmaps); unsigned long zero_pfn __read_mostly; unsigned long highest_memmap_pfn __read_mostly; +EXPORT_SYMBOL(zero_pfn); + /* * CONFIG_MMU architectures set up ZERO_PAGE in their paging_init() */ diff --git a/net/bridge/br_private.h b/net/bridge/br_private.h index 62a7fa2e3569..b6c04cbcfdc5 100644 --- a/net/bridge/br_private.h +++ b/net/bridge/br_private.h @@ -309,6 +309,9 @@ struct br_input_skb_cb { int igmp; int mrouters_only; #endif +#ifdef CONFIG_BRIDGE_VLAN_FILTERING + bool vlan_filtered; +#endif }; #define BR_INPUT_SKB_CB(__skb) ((struct br_input_skb_cb *)(__skb)->cb) diff --git a/net/bridge/br_vlan.c b/net/bridge/br_vlan.c index e1bcd653899b..3ba57fcdcd13 100644 --- a/net/bridge/br_vlan.c +++ b/net/bridge/br_vlan.c @@ -27,9 +27,13 @@ static void __vlan_add_flags(struct net_port_vlans *v, u16 vid, u16 flags) { if (flags & BRIDGE_VLAN_INFO_PVID) __vlan_add_pvid(v, vid); + else + __vlan_delete_pvid(v, vid); if (flags & BRIDGE_VLAN_INFO_UNTAGGED) set_bit(vid, v->untagged_bitmap); + else + clear_bit(vid, v->untagged_bitmap); } static int __vlan_add(struct net_port_vlans *v, u16 vid, u16 flags) @@ -125,7 +129,8 @@ struct sk_buff *br_handle_vlan(struct net_bridge *br, { u16 vid; - if (!br->vlan_enabled) + /* If this packet was not filtered at input, let it pass */ + if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) goto out; /* Vlan filter table must be configured at this point. The @@ -164,8 +169,10 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, /* If VLAN filtering is disabled on the bridge, all packets are * permitted. */ - if (!br->vlan_enabled) + if (!br->vlan_enabled) { + BR_INPUT_SKB_CB(skb)->vlan_filtered = false; return true; + } /* If there are no vlan in the permitted list, all packets are * rejected. @@ -173,6 +180,7 @@ bool br_allowed_ingress(struct net_bridge *br, struct net_port_vlans *v, if (!v) goto drop; + BR_INPUT_SKB_CB(skb)->vlan_filtered = true; proto = br->vlan_proto; /* If vlan tx offload is disabled on bridge device and frame was @@ -251,7 +259,8 @@ bool br_allowed_egress(struct net_bridge *br, { u16 vid; - if (!br->vlan_enabled) + /* If this packet was not filtered at input, let it pass */ + if (!BR_INPUT_SKB_CB(skb)->vlan_filtered) return true; if (!v) @@ -270,6 +279,7 @@ bool br_should_learn(struct net_bridge_port *p, struct sk_buff *skb, u16 *vid) struct net_bridge *br = p->br; struct net_port_vlans *v; + /* If filtering was disabled at input, let it pass. */ if (!br->vlan_enabled) return true; diff --git a/net/core/dev.c b/net/core/dev.c index ab9a16530c36..cf8a95f48cff 100644 --- a/net/core/dev.c +++ b/net/core/dev.c @@ -4809,9 +4809,14 @@ static void netdev_adjacent_sysfs_del(struct net_device *dev, sysfs_remove_link(&(dev->dev.kobj), linkname); } -#define netdev_adjacent_is_neigh_list(dev, dev_list) \ - (dev_list == &dev->adj_list.upper || \ - dev_list == &dev->adj_list.lower) +static inline bool netdev_adjacent_is_neigh_list(struct net_device *dev, + struct net_device *adj_dev, + struct list_head *dev_list) +{ + return (dev_list == &dev->adj_list.upper || + dev_list == &dev->adj_list.lower) && + net_eq(dev_net(dev), dev_net(adj_dev)); +} static int __netdev_adjacent_dev_insert(struct net_device *dev, struct net_device *adj_dev, @@ -4841,7 +4846,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, pr_debug("dev_hold for %s, because of link added from %s to %s\n", adj_dev->name, dev->name, adj_dev->name); - if (netdev_adjacent_is_neigh_list(dev, dev_list)) { + if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) { ret = netdev_adjacent_sysfs_add(dev, adj_dev, dev_list); if (ret) goto free_adj; @@ -4862,7 +4867,7 @@ static int __netdev_adjacent_dev_insert(struct net_device *dev, return 0; remove_symlinks: - if (netdev_adjacent_is_neigh_list(dev, dev_list)) + if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); free_adj: kfree(adj); @@ -4895,8 +4900,7 @@ static void __netdev_adjacent_dev_remove(struct net_device *dev, if (adj->master) sysfs_remove_link(&(dev->dev.kobj), "master"); - if (netdev_adjacent_is_neigh_list(dev, dev_list) && - net_eq(dev_net(dev),dev_net(adj_dev))) + if (netdev_adjacent_is_neigh_list(dev, adj_dev, dev_list)) netdev_adjacent_sysfs_del(dev, adj_dev->name, dev_list); list_del_rcu(&adj->list); diff --git a/net/core/sock.c b/net/core/sock.c index d372b4bd3f99..9c3f823e76a9 100644 --- a/net/core/sock.c +++ b/net/core/sock.c @@ -1866,7 +1866,7 @@ EXPORT_SYMBOL(sock_alloc_send_skb); * skb_page_frag_refill - check that a page_frag contains enough room * @sz: minimum size of the fragment we want to get * @pfrag: pointer to page_frag - * @prio: priority for memory allocation + * @gfp: priority for memory allocation * * Note: While this allocator tries to use high order pages, there is * no guarantee that allocations succeed. Therefore, @sz MUST be diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index afed1aac2638..bd41dd1948b6 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -79,10 +79,10 @@ static void __tunnel_dst_set(struct ip_tunnel_dst *idst, idst->saddr = saddr; } -static void tunnel_dst_set(struct ip_tunnel *t, +static noinline void tunnel_dst_set(struct ip_tunnel *t, struct dst_entry *dst, __be32 saddr) { - __tunnel_dst_set(this_cpu_ptr(t->dst_cache), dst, saddr); + __tunnel_dst_set(raw_cpu_ptr(t->dst_cache), dst, saddr); } static void tunnel_dst_reset(struct ip_tunnel *t) @@ -106,7 +106,7 @@ static struct rtable *tunnel_rtable_get(struct ip_tunnel *t, struct dst_entry *dst; rcu_read_lock(); - idst = this_cpu_ptr(t->dst_cache); + idst = raw_cpu_ptr(t->dst_cache); dst = rcu_dereference(idst->dst); if (dst && !atomic_inc_not_zero(&dst->__refcnt)) dst = NULL; diff --git a/net/ipv4/route.c b/net/ipv4/route.c index eaa4b000c7b4..173e7ea54c70 100644 --- a/net/ipv4/route.c +++ b/net/ipv4/route.c @@ -2265,9 +2265,9 @@ struct rtable *ip_route_output_flow(struct net *net, struct flowi4 *flp4, return rt; if (flp4->flowi4_proto) - rt = (struct rtable *) xfrm_lookup(net, &rt->dst, - flowi4_to_flowi(flp4), - sk, 0); + rt = (struct rtable *)xfrm_lookup_route(net, &rt->dst, + flowi4_to_flowi(flp4), + sk, 0); return rt; } diff --git a/net/ipv6/addrconf.c b/net/ipv6/addrconf.c index fc1fac2a0528..3342ee64f2e3 100644 --- a/net/ipv6/addrconf.c +++ b/net/ipv6/addrconf.c @@ -3094,11 +3094,13 @@ static int addrconf_ifdown(struct net_device *dev, int how) write_unlock_bh(&idev->lock); - /* Step 5: Discard multicast list */ - if (how) + /* Step 5: Discard anycast and multicast list */ + if (how) { + ipv6_ac_destroy_dev(idev); ipv6_mc_destroy_dev(idev); - else + } else { ipv6_mc_down(idev); + } idev->tstamp = jiffies; diff --git a/net/ipv6/anycast.c b/net/ipv6/anycast.c index ff2de7d9d8e6..9a386842fd62 100644 --- a/net/ipv6/anycast.c +++ b/net/ipv6/anycast.c @@ -351,6 +351,27 @@ static int ipv6_dev_ac_dec(struct net_device *dev, const struct in6_addr *addr) return __ipv6_dev_ac_dec(idev, addr); } +void ipv6_ac_destroy_dev(struct inet6_dev *idev) +{ + struct ifacaddr6 *aca; + + write_lock_bh(&idev->lock); + while ((aca = idev->ac_list) != NULL) { + idev->ac_list = aca->aca_next; + write_unlock_bh(&idev->lock); + + addrconf_leave_solict(idev, &aca->aca_addr); + + dst_hold(&aca->aca_rt->dst); + ip6_del_rt(aca->aca_rt); + + aca_put(aca); + + write_lock_bh(&idev->lock); + } + write_unlock_bh(&idev->lock); +} + /* * check if the interface has this anycast address * called with rcu_read_lock() diff --git a/net/ipv6/ip6_output.c b/net/ipv6/ip6_output.c index 315a55d66079..0a3448b2888f 100644 --- a/net/ipv6/ip6_output.c +++ b/net/ipv6/ip6_output.c @@ -1009,7 +1009,7 @@ struct dst_entry *ip6_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, if (final_dst) fl6->daddr = *final_dst; - return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); + return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); } EXPORT_SYMBOL_GPL(ip6_dst_lookup_flow); @@ -1041,7 +1041,7 @@ struct dst_entry *ip6_sk_dst_lookup_flow(struct sock *sk, struct flowi6 *fl6, if (final_dst) fl6->daddr = *final_dst; - return xfrm_lookup(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); + return xfrm_lookup_route(sock_net(sk), dst, flowi6_to_flowi(fl6), sk, 0); } EXPORT_SYMBOL_GPL(ip6_sk_dst_lookup_flow); diff --git a/net/mac80211/sta_info.c b/net/mac80211/sta_info.c index 441875f03750..a1e433b88c66 100644 --- a/net/mac80211/sta_info.c +++ b/net/mac80211/sta_info.c @@ -1822,7 +1822,7 @@ void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_PREAMBLE; if (sdata->vif.bss_conf.use_short_slot) sinfo->bss_param.flags |= BSS_PARAM_FLAGS_SHORT_SLOT_TIME; - sinfo->bss_param.dtim_period = sdata->local->hw.conf.ps_dtim_period; + sinfo->bss_param.dtim_period = sdata->vif.bss_conf.dtim_period; sinfo->bss_param.beacon_interval = sdata->vif.bss_conf.beacon_int; sinfo->sta_flags.set = 0; diff --git a/net/openvswitch/datapath.c b/net/openvswitch/datapath.c index 91d66b7e64ac..64dc864a417f 100644 --- a/net/openvswitch/datapath.c +++ b/net/openvswitch/datapath.c @@ -78,11 +78,12 @@ static const struct genl_multicast_group ovs_dp_vport_multicast_group = { /* Check if need to build a reply message. * OVS userspace sets the NLM_F_ECHO flag if it needs the reply. */ -static bool ovs_must_notify(struct genl_info *info, - const struct genl_multicast_group *grp) +static bool ovs_must_notify(struct genl_family *family, struct genl_info *info, + unsigned int group) { return info->nlhdr->nlmsg_flags & NLM_F_ECHO || - netlink_has_listeners(genl_info_net(info)->genl_sock, 0); + genl_has_listeners(family, genl_info_net(info)->genl_sock, + group); } static void ovs_notify(struct genl_family *family, @@ -763,7 +764,7 @@ static struct sk_buff *ovs_flow_cmd_alloc_info(const struct sw_flow_actions *act { struct sk_buff *skb; - if (!always && !ovs_must_notify(info, &ovs_dp_flow_multicast_group)) + if (!always && !ovs_must_notify(&dp_flow_genl_family, info, 0)) return NULL; skb = genlmsg_new_unicast(ovs_flow_cmd_msg_size(acts), info, GFP_KERNEL); diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c index 02a86a27fd84..5fa54dd78e25 100644 --- a/net/rfkill/rfkill-gpio.c +++ b/net/rfkill/rfkill-gpio.c @@ -163,6 +163,7 @@ static const struct acpi_device_id rfkill_acpi_match[] = { { "LNV4752", RFKILL_TYPE_GPS }, { }, }; +MODULE_DEVICE_TABLE(acpi, rfkill_acpi_match); #endif static struct platform_driver rfkill_gpio_driver = { diff --git a/net/rxrpc/ar-key.c b/net/rxrpc/ar-key.c index b45d080e64a7..1b24191167f1 100644 --- a/net/rxrpc/ar-key.c +++ b/net/rxrpc/ar-key.c @@ -1143,7 +1143,7 @@ static long rxrpc_read(const struct key *key, if (copy_to_user(xdr, (s), _l) != 0) \ goto fault; \ if (_l & 3 && \ - copy_to_user((u8 *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \ + copy_to_user((u8 __user *)xdr + _l, &zero, 4 - (_l & 3)) != 0) \ goto fault; \ xdr += (_l + 3) >> 2; \ } while(0) diff --git a/net/sched/sch_choke.c b/net/sched/sch_choke.c index ed30e436128b..fb666d1e4de3 100644 --- a/net/sched/sch_choke.c +++ b/net/sched/sch_choke.c @@ -133,10 +133,16 @@ static void choke_drop_by_idx(struct Qdisc *sch, unsigned int idx) --sch->q.qlen; } +/* private part of skb->cb[] that a qdisc is allowed to use + * is limited to QDISC_CB_PRIV_LEN bytes. + * As a flow key might be too large, we store a part of it only. + */ +#define CHOKE_K_LEN min_t(u32, sizeof(struct flow_keys), QDISC_CB_PRIV_LEN - 3) + struct choke_skb_cb { u16 classid; u8 keys_valid; - struct flow_keys keys; + u8 keys[QDISC_CB_PRIV_LEN - 3]; }; static inline struct choke_skb_cb *choke_skb_cb(const struct sk_buff *skb) @@ -163,22 +169,26 @@ static u16 choke_get_classid(const struct sk_buff *skb) static bool choke_match_flow(struct sk_buff *skb1, struct sk_buff *skb2) { + struct flow_keys temp; + if (skb1->protocol != skb2->protocol) return false; if (!choke_skb_cb(skb1)->keys_valid) { choke_skb_cb(skb1)->keys_valid = 1; - skb_flow_dissect(skb1, &choke_skb_cb(skb1)->keys); + skb_flow_dissect(skb1, &temp); + memcpy(&choke_skb_cb(skb1)->keys, &temp, CHOKE_K_LEN); } if (!choke_skb_cb(skb2)->keys_valid) { choke_skb_cb(skb2)->keys_valid = 1; - skb_flow_dissect(skb2, &choke_skb_cb(skb2)->keys); + skb_flow_dissect(skb2, &temp); + memcpy(&choke_skb_cb(skb2)->keys, &temp, CHOKE_K_LEN); } return !memcmp(&choke_skb_cb(skb1)->keys, &choke_skb_cb(skb2)->keys, - sizeof(struct flow_keys)); + CHOKE_K_LEN); } /* diff --git a/net/socket.c b/net/socket.c index 2e2586e2dee1..4cdbc107606f 100644 --- a/net/socket.c +++ b/net/socket.c @@ -1996,6 +1996,9 @@ static int copy_msghdr_from_user(struct msghdr *kmsg, if (copy_from_user(kmsg, umsg, sizeof(struct msghdr))) return -EFAULT; + if (kmsg->msg_name == NULL) + kmsg->msg_namelen = 0; + if (kmsg->msg_namelen < 0) return -EINVAL; diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index df7b1332a1ec..7257164af91b 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c @@ -6969,6 +6969,9 @@ void __cfg80211_send_event_skb(struct sk_buff *skb, gfp_t gfp) struct nlattr *data = ((void **)skb->cb)[2]; enum nl80211_multicast_groups mcgrp = NL80211_MCGRP_TESTMODE; + /* clear CB data for netlink core to own from now on */ + memset(skb->cb, 0, sizeof(skb->cb)); + nla_nest_end(skb, data); genlmsg_end(skb, hdr); @@ -9294,6 +9297,9 @@ int cfg80211_vendor_cmd_reply(struct sk_buff *skb) void *hdr = ((void **)skb->cb)[1]; struct nlattr *data = ((void **)skb->cb)[2]; + /* clear CB data for netlink core to own from now on */ + memset(skb->cb, 0, sizeof(skb->cb)); + if (WARN_ON(!rdev->cur_cmd_info)) { kfree_skb(skb); return -EINVAL; diff --git a/net/xfrm/xfrm_policy.c b/net/xfrm/xfrm_policy.c index beeed602aeb3..fdde51f4271a 100644 --- a/net/xfrm/xfrm_policy.c +++ b/net/xfrm/xfrm_policy.c @@ -39,6 +39,11 @@ #define XFRM_QUEUE_TMO_MAX ((unsigned)(60*HZ)) #define XFRM_MAX_QUEUE_LEN 100 +struct xfrm_flo { + struct dst_entry *dst_orig; + u8 flags; +}; + static DEFINE_SPINLOCK(xfrm_policy_afinfo_lock); static struct xfrm_policy_afinfo __rcu *xfrm_policy_afinfo[NPROTO] __read_mostly; @@ -1877,13 +1882,14 @@ static int xdst_queue_output(struct sock *sk, struct sk_buff *skb) } static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, - struct dst_entry *dst, + struct xfrm_flo *xflo, const struct flowi *fl, int num_xfrms, u16 family) { int err; struct net_device *dev; + struct dst_entry *dst; struct dst_entry *dst1; struct xfrm_dst *xdst; @@ -1891,9 +1897,12 @@ static struct xfrm_dst *xfrm_create_dummy_bundle(struct net *net, if (IS_ERR(xdst)) return xdst; - if (net->xfrm.sysctl_larval_drop || num_xfrms <= 0) + if (!(xflo->flags & XFRM_LOOKUP_QUEUE) || + net->xfrm.sysctl_larval_drop || + num_xfrms <= 0) return xdst; + dst = xflo->dst_orig; dst1 = &xdst->u.dst; dst_hold(dst); xdst->route = dst; @@ -1935,7 +1944,7 @@ static struct flow_cache_object * xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, struct flow_cache_object *oldflo, void *ctx) { - struct dst_entry *dst_orig = (struct dst_entry *)ctx; + struct xfrm_flo *xflo = (struct xfrm_flo *)ctx; struct xfrm_policy *pols[XFRM_POLICY_TYPE_MAX]; struct xfrm_dst *xdst, *new_xdst; int num_pols = 0, num_xfrms = 0, i, err, pol_dead; @@ -1976,7 +1985,8 @@ xfrm_bundle_lookup(struct net *net, const struct flowi *fl, u16 family, u8 dir, goto make_dummy_bundle; } - new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, dst_orig); + new_xdst = xfrm_resolve_and_create_bundle(pols, num_pols, fl, family, + xflo->dst_orig); if (IS_ERR(new_xdst)) { err = PTR_ERR(new_xdst); if (err != -EAGAIN) @@ -2010,7 +2020,7 @@ make_dummy_bundle: /* We found policies, but there's no bundles to instantiate: * either because the policy blocks, has no transformations or * we could not build template (no xfrm_states).*/ - xdst = xfrm_create_dummy_bundle(net, dst_orig, fl, num_xfrms, family); + xdst = xfrm_create_dummy_bundle(net, xflo, fl, num_xfrms, family); if (IS_ERR(xdst)) { xfrm_pols_put(pols, num_pols); return ERR_CAST(xdst); @@ -2104,13 +2114,18 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, } if (xdst == NULL) { + struct xfrm_flo xflo; + + xflo.dst_orig = dst_orig; + xflo.flags = flags; + /* To accelerate a bit... */ if ((dst_orig->flags & DST_NOXFRM) || !net->xfrm.policy_count[XFRM_POLICY_OUT]) goto nopol; flo = flow_cache_lookup(net, fl, family, dir, - xfrm_bundle_lookup, dst_orig); + xfrm_bundle_lookup, &xflo); if (flo == NULL) goto nopol; if (IS_ERR(flo)) { @@ -2138,7 +2153,7 @@ struct dst_entry *xfrm_lookup(struct net *net, struct dst_entry *dst_orig, xfrm_pols_put(pols, drop_pols); XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTNOSTATES); - return make_blackhole(net, family, dst_orig); + return ERR_PTR(-EREMOTE); } err = -EAGAIN; @@ -2195,6 +2210,23 @@ dropdst: } EXPORT_SYMBOL(xfrm_lookup); +/* Callers of xfrm_lookup_route() must ensure a call to dst_output(). + * Otherwise we may send out blackholed packets. + */ +struct dst_entry *xfrm_lookup_route(struct net *net, struct dst_entry *dst_orig, + const struct flowi *fl, + struct sock *sk, int flags) +{ + struct dst_entry *dst = xfrm_lookup(net, dst_orig, fl, sk, + flags | XFRM_LOOKUP_QUEUE); + + if (IS_ERR(dst) && PTR_ERR(dst) == -EREMOTE) + return make_blackhole(net, dst_orig->ops->family, dst_orig); + + return dst; +} +EXPORT_SYMBOL(xfrm_lookup_route); + static inline int xfrm_secpath_reject(int idx, struct sk_buff *skb, const struct flowi *fl) { @@ -2460,7 +2492,7 @@ int __xfrm_route_forward(struct sk_buff *skb, unsigned short family) skb_dst_force(skb); - dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, 0); + dst = xfrm_lookup(net, skb_dst(skb), &fl, NULL, XFRM_LOOKUP_QUEUE); if (IS_ERR(dst)) { res = 0; dst = NULL; diff --git a/sound/core/pcm_lib.c b/sound/core/pcm_lib.c index 9acc77eae487..0032278567ad 100644 --- a/sound/core/pcm_lib.c +++ b/sound/core/pcm_lib.c @@ -1782,14 +1782,16 @@ static int snd_pcm_lib_ioctl_fifo_size(struct snd_pcm_substream *substream, { struct snd_pcm_hw_params *params = arg; snd_pcm_format_t format; - int channels, width; + int channels; + ssize_t frame_size; params->fifo_size = substream->runtime->hw.fifo_size; if (!(substream->runtime->hw.info & SNDRV_PCM_INFO_FIFO_IN_FRAMES)) { format = params_format(params); channels = params_channels(params); - width = snd_pcm_format_physical_width(format); - params->fifo_size /= width * channels; + frame_size = snd_pcm_format_size(format, channels); + if (frame_size > 0) + params->fifo_size /= (unsigned)frame_size; } return 0; } diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 6e5d0cb4e3d7..47ccb8f44adb 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c @@ -777,6 +777,7 @@ static const struct hda_model_fixup cxt5066_fixup_models[] = { { .id = CXT_PINCFG_LENOVO_TP410, .name = "tp410" }, { .id = CXT_FIXUP_THINKPAD_ACPI, .name = "thinkpad" }, { .id = CXT_PINCFG_LEMOTE_A1004, .name = "lemote-a1004" }, + { .id = CXT_PINCFG_LEMOTE_A1205, .name = "lemote-a1205" }, { .id = CXT_FIXUP_OLPC_XO, .name = "olpc-xo" }, {} }; diff --git a/sound/usb/caiaq/control.c b/sound/usb/caiaq/control.c index f65fc0987cfb..b7a7c805d63f 100644 --- a/sound/usb/caiaq/control.c +++ b/sound/usb/caiaq/control.c @@ -100,15 +100,19 @@ static int control_put(struct snd_kcontrol *kcontrol, struct snd_usb_caiaqdev *cdev = caiaqdev(chip->card); int pos = kcontrol->private_value; int v = ucontrol->value.integer.value[0]; - unsigned char cmd = EP1_CMD_WRITE_IO; + unsigned char cmd; - if (cdev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1)) - cmd = EP1_CMD_DIMM_LEDS; - - if (cdev->chip.usb_id == - USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER)) + switch (cdev->chip.usb_id) { + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_MASCHINECONTROLLER): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_TRAKTORKONTROLX1): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER2): + case USB_ID(USB_VID_NATIVEINSTRUMENTS, USB_PID_KORECONTROLLER): cmd = EP1_CMD_DIMM_LEDS; + break; + default: + cmd = EP1_CMD_WRITE_IO; + break; + } if (pos & CNT_INTVAL) { int i = pos & ~CNT_INTVAL; diff --git a/virt/kvm/arm/vgic-v2.c b/virt/kvm/arm/vgic-v2.c index 01124ef3690a..416baedfc89f 100644 --- a/virt/kvm/arm/vgic-v2.c +++ b/virt/kvm/arm/vgic-v2.c @@ -71,7 +71,7 @@ static void vgic_v2_sync_lr_elrsr(struct kvm_vcpu *vcpu, int lr, struct vgic_lr lr_desc) { if (!(lr_desc.state & LR_STATE_MASK)) - set_bit(lr, (unsigned long *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr); + __set_bit(lr, (unsigned long *)vcpu->arch.vgic_cpu.vgic_v2.vgic_elrsr); } static u64 vgic_v2_get_elrsr(const struct kvm_vcpu *vcpu) diff --git a/virt/kvm/kvm_main.c b/virt/kvm/kvm_main.c index 33712fb26eb1..95519bc959ed 100644 --- a/virt/kvm/kvm_main.c +++ b/virt/kvm/kvm_main.c @@ -110,7 +110,7 @@ static bool largepages_enabled = true; bool kvm_is_mmio_pfn(pfn_t pfn) { if (pfn_valid(pfn)) - return PageReserved(pfn_to_page(pfn)); + return !is_zero_pfn(pfn) && PageReserved(pfn_to_page(pfn)); return true; } @@ -1725,7 +1725,7 @@ int kvm_vcpu_yield_to(struct kvm_vcpu *target) rcu_read_lock(); pid = rcu_dereference(target->pid); if (pid) - task = get_pid_task(target->pid, PIDTYPE_PID); + task = get_pid_task(pid, PIDTYPE_PID); rcu_read_unlock(); if (!task) return ret; |