Merge tag 'spdx_identifiers-4.14-rc8' of git://git.kernel.org/pub/scm/linux/kernel...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Nov 2017 17:04:46 +0000 (10:04 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 2 Nov 2017 17:04:46 +0000 (10:04 -0700)
Pull initial SPDX identifiers from Greg KH:
 "License cleanup: add SPDX license identifiers to some files

  Many source files in the tree are missing licensing information, which
  makes it harder for compliance tools to determine the correct license.

  By default all files without license information are under the default
  license of the kernel, which is GPL version 2.

  Update the files which contain no license information with the
  'GPL-2.0' SPDX license identifier. The SPDX identifier is a legally
  binding shorthand, which can be used instead of the full boiler plate
  text.

  This patch is based on work done by Thomas Gleixner and Kate Stewart
  and Philippe Ombredanne.

  How this work was done:

  Patches were generated and checked against linux-4.14-rc6 for a subset
  of the use cases:

   - file had no licensing information it it.

   - file was a */uapi/* one with no licensing information in it,

   - file was a */uapi/* one with existing licensing information,

  Further patches will be generated in subsequent months to fix up cases
  where non-standard license headers were used, and references to
  license had to be inferred by heuristics based on keywords.

  The analysis to determine which SPDX License Identifier to be applied
  to a file was done in a spreadsheet of side by side results from of
  the output of two independent scanners (ScanCode & Windriver)
  producing SPDX tag:value files created by Philippe Ombredanne.
  Philippe prepared the base worksheet, and did an initial spot review
  of a few 1000 files.

  The 4.13 kernel was the starting point of the analysis with 60,537
  files assessed. Kate Stewart did a file by file comparison of the
  scanner results in the spreadsheet to determine which SPDX license
  identifier(s) to be applied to the file. She confirmed any
  determination that was not immediately clear with lawyers working with
  the Linux Foundation.

  Criteria used to select files for SPDX license identifier tagging was:

   - Files considered eligible had to be source code files.

   - Make and config files were included as candidates if they contained
     >5 lines of source

   - File already had some variant of a license header in it (even if <5
     lines).

  All documentation files were explicitly excluded.

  The following heuristics were used to determine which SPDX license
  identifiers to apply.

   - when both scanners couldn't find any license traces, file was
     considered to have no license information in it, and the top level
     COPYING file license applied.

     For non */uapi/* files that summary was:

       SPDX license identifier                            # files
       ---------------------------------------------------|-------
       GPL-2.0                                              11139

     and resulted in the first patch in this series.

     If that file was a */uapi/* path one, it was "GPL-2.0 WITH
     Linux-syscall-note" otherwise it was "GPL-2.0". Results of that
     was:

       SPDX license identifier                            # files
       ---------------------------------------------------|-------
       GPL-2.0 WITH Linux-syscall-note                        930

     and resulted in the second patch in this series.

   - if a file had some form of licensing information in it, and was one
     of the */uapi/* ones, it was denoted with the Linux-syscall-note if
     any GPL family license was found in the file or had no licensing in
     it (per prior point). Results summary:

       SPDX license identifier                            # files
       ---------------------------------------------------|------
       GPL-2.0 WITH Linux-syscall-note                       270
       GPL-2.0+ WITH Linux-syscall-note                      169
       ((GPL-2.0 WITH Linux-syscall-note) OR BSD-2-Clause)    21
       ((GPL-2.0 WITH Linux-syscall-note) OR BSD-3-Clause)    17
       LGPL-2.1+ WITH Linux-syscall-note                      15
       GPL-1.0+ WITH Linux-syscall-note                       14
       ((GPL-2.0+ WITH Linux-syscall-note) OR BSD-3-Clause)    5
       LGPL-2.0+ WITH Linux-syscall-note                       4
       LGPL-2.1 WITH Linux-syscall-note                        3
       ((GPL-2.0 WITH Linux-syscall-note) OR MIT)              3
       ((GPL-2.0 WITH Linux-syscall-note) AND MIT)             1

     and that resulted in the third patch in this series.

   - when the two scanners agreed on the detected license(s), that
     became the concluded license(s).

   - when there was disagreement between the two scanners (one detected
     a license but the other didn't, or they both detected different
     licenses) a manual inspection of the file occurred.

   - In most cases a manual inspection of the information in the file
     resulted in a clear resolution of the license that should apply
     (and which scanner probably needed to revisit its heuristics).

   - When it was not immediately clear, the license identifier was
     confirmed with lawyers working with the Linux Foundation.

   - If there was any question as to the appropriate license identifier,
     the file was flagged for further research and to be revisited later
     in time.

  In total, over 70 hours of logged manual review was done on the
  spreadsheet to determine the SPDX license identifiers to apply to the
  source files by Kate, Philippe, Thomas and, in some cases,
  confirmation by lawyers working with the Linux Foundation.

  Kate also obtained a third independent scan of the 4.13 code base from
  FOSSology, and compared selected files where the other two scanners
  disagreed against that SPDX file, to see if there was new insights.
  The Windriver scanner is based on an older version of FOSSology in
  part, so they are related.

  Thomas did random spot checks in about 500 files from the spreadsheets
  for the uapi headers and agreed with SPDX license identifier in the
  files he inspected. For the non-uapi files Thomas did random spot
  checks in about 15000 files.

  In initial set of patches against 4.14-rc6, 3 files were found to have
  copy/paste license identifier errors, and have been fixed to reflect
  the correct identifier.

  Additionally Philippe spent 10 hours this week doing a detailed manual
  inspection and review of the 12,461 patched files from the initial
  patch version early this week with:

   - a full scancode scan run, collecting the matched texts, detected
     license ids and scores

   - reviewing anything where there was a license detected (about 500+
     files) to ensure that the applied SPDX license was correct

   - reviewing anything where there was no detection but the patch
     license was not GPL-2.0 WITH Linux-syscall-note to ensure that the
     applied SPDX license was correct

  This produced a worksheet with 20 files needing minor correction. This
  worksheet was then exported into 3 different .csv files for the
  different types of files to be modified.

  These .csv files were then reviewed by Greg. Thomas wrote a script to
  parse the csv files and add the proper SPDX tag to the file, in the
  format that the file expected. This script was further refined by Greg
  based on the output to detect more types of files automatically and to
  distinguish between header and source .c files (which need different
  comment types.) Finally Greg ran the script using the .csv files to
  generate the patches.

Reviewed-by: Kate Stewart <kstewart@linuxfoundation.org>
Reviewed-by: Philippe Ombredanne <pombredanne@nexb.com>
Reviewed-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>"
* tag 'spdx_identifiers-4.14-rc8' of git://git.kernel.org/pub/scm/linux/kernel/git/gregkh/driver-core:
  License cleanup: add SPDX license identifier to uapi header files with a license
  License cleanup: add SPDX license identifier to uapi header files with no license
  License cleanup: add SPDX GPL-2.0 license identifier to files with no license

237 files changed:
Documentation/kbuild/makefiles.txt
MAINTAINERS
Makefile
arch/alpha/kernel/sys_alcor.c
arch/alpha/kernel/sys_cabriolet.c
arch/alpha/kernel/sys_dp264.c
arch/alpha/kernel/sys_eb64p.c
arch/alpha/kernel/sys_eiger.c
arch/alpha/kernel/sys_miata.c
arch/alpha/kernel/sys_mikasa.c
arch/alpha/kernel/sys_nautilus.c
arch/alpha/kernel/sys_noritake.c
arch/alpha/kernel/sys_rawhide.c
arch/alpha/kernel/sys_ruffian.c
arch/alpha/kernel/sys_rx164.c
arch/alpha/kernel/sys_sable.c
arch/alpha/kernel/sys_sio.c
arch/alpha/kernel/sys_sx164.c
arch/alpha/kernel/sys_takara.c
arch/alpha/kernel/sys_wildfire.c
arch/arc/boot/dts/hsdk.dts
arch/arc/configs/hsdk_defconfig
arch/arc/kernel/smp.c
arch/arc/plat-hsdk/Kconfig
arch/arc/plat-hsdk/platform.c
arch/arm/xen/p2m.c
arch/powerpc/kvm/book3s_64_vio.c
arch/powerpc/kvm/book3s_hv_rmhandlers.S
arch/powerpc/kvm/powerpc.c
arch/s390/kernel/entry.S
arch/x86/crypto/chacha20-avx2-x86_64.S
arch/x86/crypto/chacha20-ssse3-x86_64.S
arch/x86/entry/entry_64.S
arch/x86/events/intel/bts.c
arch/x86/include/asm/io.h
arch/x86/kernel/amd_nb.c
arch/x86/kernel/unwind_orc.c
arch/x86/mm/fault.c
arch/x86/mm/mmap.c
drivers/block/nbd.c
drivers/block/virtio_blk.c
drivers/firmware/efi/libstub/arm-stub.c
drivers/firmware/efi/test/efi_test.c
drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c
drivers/gpu/drm/amd/powerplay/hwmgr/smu7_hwmgr.c
drivers/gpu/drm/i915/gvt/cmd_parser.c
drivers/gpu/drm/i915/gvt/execlist.c
drivers/gpu/drm/i915/gvt/handlers.c
drivers/gpu/drm/i915/gvt/reg.h
drivers/gpu/drm/i915/gvt/scheduler.h
drivers/gpu/drm/i915/i915_perf.c
drivers/hwmon/da9052-hwmon.c
drivers/hwmon/tmp102.c
drivers/ide/ide-cd.c
drivers/infiniband/core/netlink.c
drivers/infiniband/core/nldev.c
drivers/input/mouse/elan_i2c_core.c
drivers/input/rmi4/rmi_f30.c
drivers/input/tablet/gtco.c
drivers/mmc/host/renesas_sdhi_internal_dmac.c
drivers/mmc/host/tmio_mmc_core.c
drivers/net/can/sun4i_can.c
drivers/net/can/usb/kvaser_usb.c
drivers/net/ethernet/hisilicon/hns/hns_enet.c
drivers/net/ethernet/intel/e1000/e1000_ethtool.c
drivers/net/ethernet/intel/e1000/e1000_main.c
drivers/net/ethernet/intel/i40e/i40e_txrx.c
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/ixgbe/ixgbe_main.c
drivers/net/ethernet/marvell/mvpp2.c
drivers/net/ethernet/mellanox/mlx5/core/dev.c
drivers/net/ethernet/mellanox/mlx5/core/en_dcbnl.c
drivers/net/ethernet/mellanox/mlx5/core/en_tc.c
drivers/net/ethernet/mellanox/mlx5/core/health.c
drivers/net/ethernet/mellanox/mlx5/core/port.c
drivers/net/ethernet/mellanox/mlxsw/i2c.c
drivers/net/ethernet/mellanox/mlxsw/reg.h
drivers/net/ethernet/netronome/nfp/flower/action.c
drivers/net/ethernet/stmicro/stmmac/dwmac-dwc-qos-eth.c
drivers/net/ethernet/stmicro/stmmac/stmmac_platform.c
drivers/net/ipvlan/ipvtap.c
drivers/net/macvtap.c
drivers/net/phy/marvell.c
drivers/net/tap.c
drivers/net/tun.c
drivers/net/usb/cdc_ether.c
drivers/net/usb/r8152.c
drivers/net/wan/lapbether.c
drivers/net/wireless/ath/ath10k/htt_rx.c
drivers/net/wireless/ath/ath10k/rx_desc.h
drivers/net/wireless/ath/wcn36xx/main.c
drivers/nvme/host/core.c
drivers/nvme/host/fc.c
drivers/nvme/host/rdma.c
drivers/nvme/target/core.c
drivers/nvme/target/nvmet.h
drivers/pinctrl/pinctrl-amd.c
drivers/pinctrl/pinctrl-mcp23s08.c
drivers/platform/x86/intel_pmc_ipc.c
drivers/regulator/axp20x-regulator.c
drivers/regulator/rn5t618-regulator.c
drivers/s390/scsi/zfcp_aux.c
drivers/s390/scsi/zfcp_erp.c
drivers/s390/scsi/zfcp_scsi.c
drivers/scsi/aacraid/comminit.c
drivers/scsi/aacraid/linit.c
drivers/scsi/hpsa.c
drivers/scsi/qla2xxx/qla_os.c
drivers/scsi/scsi_lib.c
drivers/scsi/sg.c
drivers/spi/spi-armada-3700.c
drivers/spi/spi-bcm-qspi.c
drivers/spi/spi-stm32.c
drivers/spi/spi.c
drivers/xen/gntdev.c
drivers/xen/xen-balloon.c
fs/ceph/caps.c
fs/cifs/Kconfig
fs/cifs/cifsglob.h
fs/cifs/dir.c
fs/cifs/smb2maperror.c
fs/cifs/smb2ops.c
fs/cifs/smb2pdu.c
fs/cifs/smb2pdu.h
fs/cifs/smb2proto.h
fs/cifs/smb2transport.c
fs/fuse/dir.c
fs/overlayfs/inode.c
fs/overlayfs/namei.c
fs/overlayfs/overlayfs.h
fs/overlayfs/readdir.c
fs/overlayfs/super.c
fs/xfs/xfs_file.c
include/linux/if_tap.h
include/linux/mlx5/port.h
include/linux/sctp.h
include/linux/swait.h
include/net/fq_impl.h
include/net/inet_sock.h
include/net/pkt_cls.h
include/net/sch_generic.h
include/net/sctp/sm.h
include/net/sctp/ulpevent.h
include/net/strparser.h
include/net/tcp.h
include/uapi/linux/bpf.h
include/uapi/linux/sctp.h
include/uapi/linux/spi/spidev.h
init/Kconfig
kernel/bpf/sockmap.c
kernel/futex.c
kernel/signal.c
kernel/workqueue.c
lib/asn1_decoder.c
lib/assoc_array.c
lib/ioremap.c
net/core/filter.c
net/dccp/ipv4.c
net/dsa/dsa2.c
net/ife/ife.c
net/ipv4/inet_connection_sock.c
net/ipv4/ipip.c
net/ipv4/tcp_ipv4.c
net/ipv4/tcp_output.c
net/ipv6/addrconf.c
net/ipv6/ip6_gre.c
net/l2tp/l2tp_ppp.c
net/mac80211/cfg.c
net/mac80211/key.c
net/psample/psample.c
net/rds/ib_send.c
net/sched/act_sample.c
net/sched/cls_api.c
net/sched/cls_basic.c
net/sched/cls_bpf.c
net/sched/cls_cgroup.c
net/sched/cls_flow.c
net/sched/cls_flower.c
net/sched/cls_fw.c
net/sched/cls_matchall.c
net/sched/cls_route.c
net/sched/cls_rsvp.h
net/sched/cls_tcindex.c
net/sched/cls_u32.c
net/sched/sch_api.c
net/sctp/input.c
net/sctp/ipv6.c
net/sctp/sm_make_chunk.c
net/sctp/sm_sideeffect.c
net/sctp/socket.c
net/sctp/stream.c
net/sctp/ulpevent.c
net/strparser/strparser.c
net/sunrpc/xprt.c
net/unix/diag.c
net/wireless/sme.c
net/xfrm/xfrm_output.c
net/xfrm/xfrm_policy.c
net/xfrm/xfrm_state.c
net/xfrm/xfrm_user.c
samples/trace_events/trace-events-sample.c
scripts/Makefile.modpost
security/apparmor/.gitignore
security/apparmor/Makefile
security/apparmor/apparmorfs.c
security/apparmor/file.c
security/apparmor/include/audit.h
security/apparmor/include/net.h [deleted file]
security/apparmor/include/perms.h
security/apparmor/include/policy.h
security/apparmor/lib.c
security/apparmor/lsm.c
security/apparmor/net.c [deleted file]
security/apparmor/policy_unpack.c
security/keys/keyring.c
security/keys/trusted.c
sound/core/seq/seq_clientmgr.c
sound/core/timer_compat.c
sound/pci/hda/patch_realtek.c
sound/soc/codecs/adau17x1.c
sound/soc/codecs/adau17x1.h
sound/soc/codecs/rt5514-spi.c
sound/soc/codecs/rt5514-spi.h
sound/soc/codecs/rt5514.c
sound/soc/codecs/rt5514.h
sound/soc/codecs/rt5616.c
sound/soc/codecs/rt5659.c
sound/soc/codecs/rt5663.c
sound/soc/soc-topology.c
tools/include/uapi/linux/bpf.h
tools/power/cpupower/Makefile
tools/scripts/Makefile.include
tools/testing/selftests/lib.mk
tools/testing/selftests/tc-testing/tc-tests/filters/tests.json
tools/testing/selftests/tc-testing/tdc.py
tools/testing/selftests/tc-testing/tdc_batch.py [new file with mode: 0755]
tools/testing/selftests/tc-testing/tdc_config.py

index 329e740adea70db91ac2c9cd9f671f79ca58790e..f6f80380dff2fa0851c5ae02de27497e9bc9c0df 100644 (file)
@@ -1108,14 +1108,6 @@ When kbuild executes, the following steps are followed (roughly):
     ld
        Link target. Often, LDFLAGS_$@ is used to set specific options to ld.
 
-    objcopy
-       Copy binary. Uses OBJCOPYFLAGS usually specified in
-       arch/$(ARCH)/Makefile.
-       OBJCOPYFLAGS_$@ may be used to set additional options.
-
-    gzip
-       Compress target. Use maximum compression to compress target.
-
        Example:
                #arch/x86/boot/Makefile
                LDFLAGS_bootsect := -Ttext 0x0 -s --oformat binary
@@ -1139,6 +1131,19 @@ When kbuild executes, the following steps are followed (roughly):
              resulting in the target file being recompiled for no
              obvious reason.
 
+    objcopy
+       Copy binary. Uses OBJCOPYFLAGS usually specified in
+       arch/$(ARCH)/Makefile.
+       OBJCOPYFLAGS_$@ may be used to set additional options.
+
+    gzip
+       Compress target. Use maximum compression to compress target.
+
+       Example:
+               #arch/x86/boot/compressed/Makefile
+               $(obj)/vmlinux.bin.gz: $(vmlinux.bin.all-y) FORCE
+                       $(call if_changed,gzip)
+
     dtc
        Create flattened device tree blob object suitable for linking
        into vmlinux. Device tree blobs linked into vmlinux are placed
@@ -1219,7 +1224,7 @@ When kbuild executes, the following steps are followed (roughly):
        that may be shared between individual architectures.
        The recommended approach how to use a generic header file is
        to list the file in the Kbuild file.
-       See "7.3 generic-y" for further info on syntax etc.
+       See "7.2 generic-y" for further info on syntax etc.
 
 --- 6.11 Post-link pass
 
@@ -1254,13 +1259,13 @@ A Kbuild file may be defined under arch/<arch>/include/uapi/asm/ and
 arch/<arch>/include/asm/ to list asm files coming from asm-generic.
 See subsequent chapter for the syntax of the Kbuild file.
 
-       --- 7.1 no-export-headers
+--- 7.1 no-export-headers
 
        no-export-headers is essentially used by include/uapi/linux/Kbuild to
        avoid exporting specific headers (e.g. kvm.h) on architectures that do
        not support it. It should be avoided as much as possible.
 
-       --- 7.2 generic-y
+--- 7.2 generic-y
 
        If an architecture uses a verbatim copy of a header from
        include/asm-generic then this is listed in the file
@@ -1287,7 +1292,7 @@ See subsequent chapter for the syntax of the Kbuild file.
                Example: termios.h
                        #include <asm-generic/termios.h>
 
-       --- 7.3 generated-y
+--- 7.3 generated-y
 
        If an architecture generates other header files alongside generic-y
        wrappers, generated-y specifies them.
@@ -1299,7 +1304,7 @@ See subsequent chapter for the syntax of the Kbuild file.
                        #arch/x86/include/asm/Kbuild
                        generated-y += syscalls_32.h
 
-       --- 7.5 mandatory-y
+--- 7.4 mandatory-y
 
        mandatory-y is essentially used by include/uapi/asm-generic/Kbuild.asm
        to define the minimum set of headers that must be exported in
index d85c08956875e54b1273e29577bdd9af824b04ec..bf1d20695cbf8bce4380626dfda323279cd5877f 100644 (file)
@@ -6671,7 +6671,7 @@ F:        include/net/ieee802154_netdev.h
 F:     Documentation/networking/ieee802154.txt
 
 IFE PROTOCOL
-M:     Yotam Gigi <yotamg@mellanox.com>
+M:     Yotam Gigi <yotam.gi@gmail.com>
 M:     Jamal Hadi Salim <jhs@mojatatu.com>
 F:     net/ife
 F:     include/net/ife.h
@@ -8743,7 +8743,7 @@ Q:        http://patchwork.ozlabs.org/project/netdev/list/
 F:     drivers/net/ethernet/mellanox/mlxsw/
 
 MELLANOX FIRMWARE FLASH LIBRARY (mlxfw)
-M:     Yotam Gigi <yotamg@mellanox.com>
+M:     mlxsw@mellanox.com
 L:     netdev@vger.kernel.org
 S:     Supported
 W:     http://www.mellanox.com
@@ -10179,7 +10179,6 @@ F:      Documentation/parport*.txt
 
 PARAVIRT_OPS INTERFACE
 M:     Juergen Gross <jgross@suse.com>
-M:     Chris Wright <chrisw@sous-sol.org>
 M:     Alok Kataria <akataria@vmware.com>
 M:     Rusty Russell <rusty@rustcorp.com.au>
 L:     virtualization@lists.linux-foundation.org
@@ -10891,7 +10890,7 @@ S:      Maintained
 F:     drivers/block/ps3vram.c
 
 PSAMPLE PACKET SAMPLING SUPPORT:
-M:     Yotam Gigi <yotamg@mellanox.com>
+M:     Yotam Gigi <yotam.gi@gmail.com>
 S:     Maintained
 F:     net/psample
 F:     include/net/psample.h
index 4d1dcce4fbb95b16b42c003d416122a8e83473b1..3a8868ee967e69ef0fbbb101f58ce4c00d40db0c 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 4
 PATCHLEVEL = 14
 SUBLEVEL = 0
-EXTRAVERSION = -rc6
+EXTRAVERSION = -rc7
 NAME = Fearless Coyote
 
 # *DOCUMENTATION*
@@ -131,8 +131,8 @@ endif
 ifneq ($(KBUILD_OUTPUT),)
 # check that the output directory actually exists
 saved-output := $(KBUILD_OUTPUT)
-$(shell [ -d $(KBUILD_OUTPUT) ] || mkdir -p $(KBUILD_OUTPUT))
-KBUILD_OUTPUT := $(realpath $(KBUILD_OUTPUT))
+KBUILD_OUTPUT := $(shell mkdir -p $(KBUILD_OUTPUT) && cd $(KBUILD_OUTPUT) \
+                                                               && /bin/pwd)
 $(if $(KBUILD_OUTPUT),, \
      $(error failed to create output directory "$(saved-output)"))
 
@@ -698,11 +698,11 @@ KBUILD_CFLAGS += $(stackp-flag)
 
 ifeq ($(cc-name),clang)
 ifneq ($(CROSS_COMPILE),)
-CLANG_TARGET   := -target $(notdir $(CROSS_COMPILE:%-=%))
+CLANG_TARGET   := --target=$(notdir $(CROSS_COMPILE:%-=%))
 GCC_TOOLCHAIN  := $(realpath $(dir $(shell which $(LD)))/..)
 endif
 ifneq ($(GCC_TOOLCHAIN),)
-CLANG_GCC_TC   := -gcc-toolchain $(GCC_TOOLCHAIN)
+CLANG_GCC_TC   := --gcc-toolchain=$(GCC_TOOLCHAIN)
 endif
 KBUILD_CFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
 KBUILD_AFLAGS += $(CLANG_TARGET) $(CLANG_GCC_TC)
@@ -1400,7 +1400,7 @@ help:
        @echo  '                    Build, install, and boot kernel before'
        @echo  '                    running kselftest on it'
        @echo  '  kselftest-clean - Remove all generated kselftest files'
-       @echo  '  kselftest-merge - Merge all the config dependencies of kselftest to existed'
+       @echo  '  kselftest-merge - Merge all the config dependencies of kselftest to existing'
        @echo  '                    .config.'
        @echo  ''
        @echo 'Userspace tools targets:'
index dabb0d205c40ddb15fb5f49926b49c2face755e0..e56efd5b855fed163d93d96a7ed5b2c4c5a5b361 100644 (file)
@@ -182,10 +182,10 @@ alcor_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 alcor_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[7][5] __initdata = {
+       static char irq_tab[7][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                /* note: IDSEL 17 is XLT only */
                {16+13, 16+13, 16+13, 16+13, 16+13},    /* IdSel 17,  TULIP  */
index b8687dadd0387f6985d93425209ca2fa1487035b..10bc46a4ec40b29fb2207d77f572dc6779d40dc0 100644 (file)
@@ -174,10 +174,10 @@ pc164_init_irq(void)
  * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
  */
 
-static inline int __init
+static inline int
 eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT  INTA  INTB  INTC   INTD */
                {16+0, 16+0, 16+5,  16+9, 16+13},  /* IdSel 6,  slot 0, J25 */
                {16+1, 16+1, 16+6, 16+10, 16+14},  /* IdSel 7,  slot 1, J26 */
@@ -204,10 +204,10 @@ eb66p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
  * because it is the Saturn IO (SIO) PCI/ISA Bridge Chip.
  */
 
-static inline int __init
+static inline int
 cabriolet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT   INTA  INTB  INTC   INTD */
                { 16+2, 16+2, 16+7, 16+11, 16+15}, /* IdSel 5,  slot 2, J21 */
                { 16+0, 16+0, 16+5,  16+9, 16+13}, /* IdSel 6,  slot 0, J19 */
@@ -288,10 +288,10 @@ cia_cab_init_pci(void)
  * 
  */
 
-static inline int __init
+static inline int
 alphapc164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[7][5] __initdata = {
+       static char irq_tab[7][5] = {
                /*INT   INTA  INTB   INTC   INTD */
                { 16+2, 16+2, 16+9,  16+13, 16+17}, /* IdSel  5, slot 2, J20 */
                { 16+0, 16+0, 16+7,  16+11, 16+15}, /* IdSel  6, slot 0, J29 */
index 3d816947de135975056d660910e0bdf97dc4d6e8..d335086218207d9327df05499ded58ea2b4deeff 100644 (file)
@@ -357,7 +357,7 @@ clipper_init_irq(void)
  *  10  64 bit PCI option slot 3 (not bus 0)
  */
 
-static int __init
+static int
 isa_irq_fixup(const struct pci_dev *dev, int irq)
 {
        u8 irq8;
@@ -373,10 +373,10 @@ isa_irq_fixup(const struct pci_dev *dev, int irq)
        return irq8 & 0xf;
 }
 
-static int __init
+static int
 dp264_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[6][5] __initdata = {
+       static char irq_tab[6][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 5 ISA Bridge */
                { 16+ 3, 16+ 3, 16+ 2, 16+ 2, 16+ 2}, /* IdSel 6 SCSI builtin*/
@@ -395,10 +395,10 @@ dp264_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return isa_irq_fixup(dev, irq);
 }
 
-static int __init
+static int
 monet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[13][5] __initdata = {
+       static char irq_tab[13][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {    45,    45,    45,    45,    45}, /* IdSel 3 21143 PCI1 */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 4 unused */
@@ -424,7 +424,7 @@ monet_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
 }
 
-static u8 __init
+static u8
 monet_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        struct pci_controller *hose = dev->sysdata;
@@ -457,10 +457,10 @@ monet_swizzle(struct pci_dev *dev, u8 *pinp)
        return slot;
 }
 
-static int __init
+static int
 webbrick_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[13][5] __initdata = {
+       static char irq_tab[13][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 7 ISA Bridge */
                {    -1,    -1,    -1,    -1,    -1}, /* IdSel 8 unused */
@@ -479,10 +479,10 @@ webbrick_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return isa_irq_fixup(dev, COMMON_TABLE_LOOKUP);
 }
 
-static int __init
+static int
 clipper_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[7][5] __initdata = {
+       static char irq_tab[7][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 16+ 8, 16+ 8, 16+ 9, 16+10, 16+11}, /* IdSel 1 slot 1 */
                { 16+12, 16+12, 16+13, 16+14, 16+15}, /* IdSel 2 slot 2 */
index 59fd789dfc8066880cf85dda7fce7deed6e012a1..5251937ec1b469129ae16088c57248846482d61e 100644 (file)
@@ -168,10 +168,10 @@ eb64p_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 eb64p_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT  INTA  INTB  INTC   INTD */
                {16+7, 16+7, 16+7, 16+7,  16+7},  /* IdSel 5,  slot ?, ?? */
                {16+0, 16+0, 16+2, 16+4,  16+9},  /* IdSel 6,  slot ?, ?? */
index 3c8c36d954480d8387f4ad91baef7173a6120c29..016f79251141a547f47f1c98c0bfc13c1ca98851 100644 (file)
@@ -142,7 +142,7 @@ eiger_init_irq(void)
        }
 }
 
-static int __init
+static int
 eiger_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        u8 irq_orig;
@@ -159,7 +159,7 @@ eiger_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return irq_orig - 0x80;
 }
 
-static u8 __init
+static u8
 eiger_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        struct pci_controller *hose = dev->sysdata;
index d20337768606dae25d8b653244a2b1ba76d88bfd..6fa07dc5339d2c70f4c969d7a77bc7246772a49b 100644 (file)
@@ -150,10 +150,10 @@ miata_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-        static char irq_tab[18][5] __initdata = {
+        static char irq_tab[18][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {16+ 8, 16+ 8, 16+ 8, 16+ 8, 16+ 8},  /* IdSel 14,  DC21142 */
                {   -1,    -1,    -1,    -1,    -1},  /* IdSel 15,  EIDE    */
@@ -197,7 +197,7 @@ miata_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 miata_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index 68b7d0c63b8dd40388f675c571bf21a03005257f..3af4f94113e1701e6729b2932a8055b3c6902201 100644 (file)
@@ -146,10 +146,10 @@ mikasa_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 mikasa_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[8][5] __initdata = {
+       static char irq_tab[8][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {16+12, 16+12, 16+12, 16+12, 16+12},    /* IdSel 17,  SCSI */
                {   -1,    -1,    -1,    -1,    -1},    /* IdSel 18,  PCEB */
index cefa225ab47826245f2cb80f3738eaac39149872..239dc0e601d536ab05d08c83dfebfcc02567a405 100644 (file)
@@ -63,7 +63,7 @@ nautilus_init_irq(void)
        common_init_isa_dma();
 }
 
-static int __init
+static int
 nautilus_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /* Preserve the IRQ set up by the console.  */
index 1f2e8b1faa9a789088165602910214f6482ea361..b106f327f765268541a6f4f29033eda9f3898328 100644 (file)
@@ -194,10 +194,10 @@ noritake_init_irq(void)
  * comes in on.  This makes interrupt processing much easier.
  */
 
-static int __init
+static int
 noritake_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[15][5] __initdata = {
+       static char irq_tab[15][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                /* note: IDSELs 16, 17, and 25 are CORELLE only */
                { 16+1,  16+1,  16+1,  16+1,  16+1},  /* IdSel 16,  QLOGIC */
@@ -222,7 +222,7 @@ noritake_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 noritake_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index b21e572c1299032a112e6c8031c7360ed65f5b78..b76f65d0e8b54f51e3874116ebd37e4223c33bb5 100644 (file)
@@ -222,10 +222,10 @@ rawhide_init_irq(void)
  * 
  */
 
-static int __init
+static int
 rawhide_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 16+16, 16+16, 16+16, 16+16, 16+16}, /* IdSel 1 SCSI PCI 1 */
                { 16+ 0, 16+ 0, 16+ 1, 16+ 2, 16+ 3}, /* IdSel 2 slot 2 */
index 197660ba686f9551cc8ff6a25a204a9d0b2f295d..07830cccabf995b098f203e90ec5728f9e39b62e 100644 (file)
@@ -118,10 +118,10 @@ ruffian_kill_arch (int mode)
  *
  */
 
-static int __init
+static int
 ruffian_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-        static char irq_tab[11][5] __initdata = {
+        static char irq_tab[11][5] = {
              /*INT  INTA INTB INTC INTD */
                {-1,  -1,  -1,  -1,  -1},  /* IdSel 13,  21052       */
                {-1,  -1,  -1,  -1,  -1},  /* IdSel 14,  SIO         */
@@ -140,7 +140,7 @@ ruffian_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 ruffian_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index b09146e4a08de0c07fef4081db5ec06c8fa6e9eb..a3db719d3c3873d788f42b50d6ba03367f5ae134 100644 (file)
@@ -143,7 +143,7 @@ rx164_init_irq(void)
  * 
  */
 
-static int __init
+static int
 rx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
 #if 0
@@ -157,7 +157,7 @@ rx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
          { 16+1, 16+1, 16+6, 16+11, 16+16},      /* IdSel 10, slot 4 */
        };
 #else
-       static char irq_tab[6][5] __initdata = {
+       static char irq_tab[6][5] = {
          /*INT   INTA  INTB  INTC   INTD */
          { 16+0, 16+0, 16+6, 16+11, 16+16},      /* IdSel 5,  slot 0 */
          { 16+1, 16+1, 16+7, 16+12, 16+17},      /* IdSel 6,  slot 1 */
index 76eb2afca575ccd6ad4f54aa7b7095ffcf0f939d..3cf0d32da5d80adf41c4357a927bda5617e933c1 100644 (file)
@@ -193,10 +193,10 @@ sable_init_irq(void)
  * with the values in the irq swizzling tables above.
  */
 
-static int __init
+static int
 sable_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[9][5] __initdata = {
+       static char irq_tab[9][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 32+0,  32+0,  32+0,  32+0,  32+0},  /* IdSel 0,  TULIP  */
                { 32+1,  32+1,  32+1,  32+1,  32+1},  /* IdSel 1,  SCSI   */
@@ -375,10 +375,10 @@ lynx_init_irq(void)
  * with the values in the irq swizzling tables above.
  */
 
-static int __init
+static int
 lynx_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[19][5] __initdata = {
+       static char irq_tab[19][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                {   -1,    -1,    -1,    -1,    -1},  /* IdSel 13,  PCEB   */
                {   -1,    -1,    -1,    -1,    -1},  /* IdSel 14,  PPB    */
@@ -405,7 +405,7 @@ lynx_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 lynx_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot, pin = *pinp;
index b44b1cb923f36cc62be8f005bd30d9739a81eb45..37bd6d9b8eb9633ba398c81be1744694abdf021c 100644 (file)
@@ -145,7 +145,7 @@ sio_fixup_irq_levels(unsigned int level_bits)
        outb((level_bits >> 8) & 0xff, 0x4d1);
 }
 
-static inline int __init
+static inline int
 noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        /*
@@ -166,7 +166,7 @@ noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
         * that they use the default INTA line, if they are interrupt
         * driven at all).
         */
-       static char irq_tab[][5] __initdata = {
+       static char irq_tab[][5] = {
                /*INT A   B   C   D */
                { 3,  3,  3,  3,  3}, /* idsel  6 (53c810) */ 
                {-1, -1, -1, -1, -1}, /* idsel  7 (SIO: PCI/ISA bridge) */
@@ -184,10 +184,10 @@ noname_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return irq >= 0 ? tmp : -1;
 }
 
-static inline int __init
+static inline int
 p2k_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[][5] __initdata = {
+       static char irq_tab[][5] = {
                /*INT A   B   C   D */
                { 0,  0, -1, -1, -1}, /* idsel  6 (53c810) */
                {-1, -1, -1, -1, -1}, /* idsel  7 (SIO: PCI/ISA bridge) */
index 6c92f25172fff5be62de0e441e8c1d288864859e..1ec638a2746a055ea6ca6d0560b035b727c19f1e 100644 (file)
@@ -95,10 +95,10 @@ sx164_init_irq(void)
  *   9  32 bit PCI option slot 3
  */
 
-static int __init
+static int
 sx164_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[5][5] __initdata = {
+       static char irq_tab[5][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { 16+ 9, 16+ 9, 16+13, 16+17, 16+21}, /* IdSel 5 slot 2 J17 */
                { 16+11, 16+11, 16+15, 16+19, 16+23}, /* IdSel 6 slot 0 J19 */
index b0913e61416c7ab3fa8f80ec401ea910610bf9ba..e230c68640883e3733059a99e3dfc7c83140677a 100644 (file)
@@ -156,10 +156,10 @@ takara_init_irq(void)
  * assign it whatever the hell IRQ we like and it doesn't matter.
  */
 
-static int __init
+static int
 takara_map_irq_srm(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[15][5] __initdata = {
+       static char irq_tab[15][5] = {
                { 16+3, 16+3, 16+3, 16+3, 16+3},   /* slot  6 == device 3 */
                { 16+2, 16+2, 16+2, 16+2, 16+2},   /* slot  7 == device 2 */
                { 16+1, 16+1, 16+1, 16+1, 16+1},   /* slot  8 == device 1 */
@@ -211,7 +211,7 @@ takara_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
        return COMMON_TABLE_LOOKUP;
 }
 
-static u8 __init
+static u8
 takara_swizzle(struct pci_dev *dev, u8 *pinp)
 {
        int slot = PCI_SLOT(dev->devfn);
index 8290274dec11d6a164630aaab111fab8343e80a0..8e64052811abc7701a89e56ac7fb660a84096729 100644 (file)
@@ -289,10 +289,10 @@ wildfire_device_interrupt(unsigned long vector)
  *   7  64 bit PCI 1 option slot 7
  */
 
-static int __init
+static int
 wildfire_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
-       static char irq_tab[8][5] __initdata = {
+       static char irq_tab[8][5] = {
                /*INT    INTA   INTB   INTC   INTD */
                { -1,    -1,    -1,    -1,    -1}, /* IdSel 0 ISA Bridge */
                { 36,    36,    36+1, 36+2, 36+3}, /* IdSel 1 SCSI builtin */
index 8adde1b492f14e833279ff75f448b7c0bb350781..8f627c200d609148c55731aac99b2a353e72f126 100644 (file)
                        /*
                         * DW sdio controller has external ciu clock divider
                         * controlled via register in SDIO IP. Due to its
-                        * unexpected default value (it should devide by 1
-                        * but it devides by 8) SDIO IP uses wrong clock and
+                        * unexpected default value (it should divide by 1
+                        * but it divides by 8) SDIO IP uses wrong clock and
                         * works unstable (see STAR 9001204800)
+                        * We switched to the minimum possible value of the
+                        * divisor (div-by-2) in HSDK platform code.
                         * So add temporary fix and change clock frequency
-                        * from 100000000 to 12500000 Hz until we fix dw sdio
-                        * driver itself.
+                        * to 50000000 Hz until we fix dw sdio driver itself.
                         */
-                       clock-frequency = <12500000>;
+                       clock-frequency = <50000000>;
                        #clock-cells = <0>;
                };
 
index 15f0f6b5fec1ae6f8e0c1bfb4fa6c970915e1713..7b8f8faf8a24315d3379d189cab69506539e04a8 100644 (file)
@@ -63,7 +63,6 @@ CONFIG_MMC_SDHCI=y
 CONFIG_MMC_SDHCI_PLTFM=y
 CONFIG_MMC_DW=y
 # CONFIG_IOMMU_SUPPORT is not set
-CONFIG_RESET_HSDK=y
 CONFIG_EXT3_FS=y
 CONFIG_VFAT_FS=y
 CONFIG_TMPFS=y
index f46267153ec2e971bb4b81e2513835d2ee2be635..6df9d94a953763eca43b20f02f1897308ab1ee7a 100644 (file)
@@ -23,6 +23,8 @@
 #include <linux/cpumask.h>
 #include <linux/reboot.h>
 #include <linux/irqdomain.h>
+#include <linux/export.h>
+
 #include <asm/processor.h>
 #include <asm/setup.h>
 #include <asm/mach_desc.h>
@@ -30,6 +32,9 @@
 #ifndef CONFIG_ARC_HAS_LLSC
 arch_spinlock_t smp_atomic_ops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
 arch_spinlock_t smp_bitops_lock = __ARCH_SPIN_LOCK_UNLOCKED;
+
+EXPORT_SYMBOL_GPL(smp_atomic_ops_lock);
+EXPORT_SYMBOL_GPL(smp_bitops_lock);
 #endif
 
 struct plat_smp_ops  __weak plat_smp_ops;
index bd08de4be75e7edc4ce8875c8af7f1723f0f5b01..19ab3cf98f0f34904b8431a6d4cf36642066c513 100644 (file)
@@ -8,3 +8,4 @@
 menuconfig ARC_SOC_HSDK
        bool "ARC HS Development Kit SOC"
        select CLK_HSDK
+       select RESET_HSDK
index 744e62e5878898b21f49c58c588ddb167523cc60..fd0ae5e38639a8756c86d7882c6e74c88f0e07e5 100644 (file)
@@ -74,6 +74,10 @@ static void __init hsdk_set_cpu_freq_1ghz(void)
                pr_err("Failed to setup CPU frequency to 1GHz!");
 }
 
+#define SDIO_BASE              (ARC_PERIPHERAL_BASE + 0xA000)
+#define SDIO_UHS_REG_EXT       (SDIO_BASE + 0x108)
+#define SDIO_UHS_REG_EXT_DIV_2 (2 << 30)
+
 static void __init hsdk_init_early(void)
 {
        /*
@@ -89,6 +93,12 @@ static void __init hsdk_init_early(void)
        /* Really apply settings made above */
        writel(1, (void __iomem *) CREG_PAE_UPDATE);
 
+       /*
+        * Switch SDIO external ciu clock divider from default div-by-8 to
+        * minimum possible div-by-2.
+        */
+       iowrite32(SDIO_UHS_REG_EXT_DIV_2, (void __iomem *) SDIO_UHS_REG_EXT);
+
        /*
         * Setup CPU frequency to 1GHz.
         * TODO: remove it after smart hsdk pll driver will be introduced.
index e71eefa2e427bf2703ba7f6c7fb7a6577d8ab390..0641ba54ab62ae9786cb12ab88b2666b5c783b7a 100644 (file)
@@ -1,7 +1,7 @@
 #include <linux/bootmem.h>
 #include <linux/gfp.h>
 #include <linux/export.h>
-#include <linux/rwlock.h>
+#include <linux/spinlock.h>
 #include <linux/slab.h>
 #include <linux/types.h>
 #include <linux/dma-mapping.h>
index 8f2da8bba737b066488a5c0b3909a02ede239ba6..4dffa611376d67850ac4ef8730a547fcccf63491 100644 (file)
@@ -478,28 +478,30 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
                return ret;
 
        dir = iommu_tce_direction(tce);
+
+       idx = srcu_read_lock(&vcpu->kvm->srcu);
+
        if ((dir != DMA_NONE) && kvmppc_gpa_to_ua(vcpu->kvm,
-                       tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), &ua, NULL))
-               return H_PARAMETER;
+                       tce & ~(TCE_PCI_READ | TCE_PCI_WRITE), &ua, NULL)) {
+               ret = H_PARAMETER;
+               goto unlock_exit;
+       }
 
        entry = ioba >> stt->page_shift;
 
        list_for_each_entry_lockless(stit, &stt->iommu_tables, next) {
-               if (dir == DMA_NONE) {
+               if (dir == DMA_NONE)
                        ret = kvmppc_tce_iommu_unmap(vcpu->kvm,
                                        stit->tbl, entry);
-               } else {
-                       idx = srcu_read_lock(&vcpu->kvm->srcu);
+               else
                        ret = kvmppc_tce_iommu_map(vcpu->kvm, stit->tbl,
                                        entry, ua, dir);
-                       srcu_read_unlock(&vcpu->kvm->srcu, idx);
-               }
 
                if (ret == H_SUCCESS)
                        continue;
 
                if (ret == H_TOO_HARD)
-                       return ret;
+                       goto unlock_exit;
 
                WARN_ON_ONCE(1);
                kvmppc_clear_tce(stit->tbl, entry);
@@ -507,7 +509,10 @@ long kvmppc_h_put_tce(struct kvm_vcpu *vcpu, unsigned long liobn,
 
        kvmppc_tce_put(stt, entry, tce);
 
-       return H_SUCCESS;
+unlock_exit:
+       srcu_read_unlock(&vcpu->kvm->srcu, idx);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(kvmppc_h_put_tce);
 
index ec69fa45d5a2f249322d32218a722f4d54390e97..42639fba89e881c12e0d9ba5af3bfa1139565688 100644 (file)
@@ -989,13 +989,14 @@ ALT_FTR_SECTION_END_IFCLR(CPU_FTR_ARCH_300)
        beq     no_xive
        ld      r11, VCPU_XIVE_SAVED_STATE(r4)
        li      r9, TM_QW1_OS
-       stdcix  r11,r9,r10
        eieio
+       stdcix  r11,r9,r10
        lwz     r11, VCPU_XIVE_CAM_WORD(r4)
        li      r9, TM_QW1_OS + TM_WORD2
        stwcix  r11,r9,r10
        li      r9, 1
        stw     r9, VCPU_XIVE_PUSHED(r4)
+       eieio
 no_xive:
 #endif /* CONFIG_KVM_XICS */
 
@@ -1310,6 +1311,7 @@ END_FTR_SECTION_IFSET(CPU_FTR_HAS_PPR)
        bne     3f
 BEGIN_FTR_SECTION
        PPC_MSGSYNC
+       lwsync
 END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        lbz     r0, HSTATE_HOST_IPI(r13)
        cmpwi   r0, 0
@@ -1400,8 +1402,8 @@ guest_exit_cont:          /* r9 = vcpu, r12 = trap, r13 = paca */
        cmpldi  cr0, r10, 0
        beq     1f
        /* First load to pull the context, we ignore the value */
-       lwzx    r11, r7, r10
        eieio
+       lwzx    r11, r7, r10
        /* Second load to recover the context state (Words 0 and 1) */
        ldx     r11, r6, r10
        b       3f
@@ -1409,8 +1411,8 @@ guest_exit_cont:          /* r9 = vcpu, r12 = trap, r13 = paca */
        cmpldi  cr0, r10, 0
        beq     1f
        /* First load to pull the context, we ignore the value */
-       lwzcix  r11, r7, r10
        eieio
+       lwzcix  r11, r7, r10
        /* Second load to recover the context state (Words 0 and 1) */
        ldcix   r11, r6, r10
 3:     std     r11, VCPU_XIVE_SAVED_STATE(r9)
@@ -1420,6 +1422,7 @@ guest_exit_cont:          /* r9 = vcpu, r12 = trap, r13 = paca */
        stw     r10, VCPU_XIVE_PUSHED(r9)
        stb     r10, (VCPU_XIVE_SAVED_STATE+3)(r9)
        stb     r0, (VCPU_XIVE_SAVED_STATE+4)(r9)
+       eieio
 1:
 #endif /* CONFIG_KVM_XICS */
        /* Save more register state  */
@@ -2788,6 +2791,10 @@ END_FTR_SECTION_IFSET(CPU_FTR_ARCH_207S)
        PPC_MSGCLR(6)
        /* see if it's a host IPI */
        li      r3, 1
+BEGIN_FTR_SECTION
+       PPC_MSGSYNC
+       lwsync
+END_FTR_SECTION_IFSET(CPU_FTR_ARCH_300)
        lbz     r0, HSTATE_HOST_IPI(r13)
        cmpwi   r0, 0
        bnelr
index 3480faaf1ef886118ba1ee26389ea25c4c3d8a69..ee279c7f48021e0b43c658d7529b9160061b5415 100644 (file)
@@ -644,8 +644,7 @@ int kvm_vm_ioctl_check_extension(struct kvm *kvm, long ext)
                break;
 #endif
        case KVM_CAP_PPC_HTM:
-               r = cpu_has_feature(CPU_FTR_TM_COMP) &&
-                   is_kvmppc_hv_enabled(kvm);
+               r = cpu_has_feature(CPU_FTR_TM_COMP) && hv_enabled;
                break;
        default:
                r = 0;
index c41adce6062cbeabc4f6e49881c57398fa733131..7c6904d616d877330ae5768a9ad348e298a1562e 100644 (file)
@@ -522,12 +522,15 @@ ENTRY(pgm_check_handler)
        tmhh    %r8,0x0001              # test problem state bit
        jnz     2f                      # -> fault in user space
 #if IS_ENABLED(CONFIG_KVM)
-       # cleanup critical section for sie64a
+       # cleanup critical section for program checks in sie64a
        lgr     %r14,%r9
        slg     %r14,BASED(.Lsie_critical_start)
        clg     %r14,BASED(.Lsie_critical_length)
        jhe     0f
-       brasl   %r14,.Lcleanup_sie
+       lg      %r14,__SF_EMPTY(%r15)           # get control block pointer
+       ni      __SIE_PROG0C+3(%r14),0xfe       # no longer in SIE
+       lctlg   %c1,%c1,__LC_USER_ASCE          # load primary asce
+       larl    %r9,sie_exit                    # skip forward to sie_exit
 #endif
 0:     tmhh    %r8,0x4000              # PER bit set in old PSW ?
        jnz     1f                      # -> enabled, can't be a double fault
index 3a2dc3dc6cac162bc51946bb08cf8da745c73f57..f3cd26f4833254cb0966f31a1afae8c5c9fc95a4 100644 (file)
@@ -45,7 +45,7 @@ ENTRY(chacha20_8block_xor_avx2)
 
        vzeroupper
        # 4 * 32 byte stack, 32-byte aligned
-       mov             %rsp, %r8
+       lea             8(%rsp),%r10
        and             $~31, %rsp
        sub             $0x80, %rsp
 
@@ -443,6 +443,6 @@ ENTRY(chacha20_8block_xor_avx2)
        vmovdqu         %ymm15,0x01e0(%rsi)
 
        vzeroupper
-       mov             %r8,%rsp
+       lea             -8(%r10),%rsp
        ret
 ENDPROC(chacha20_8block_xor_avx2)
index 3f511a7d73b897e2ea4560b6a5b2809c5e450255..512a2b500fd1813d1ffc4d74053ec137ecf865c5 100644 (file)
@@ -160,7 +160,7 @@ ENTRY(chacha20_4block_xor_ssse3)
        # done with the slightly better performing SSSE3 byte shuffling,
        # 7/12-bit word rotation uses traditional shift+OR.
 
-       mov             %rsp,%r11
+       lea             8(%rsp),%r10
        sub             $0x80,%rsp
        and             $~63,%rsp
 
@@ -625,6 +625,6 @@ ENTRY(chacha20_4block_xor_ssse3)
        pxor            %xmm1,%xmm15
        movdqu          %xmm15,0xf0(%rsi)
 
-       mov             %r11,%rsp
+       lea             -8(%r10),%rsp
        ret
 ENDPROC(chacha20_4block_xor_ssse3)
index 4b1ad51eb7ccab509d4fdfe4def31498fe9f20a4..bcfc5668dcb22f303b21c7a636273c46274835c5 100644 (file)
@@ -809,7 +809,7 @@ apicinterrupt IRQ_WORK_VECTOR                       irq_work_interrupt              smp_irq_work_interrupt
 
 .macro idtentry sym do_sym has_error_code:req paranoid=0 shift_ist=-1
 ENTRY(\sym)
-       UNWIND_HINT_IRET_REGS offset=8
+       UNWIND_HINT_IRET_REGS offset=\has_error_code*8
 
        /* Sanity check */
        .if \shift_ist != -1 && \paranoid == 0
index 16076eb34699691ce8d150ae82fc93b34d46b895..141e07b0621689e745582599c009f4af1d053c6c 100644 (file)
@@ -546,9 +546,6 @@ static int bts_event_init(struct perf_event *event)
        if (event->attr.type != bts_pmu.type)
                return -ENOENT;
 
-       if (x86_add_exclusive(x86_lbr_exclusive_bts))
-               return -EBUSY;
-
        /*
         * BTS leaks kernel addresses even when CPL0 tracing is
         * disabled, so disallow intel_bts driver for unprivileged
@@ -562,6 +559,9 @@ static int bts_event_init(struct perf_event *event)
            !capable(CAP_SYS_ADMIN))
                return -EACCES;
 
+       if (x86_add_exclusive(x86_lbr_exclusive_bts))
+               return -EBUSY;
+
        ret = x86_reserve_hardware();
        if (ret) {
                x86_del_exclusive(x86_lbr_exclusive_bts);
index efb6c17ca902c563f19190df8c91d44dc72498e7..11398d55aefaea3b03fe68bf65758e97c69513d2 100644 (file)
@@ -111,10 +111,6 @@ build_mmio_write(__writeq, "q", unsigned long, "r", )
 
 #endif
 
-#define ARCH_HAS_VALID_PHYS_ADDR_RANGE
-extern int valid_phys_addr_range(phys_addr_t addr, size_t size);
-extern int valid_mmap_phys_addr_range(unsigned long pfn, size_t size);
-
 /**
  *     virt_to_phys    -       map virtual addresses to physical
  *     @address: address to remap
index 458da8509b75ecf9fb46769cc16965b02d7e4902..6db28f17ff2884e01122f2689b117e8ae63f9ec4 100644 (file)
@@ -27,6 +27,8 @@ static const struct pci_device_id amd_root_ids[] = {
        {}
 };
 
+#define PCI_DEVICE_ID_AMD_CNB17H_F4     0x1704
+
 const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_K8_NB_MISC) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_10H_NB_MISC) },
@@ -37,6 +39,7 @@ const struct pci_device_id amd_nb_misc_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F3) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F3) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F3) },
        {}
 };
 EXPORT_SYMBOL_GPL(amd_nb_misc_ids);
@@ -48,6 +51,7 @@ static const struct pci_device_id amd_nb_link_ids[] = {
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_16H_M30H_NB_F4) },
        { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_17H_DF_F4) },
+       { PCI_DEVICE(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_CNB17H_F4) },
        {}
 };
 
@@ -402,11 +406,48 @@ void amd_flush_garts(void)
 }
 EXPORT_SYMBOL_GPL(amd_flush_garts);
 
+static void __fix_erratum_688(void *info)
+{
+#define MSR_AMD64_IC_CFG 0xC0011021
+
+       msr_set_bit(MSR_AMD64_IC_CFG, 3);
+       msr_set_bit(MSR_AMD64_IC_CFG, 14);
+}
+
+/* Apply erratum 688 fix so machines without a BIOS fix work. */
+static __init void fix_erratum_688(void)
+{
+       struct pci_dev *F4;
+       u32 val;
+
+       if (boot_cpu_data.x86 != 0x14)
+               return;
+
+       if (!amd_northbridges.num)
+               return;
+
+       F4 = node_to_amd_nb(0)->link;
+       if (!F4)
+               return;
+
+       if (pci_read_config_dword(F4, 0x164, &val))
+               return;
+
+       if (val & BIT(2))
+               return;
+
+       on_each_cpu(__fix_erratum_688, NULL, 0);
+
+       pr_info("x86/cpu/AMD: CPU erratum 688 worked around\n");
+}
+
 static __init int init_amd_nbs(void)
 {
        amd_cache_northbridges();
        amd_cache_gart();
 
+       fix_erratum_688();
+
        return 0;
 }
 
index 570b70d3f604a12ebb06a77c6290ba0d72824ee5..b95007e7c1b305e24ee63e728e003d53ff7a5c31 100644 (file)
@@ -86,8 +86,8 @@ static struct orc_entry *orc_find(unsigned long ip)
                idx = (ip - LOOKUP_START_IP) / LOOKUP_BLOCK_SIZE;
 
                if (unlikely((idx >= lookup_num_blocks-1))) {
-                       orc_warn("WARNING: bad lookup idx: idx=%u num=%u ip=%lx\n",
-                                idx, lookup_num_blocks, ip);
+                       orc_warn("WARNING: bad lookup idx: idx=%u num=%u ip=%pB\n",
+                                idx, lookup_num_blocks, (void *)ip);
                        return NULL;
                }
 
@@ -96,8 +96,8 @@ static struct orc_entry *orc_find(unsigned long ip)
 
                if (unlikely((__start_orc_unwind + start >= __stop_orc_unwind) ||
                             (__start_orc_unwind + stop > __stop_orc_unwind))) {
-                       orc_warn("WARNING: bad lookup value: idx=%u num=%u start=%u stop=%u ip=%lx\n",
-                                idx, lookup_num_blocks, start, stop, ip);
+                       orc_warn("WARNING: bad lookup value: idx=%u num=%u start=%u stop=%u ip=%pB\n",
+                                idx, lookup_num_blocks, start, stop, (void *)ip);
                        return NULL;
                }
 
@@ -373,7 +373,7 @@ bool unwind_next_frame(struct unwind_state *state)
 
        case ORC_REG_R10:
                if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg R10 at ip %p\n",
+                       orc_warn("missing regs for base reg R10 at ip %pB\n",
                                 (void *)state->ip);
                        goto done;
                }
@@ -382,7 +382,7 @@ bool unwind_next_frame(struct unwind_state *state)
 
        case ORC_REG_R13:
                if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg R13 at ip %p\n",
+                       orc_warn("missing regs for base reg R13 at ip %pB\n",
                                 (void *)state->ip);
                        goto done;
                }
@@ -391,7 +391,7 @@ bool unwind_next_frame(struct unwind_state *state)
 
        case ORC_REG_DI:
                if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg DI at ip %p\n",
+                       orc_warn("missing regs for base reg DI at ip %pB\n",
                                 (void *)state->ip);
                        goto done;
                }
@@ -400,7 +400,7 @@ bool unwind_next_frame(struct unwind_state *state)
 
        case ORC_REG_DX:
                if (!state->regs || !state->full_regs) {
-                       orc_warn("missing regs for base reg DX at ip %p\n",
+                       orc_warn("missing regs for base reg DX at ip %pB\n",
                                 (void *)state->ip);
                        goto done;
                }
@@ -408,7 +408,7 @@ bool unwind_next_frame(struct unwind_state *state)
                break;
 
        default:
-               orc_warn("unknown SP base reg %d for ip %p\n",
+               orc_warn("unknown SP base reg %d for ip %pB\n",
                         orc->sp_reg, (void *)state->ip);
                goto done;
        }
@@ -436,7 +436,7 @@ bool unwind_next_frame(struct unwind_state *state)
 
        case ORC_TYPE_REGS:
                if (!deref_stack_regs(state, sp, &state->ip, &state->sp, true)) {
-                       orc_warn("can't dereference registers at %p for ip %p\n",
+                       orc_warn("can't dereference registers at %p for ip %pB\n",
                                 (void *)sp, (void *)orig_ip);
                        goto done;
                }
@@ -448,7 +448,7 @@ bool unwind_next_frame(struct unwind_state *state)
 
        case ORC_TYPE_REGS_IRET:
                if (!deref_stack_regs(state, sp, &state->ip, &state->sp, false)) {
-                       orc_warn("can't dereference iret registers at %p for ip %p\n",
+                       orc_warn("can't dereference iret registers at %p for ip %pB\n",
                                 (void *)sp, (void *)orig_ip);
                        goto done;
                }
@@ -465,7 +465,8 @@ bool unwind_next_frame(struct unwind_state *state)
                break;
 
        default:
-               orc_warn("unknown .orc_unwind entry type %d\n", orc->type);
+               orc_warn("unknown .orc_unwind entry type %d for ip %pB\n",
+                        orc->type, (void *)orig_ip);
                break;
        }
 
@@ -487,7 +488,7 @@ bool unwind_next_frame(struct unwind_state *state)
                break;
 
        default:
-               orc_warn("unknown BP base reg %d for ip %p\n",
+               orc_warn("unknown BP base reg %d for ip %pB\n",
                         orc->bp_reg, (void *)orig_ip);
                goto done;
        }
@@ -496,7 +497,7 @@ bool unwind_next_frame(struct unwind_state *state)
        if (state->stack_info.type == prev_type &&
            on_stack(&state->stack_info, (void *)state->sp, sizeof(long)) &&
            state->sp <= prev_sp) {
-               orc_warn("stack going in the wrong direction? ip=%p\n",
+               orc_warn("stack going in the wrong direction? ip=%pB\n",
                         (void *)orig_ip);
                goto done;
        }
index f5ff142e6fe01d14b0a7f0a466c9994e844b2023..b0ff378650a9c7ef988d2fa6c984ceae9c19df54 100644 (file)
@@ -1441,7 +1441,17 @@ good_area:
         * make sure we exit gracefully rather than endlessly redo
         * the fault.  Since we never set FAULT_FLAG_RETRY_NOWAIT, if
         * we get VM_FAULT_RETRY back, the mmap_sem has been unlocked.
+        *
+        * Note that handle_userfault() may also release and reacquire mmap_sem
+        * (and not return with VM_FAULT_RETRY), when returning to userland to
+        * repeat the page fault later with a VM_FAULT_NOPAGE retval
+        * (potentially after handling any pending signal during the return to
+        * userland). The return to userland is identified whenever
+        * FAULT_FLAG_USER|FAULT_FLAG_KILLABLE are both set in flags.
+        * Thus we have to be careful about not touching vma after handling the
+        * fault, so we read the pkey beforehand.
         */
+       pkey = vma_pkey(vma);
        fault = handle_mm_fault(vma, address, flags);
        major |= fault & VM_FAULT_MAJOR;
 
@@ -1468,7 +1478,6 @@ good_area:
                return;
        }
 
-       pkey = vma_pkey(vma);
        up_read(&mm->mmap_sem);
        if (unlikely(fault & VM_FAULT_ERROR)) {
                mm_fault_error(regs, error_code, address, &pkey, fault);
index 320c6237e1d1d462da274b84bba914c11a4b7b6e..a9967982684649155cfcdc921d5247c8fbfe70d6 100644 (file)
@@ -174,15 +174,3 @@ const char *arch_vma_name(struct vm_area_struct *vma)
                return "[mpx]";
        return NULL;
 }
-
-int valid_phys_addr_range(phys_addr_t addr, size_t count)
-{
-       return addr + count <= __pa(high_memory);
-}
-
-int valid_mmap_phys_addr_range(unsigned long pfn, size_t count)
-{
-       phys_addr_t addr = (phys_addr_t)pfn << PAGE_SHIFT;
-
-       return valid_phys_addr_range(addr, count);
-}
index baebbdfd74d54f4969fac84e06c8b1741b831c0c..9adfb5445f8dca5a88a4ffe59d3573ed5b854e02 100644 (file)
@@ -386,6 +386,15 @@ static int sock_xmit(struct nbd_device *nbd, int index, int send,
        return result;
 }
 
+/*
+ * Different settings for sk->sk_sndtimeo can result in different return values
+ * if there is a signal pending when we enter sendmsg, because reasons?
+ */
+static inline int was_interrupted(int result)
+{
+       return result == -ERESTARTSYS || result == -EINTR;
+}
+
 /* always call with the tx_lock held */
 static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
 {
@@ -458,7 +467,7 @@ static int nbd_send_cmd(struct nbd_device *nbd, struct nbd_cmd *cmd, int index)
        result = sock_xmit(nbd, index, 1, &from,
                        (type == NBD_CMD_WRITE) ? MSG_MORE : 0, &sent);
        if (result <= 0) {
-               if (result == -ERESTARTSYS) {
+               if (was_interrupted(result)) {
                        /* If we havne't sent anything we can just return BUSY,
                         * however if we have sent something we need to make
                         * sure we only allow this req to be sent until we are
@@ -502,7 +511,7 @@ send_pages:
                        }
                        result = sock_xmit(nbd, index, 1, &from, flags, &sent);
                        if (result <= 0) {
-                               if (result == -ERESTARTSYS) {
+                               if (was_interrupted(result)) {
                                        /* We've already sent the header, we
                                         * have no choice but to set pending and
                                         * return BUSY.
index 34e17ee799be30e4d60f8fa45a58ea6baa3dd598..68846897d2139baa1208619469a4ef15385d7aa8 100644 (file)
@@ -593,10 +593,22 @@ static int virtblk_map_queues(struct blk_mq_tag_set *set)
        return blk_mq_virtio_map_queues(set, vblk->vdev, 0);
 }
 
+#ifdef CONFIG_VIRTIO_BLK_SCSI
+static void virtblk_initialize_rq(struct request *req)
+{
+       struct virtblk_req *vbr = blk_mq_rq_to_pdu(req);
+
+       scsi_req_init(&vbr->sreq);
+}
+#endif
+
 static const struct blk_mq_ops virtio_mq_ops = {
        .queue_rq       = virtio_queue_rq,
        .complete       = virtblk_request_done,
        .init_request   = virtblk_init_request,
+#ifdef CONFIG_VIRTIO_BLK_SCSI
+       .initialize_rq_fn = virtblk_initialize_rq,
+#endif
        .map_queues     = virtblk_map_queues,
 };
 
index 1cb2d1c070c31ba1a80e8e9460d0d102e9dddd74..a94601d5939e2f51c2ebfd542cbf90dcfc2f0b7c 100644 (file)
@@ -238,7 +238,8 @@ unsigned long efi_entry(void *handle, efi_system_table_t *sys_table,
 
        efi_random_get_seed(sys_table);
 
-       if (!nokaslr()) {
+       /* hibernation expects the runtime regions to stay in the same place */
+       if (!IS_ENABLED(CONFIG_HIBERNATION) && !nokaslr()) {
                /*
                 * Randomize the base of the UEFI runtime services region.
                 * Preserve the 2 MB alignment of the region by taking a
index 08129b7b80ab9bbf2320a4061b4059554d90973f..41c48a1e8baaa8e46e9609c0b76a2698b5ac5c49 100644 (file)
@@ -593,6 +593,9 @@ static long efi_runtime_query_capsulecaps(unsigned long arg)
        if (copy_from_user(&qcaps, qcaps_user, sizeof(qcaps)))
                return -EFAULT;
 
+       if (qcaps.capsule_count == ULONG_MAX)
+               return -EINVAL;
+
        capsules = kcalloc(qcaps.capsule_count + 1,
                           sizeof(efi_capsule_header_t), GFP_KERNEL);
        if (!capsules)
index 31db356476f8f1f72f488c54282a09409bcbb749..430a6b4dfac972f7780e04ac3fc8b1303086878e 100644 (file)
@@ -225,11 +225,7 @@ static int uvd_v6_0_suspend(void *handle)
        if (r)
                return r;
 
-       /* Skip this for APU for now */
-       if (!(adev->flags & AMD_IS_APU))
-               r = amdgpu_uvd_suspend(adev);
-
-       return r;
+       return amdgpu_uvd_suspend(adev);
 }
 
 static int uvd_v6_0_resume(void *handle)
@@ -237,12 +233,10 @@ static int uvd_v6_0_resume(void *handle)
        int r;
        struct amdgpu_device *adev = (struct amdgpu_device *)handle;
 
-       /* Skip this for APU for now */
-       if (!(adev->flags & AMD_IS_APU)) {
-               r = amdgpu_uvd_resume(adev);
-               if (r)
-                       return r;
-       }
+       r = amdgpu_uvd_resume(adev);
+       if (r)
+               return r;
+
        return uvd_v6_0_hw_init(adev);
 }
 
index c2743233ba10ed8dd9b55338730fbff9722ae680..b526f49be65d066d5eb49d7339ebe3e089c08877 100644 (file)
@@ -830,7 +830,7 @@ uint32_t smu7_get_xclk(struct pp_hwmgr *hwmgr)
 {
        uint32_t reference_clock, tmp;
        struct cgs_display_info info = {0};
-       struct cgs_mode_info mode_info;
+       struct cgs_mode_info mode_info = {0};
 
        info.mode_info = &mode_info;
 
@@ -3948,10 +3948,9 @@ static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
        uint32_t ref_clock;
        uint32_t refresh_rate = 0;
        struct cgs_display_info info = {0};
-       struct cgs_mode_info mode_info;
+       struct cgs_mode_info mode_info = {0};
 
        info.mode_info = &mode_info;
-
        cgs_get_active_displays_info(hwmgr->device, &info);
        num_active_displays = info.display_count;
 
@@ -3967,6 +3966,7 @@ static int smu7_program_display_gap(struct pp_hwmgr *hwmgr)
        frame_time_in_us = 1000000 / refresh_rate;
 
        pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us;
+
        data->frame_time_x2 = frame_time_in_us * 2 / 100;
 
        display_gap2 = pre_vbi_time_in_us * (ref_clock / 100);
index 21c36e256884fb8414352d5ffdd1f3baaa6606a3..d4726a3358a4a5b241ff50af1efb9ddcd64f4fbf 100644 (file)
@@ -2723,6 +2723,9 @@ static int combine_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
        uint32_t per_ctx_start[CACHELINE_DWORDS] = {0};
        unsigned char *bb_start_sva;
 
+       if (!wa_ctx->per_ctx.valid)
+               return 0;
+
        per_ctx_start[0] = 0x18800001;
        per_ctx_start[1] = wa_ctx->per_ctx.guest_gma;
 
index 91b4300f3b394a59e6ad2f19ea5fae9834d82806..e5320b4eb698e9793ab1d6d8284935422b706a89 100644 (file)
@@ -701,8 +701,7 @@ static int submit_context(struct intel_vgpu *vgpu, int ring_id,
                        CACHELINE_BYTES;
                workload->wa_ctx.per_ctx.guest_gma =
                        per_ctx & PER_CTX_ADDR_MASK;
-
-               WARN_ON(workload->wa_ctx.indirect_ctx.size && !(per_ctx & 0x1));
+               workload->wa_ctx.per_ctx.valid = per_ctx & 1;
        }
 
        if (emulate_schedule_in)
index 2294466dd4150b943ad80c53a8ca3b611c9324c8..a5bed2e71b9260afbe5ee3db7bb6649f29b826a2 100644 (file)
@@ -1429,18 +1429,7 @@ static int skl_lcpll_write(struct intel_vgpu *vgpu, unsigned int offset,
        return 0;
 }
 
-static int ring_timestamp_mmio_read(struct intel_vgpu *vgpu,
-               unsigned int offset, void *p_data, unsigned int bytes)
-{
-       struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
-
-       mmio_hw_access_pre(dev_priv);
-       vgpu_vreg(vgpu, offset) = I915_READ(_MMIO(offset));
-       mmio_hw_access_post(dev_priv);
-       return intel_vgpu_default_mmio_read(vgpu, offset, p_data, bytes);
-}
-
-static int instdone_mmio_read(struct intel_vgpu *vgpu,
+static int mmio_read_from_hw(struct intel_vgpu *vgpu,
                unsigned int offset, void *p_data, unsigned int bytes)
 {
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
@@ -1589,6 +1578,8 @@ static int ring_reset_ctl_write(struct intel_vgpu *vgpu,
        MMIO_F(prefix(BLT_RING_BASE), s, f, am, rm, d, r, w); \
        MMIO_F(prefix(GEN6_BSD_RING_BASE), s, f, am, rm, d, r, w); \
        MMIO_F(prefix(VEBOX_RING_BASE), s, f, am, rm, d, r, w); \
+       if (HAS_BSD2(dev_priv)) \
+               MMIO_F(prefix(GEN8_BSD2_RING_BASE), s, f, am, rm, d, r, w); \
 } while (0)
 
 #define MMIO_RING_D(prefix, d) \
@@ -1635,10 +1626,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
 #undef RING_REG
 
 #define RING_REG(base) (base + 0x6c)
-       MMIO_RING_DFH(RING_REG, D_ALL, 0, instdone_mmio_read, NULL);
-       MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_ALL, instdone_mmio_read, NULL);
+       MMIO_RING_DFH(RING_REG, D_ALL, 0, mmio_read_from_hw, NULL);
 #undef RING_REG
-       MMIO_DH(GEN7_SC_INSTDONE, D_BDW_PLUS, instdone_mmio_read, NULL);
+       MMIO_DH(GEN7_SC_INSTDONE, D_BDW_PLUS, mmio_read_from_hw, NULL);
 
        MMIO_GM_RDR(0x2148, D_ALL, NULL, NULL);
        MMIO_GM_RDR(CCID, D_ALL, NULL, NULL);
@@ -1648,7 +1638,7 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_RING_DFH(RING_TAIL, D_ALL, F_CMD_ACCESS, NULL, NULL);
        MMIO_RING_DFH(RING_HEAD, D_ALL, F_CMD_ACCESS, NULL, NULL);
        MMIO_RING_DFH(RING_CTL, D_ALL, F_CMD_ACCESS, NULL, NULL);
-       MMIO_RING_DFH(RING_ACTHD, D_ALL, F_CMD_ACCESS, NULL, NULL);
+       MMIO_RING_DFH(RING_ACTHD, D_ALL, F_CMD_ACCESS, mmio_read_from_hw, NULL);
        MMIO_RING_GM_RDR(RING_START, D_ALL, NULL, NULL);
 
        /* RING MODE */
@@ -1662,9 +1652,9 @@ static int init_generic_mmio_info(struct intel_gvt *gvt)
        MMIO_RING_DFH(RING_INSTPM, D_ALL, F_MODE_MASK | F_CMD_ACCESS,
                        NULL, NULL);
        MMIO_RING_DFH(RING_TIMESTAMP, D_ALL, F_CMD_ACCESS,
-                       ring_timestamp_mmio_read, NULL);
+                       mmio_read_from_hw, NULL);
        MMIO_RING_DFH(RING_TIMESTAMP_UDW, D_ALL, F_CMD_ACCESS,
-                       ring_timestamp_mmio_read, NULL);
+                       mmio_read_from_hw, NULL);
 
        MMIO_DFH(GEN7_GT_MODE, D_ALL, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(CACHE_MODE_0_GEN7, D_ALL, F_MODE_MASK | F_CMD_ACCESS,
@@ -2411,9 +2401,6 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        struct drm_i915_private *dev_priv = gvt->dev_priv;
        int ret;
 
-       MMIO_DFH(RING_IMR(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS, NULL,
-                       intel_vgpu_reg_imr_handler);
-
        MMIO_DH(GEN8_GT_IMR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_imr_handler);
        MMIO_DH(GEN8_GT_IER(0), D_BDW_PLUS, NULL, intel_vgpu_reg_ier_handler);
        MMIO_DH(GEN8_GT_IIR(0), D_BDW_PLUS, NULL, intel_vgpu_reg_iir_handler);
@@ -2476,68 +2463,34 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        MMIO_DH(GEN8_MASTER_IRQ, D_BDW_PLUS, NULL,
                intel_vgpu_reg_master_irq_handler);
 
-       MMIO_DFH(RING_HWSTAM(GEN8_BSD2_RING_BASE), D_BDW_PLUS,
-               F_CMD_ACCESS, NULL, NULL);
-       MMIO_DFH(0x1c134, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
-
-       MMIO_DFH(RING_TAIL(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS,
-               NULL, NULL);
-       MMIO_DFH(RING_HEAD(GEN8_BSD2_RING_BASE),  D_BDW_PLUS,
-               F_CMD_ACCESS, NULL, NULL);
-       MMIO_GM_RDR(RING_START(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL);
-       MMIO_DFH(RING_CTL(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS,
-               NULL, NULL);
-       MMIO_DFH(RING_ACTHD(GEN8_BSD2_RING_BASE), D_BDW_PLUS,
-               F_CMD_ACCESS, NULL, NULL);
-       MMIO_DFH(RING_ACTHD_UDW(GEN8_BSD2_RING_BASE), D_BDW_PLUS,
-               F_CMD_ACCESS, NULL, NULL);
-       MMIO_DFH(0x1c29c, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL,
-               ring_mode_mmio_write);
-       MMIO_DFH(RING_MI_MODE(GEN8_BSD2_RING_BASE), D_BDW_PLUS,
-               F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
-       MMIO_DFH(RING_INSTPM(GEN8_BSD2_RING_BASE), D_BDW_PLUS,
-               F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
-       MMIO_DFH(RING_TIMESTAMP(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS,
-                       ring_timestamp_mmio_read, NULL);
-
-       MMIO_RING_DFH(RING_ACTHD_UDW, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+       MMIO_RING_DFH(RING_ACTHD_UDW, D_BDW_PLUS, F_CMD_ACCESS,
+               mmio_read_from_hw, NULL);
 
 #define RING_REG(base) (base + 0xd0)
        MMIO_RING_F(RING_REG, 4, F_RO, 0,
                ~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL,
                ring_reset_ctl_write);
-       MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO, 0,
-               ~_MASKED_BIT_ENABLE(RESET_CTL_REQUEST_RESET), D_BDW_PLUS, NULL,
-               ring_reset_ctl_write);
 #undef RING_REG
 
 #define RING_REG(base) (base + 0x230)
        MMIO_RING_DFH(RING_REG, D_BDW_PLUS, 0, NULL, elsp_mmio_write);
-       MMIO_DH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, elsp_mmio_write);
 #undef RING_REG
 
 #define RING_REG(base) (base + 0x234)
        MMIO_RING_F(RING_REG, 8, F_RO | F_CMD_ACCESS, 0, ~0, D_BDW_PLUS,
                NULL, NULL);
-       MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 4, F_RO | F_CMD_ACCESS, 0,
-               ~0LL, D_BDW_PLUS, NULL, NULL);
 #undef RING_REG
 
 #define RING_REG(base) (base + 0x244)
        MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
-       MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_CMD_ACCESS,
-               NULL, NULL);
 #undef RING_REG
 
 #define RING_REG(base) (base + 0x370)
        MMIO_RING_F(RING_REG, 48, F_RO, 0, ~0, D_BDW_PLUS, NULL, NULL);
-       MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 48, F_RO, 0, ~0, D_BDW_PLUS,
-                       NULL, NULL);
 #undef RING_REG
 
 #define RING_REG(base) (base + 0x3a0)
        MMIO_RING_DFH(RING_REG, D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
-       MMIO_DFH(RING_REG(GEN8_BSD2_RING_BASE), D_BDW_PLUS, F_MODE_MASK, NULL, NULL);
 #undef RING_REG
 
        MMIO_D(PIPEMISC(PIPE_A), D_BDW_PLUS);
@@ -2557,11 +2510,9 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
 
 #define RING_REG(base) (base + 0x270)
        MMIO_RING_F(RING_REG, 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);
-       MMIO_F(RING_REG(GEN8_BSD2_RING_BASE), 32, 0, 0, 0, D_BDW_PLUS, NULL, NULL);
 #undef RING_REG
 
        MMIO_RING_GM_RDR(RING_HWS_PGA, D_BDW_PLUS, NULL, NULL);
-       MMIO_GM_RDR(RING_HWS_PGA(GEN8_BSD2_RING_BASE), D_BDW_PLUS, NULL, NULL);
 
        MMIO_DFH(HDC_CHICKEN0, D_BDW_PLUS, F_MODE_MASK | F_CMD_ACCESS, NULL, NULL);
 
@@ -2849,7 +2800,6 @@ static int init_skl_mmio_info(struct intel_gvt *gvt)
        MMIO_D(0x65f08, D_SKL | D_KBL);
        MMIO_D(0x320f0, D_SKL | D_KBL);
 
-       MMIO_DFH(_REG_VCS2_EXCC, D_SKL_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_D(0x70034, D_SKL_PLUS);
        MMIO_D(0x71034, D_SKL_PLUS);
        MMIO_D(0x72034, D_SKL_PLUS);
index fbd023a16f18163d6dcb52bcf795675e3c16a4f7..7d01c77a0f7ac61212d17c901860b2ef5e6fab63 100644 (file)
@@ -54,9 +54,6 @@
 
 #define VGT_SPRSTRIDE(pipe)    _PIPE(pipe, _SPRA_STRIDE, _PLANE_STRIDE_2_B)
 
-#define _REG_VECS_EXCC         0x1A028
-#define _REG_VCS2_EXCC         0x1c028
-
 #define _REG_701C0(pipe, plane) (0x701c0 + pipe * 0x1000 + (plane - 1) * 0x100)
 #define _REG_701C4(pipe, plane) (0x701c4 + pipe * 0x1000 + (plane - 1) * 0x100)
 
index 0d431a968a32970f07cda55bb37f55a0634afc98..93a49eb0209ee645818a673a07d8a31291840ce7 100644 (file)
@@ -68,6 +68,7 @@ struct shadow_indirect_ctx {
 struct shadow_per_ctx {
        unsigned long guest_gma;
        unsigned long shadow_gma;
+       unsigned valid;
 };
 
 struct intel_shadow_wa_ctx {
index 94185d610673a77d17bf0bfb5796fbac4df2a05d..370b9d248fed89abe2b3601063ddffd27661c76e 100644 (file)
@@ -2537,6 +2537,10 @@ static const struct file_operations fops = {
        .poll           = i915_perf_poll,
        .read           = i915_perf_read,
        .unlocked_ioctl = i915_perf_ioctl,
+       /* Our ioctl have no arguments, so it's safe to use the same function
+        * to handle 32bits compatibility.
+        */
+       .compat_ioctl   = i915_perf_ioctl,
 };
 
 
index 97a62f5b9ea466cc4277a14b1a8bc59a6bd360b5..a973eb6a28908be2c17092ad4a1169e288a6f8e8 100644 (file)
@@ -477,6 +477,11 @@ static int da9052_hwmon_probe(struct platform_device *pdev)
                /* disable touchscreen features */
                da9052_reg_write(hwmon->da9052, DA9052_TSI_CONT_A_REG, 0x00);
 
+               /* Sample every 1ms */
+               da9052_reg_update(hwmon->da9052, DA9052_ADC_CONT_REG,
+                                         DA9052_ADCCONT_ADCMODE,
+                                         DA9052_ADCCONT_ADCMODE);
+
                err = da9052_request_irq(hwmon->da9052, DA9052_IRQ_TSIREADY,
                                         "tsiready-irq", da9052_tsi_datardy_irq,
                                         hwmon);
index 5eafbaada7958d81b530637b5ab5c2a3a29066b0..dfc40c740d07b7a2029777b5f01a8bbd145439b0 100644 (file)
@@ -268,14 +268,11 @@ static int tmp102_probe(struct i2c_client *client,
                return err;
        }
 
-       tmp102->ready_time = jiffies;
-       if (tmp102->config_orig & TMP102_CONF_SD) {
-               /*
-                * Mark that we are not ready with data until the first
-                * conversion is complete
-                */
-               tmp102->ready_time += msecs_to_jiffies(CONVERSION_TIME_MS);
-       }
+       /*
+        * Mark that we are not ready with data until the first
+        * conversion is complete
+        */
+       tmp102->ready_time = jiffies + msecs_to_jiffies(CONVERSION_TIME_MS);
 
        hwmon_dev = devm_hwmon_device_register_with_info(dev, client->name,
                                                         tmp102,
index 81e18f9628d068e54cd5fca5f80b06594ee5d29f..a7355ab3bb221a0a6438d336719f1f3a30e4e00a 100644 (file)
@@ -1328,6 +1328,7 @@ static int ide_cdrom_prep_fs(struct request_queue *q, struct request *rq)
        unsigned long blocks = blk_rq_sectors(rq) / (hard_sect >> 9);
        struct scsi_request *req = scsi_req(rq);
 
+       scsi_req_init(req);
        memset(req->cmd, 0, BLK_MAX_CDB);
 
        if (rq_data_dir(rq) == READ)
index b12e58787c3ddc9f87d80e500392740336bfa362..1fb72c356e36ccc77fc3d97e384a238d9fa6d2f9 100644 (file)
@@ -175,13 +175,24 @@ static int rdma_nl_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
            !netlink_capable(skb, CAP_NET_ADMIN))
                return -EPERM;
 
+       /*
+        * LS responses overload the 0x100 (NLM_F_ROOT) flag.  Don't
+        * mistakenly call the .dump() function.
+        */
+       if (index == RDMA_NL_LS) {
+               if (cb_table[op].doit)
+                       return cb_table[op].doit(skb, nlh, extack);
+               return -EINVAL;
+       }
        /* FIXME: Convert IWCM to properly handle doit callbacks */
        if ((nlh->nlmsg_flags & NLM_F_DUMP) || index == RDMA_NL_RDMA_CM ||
            index == RDMA_NL_IWCM) {
                struct netlink_dump_control c = {
                        .dump = cb_table[op].dump,
                };
-               return netlink_dump_start(nls, skb, nlh, &c);
+               if (c.dump)
+                       return netlink_dump_start(nls, skb, nlh, &c);
+               return -EINVAL;
        }
 
        if (cb_table[op].doit)
index 3ba24c428c3bda48ec8698934f275828754ac19d..2fae850a3eff6a92703aed33975af9b1e0fc3835 100644 (file)
@@ -214,7 +214,9 @@ static int nldev_port_get_doit(struct sk_buff *skb, struct nlmsghdr *nlh,
 
        err = nlmsg_parse(nlh, 0, tb, RDMA_NLDEV_ATTR_MAX - 1,
                          nldev_policy, extack);
-       if (err || !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
+       if (err ||
+           !tb[RDMA_NLDEV_ATTR_DEV_INDEX] ||
+           !tb[RDMA_NLDEV_ATTR_PORT_INDEX])
                return -EINVAL;
 
        index = nla_get_u32(tb[RDMA_NLDEV_ATTR_DEV_INDEX]);
index 0e761d079dc4669720d2d4899f13ecbbfdb22b52..6d6b092e2da901969b8e3a2cfe65f2d0f2651098 100644 (file)
@@ -1258,6 +1258,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0605", 0 },
        { "ELAN0609", 0 },
        { "ELAN060B", 0 },
+       { "ELAN0611", 0 },
        { "ELAN1000", 0 },
        { }
 };
index 34dfee555b201b0577e6e5fc0c58c63e7cc8cac7..82e0f0d43d55271c92c774ba325b1bc40099f83e 100644 (file)
@@ -232,9 +232,10 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
        unsigned int trackstick_button = BTN_LEFT;
        bool button_mapped = false;
        int i;
+       int button_count = min_t(u8, f30->gpioled_count, TRACKSTICK_RANGE_END);
 
        f30->gpioled_key_map = devm_kcalloc(&fn->dev,
-                                           f30->gpioled_count,
+                                           button_count,
                                            sizeof(f30->gpioled_key_map[0]),
                                            GFP_KERNEL);
        if (!f30->gpioled_key_map) {
@@ -242,7 +243,7 @@ static int rmi_f30_map_gpios(struct rmi_function *fn,
                return -ENOMEM;
        }
 
-       for (i = 0; i < f30->gpioled_count; i++) {
+       for (i = 0; i < button_count; i++) {
                if (!rmi_f30_is_valid_button(i, f30->ctrl))
                        continue;
 
index b796e891e2eed22e1ffdac3f3098fdf7afbe4ac6..4b8b9d7aa75e2785991fc5838bf55728c715e6fe 100644 (file)
@@ -230,13 +230,17 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
 
        /* Walk  this report and pull out the info we need */
        while (i < length) {
-               prefix = report[i];
-
-               /* Skip over prefix */
-               i++;
+               prefix = report[i++];
 
                /* Determine data size and save the data in the proper variable */
-               size = PREF_SIZE(prefix);
+               size = (1U << PREF_SIZE(prefix)) >> 1;
+               if (i + size > length) {
+                       dev_err(ddev,
+                               "Not enough data (need %d, have %d)\n",
+                               i + size, length);
+                       break;
+               }
+
                switch (size) {
                case 1:
                        data = report[i];
@@ -244,8 +248,7 @@ static void parse_hid_report_descriptor(struct gtco *device, char * report,
                case 2:
                        data16 = get_unaligned_le16(&report[i]);
                        break;
-               case 3:
-                       size = 4;
+               case 4:
                        data32 = get_unaligned_le32(&report[i]);
                        break;
                }
index f905f2361d12fa5ee1757b38ddb46eb4e653066b..8bae88a150fd45b3284b594d2d090d4f78fe1fc7 100644 (file)
@@ -146,11 +146,8 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host,
        WARN_ON(host->sg_len > 1);
 
        /* This DMAC cannot handle if buffer is not 8-bytes alignment */
-       if (!IS_ALIGNED(sg->offset, 8)) {
-               host->force_pio = true;
-               renesas_sdhi_internal_dmac_enable_dma(host, false);
-               return;
-       }
+       if (!IS_ALIGNED(sg->offset, 8))
+               goto force_pio;
 
        if (data->flags & MMC_DATA_READ) {
                dtran_mode |= DTRAN_MODE_CH_NUM_CH1;
@@ -163,8 +160,8 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host,
        }
 
        ret = dma_map_sg(&host->pdev->dev, sg, host->sg_len, dir);
-       if (ret < 0)
-               return;
+       if (ret == 0)
+               goto force_pio;
 
        renesas_sdhi_internal_dmac_enable_dma(host, true);
 
@@ -176,6 +173,12 @@ renesas_sdhi_internal_dmac_start_dma(struct tmio_mmc_host *host,
                                            dtran_mode);
        renesas_sdhi_internal_dmac_dm_write(host, DM_DTRAN_ADDR,
                                            sg->dma_address);
+
+       return;
+
+force_pio:
+       host->force_pio = true;
+       renesas_sdhi_internal_dmac_enable_dma(host, false);
 }
 
 static void renesas_sdhi_internal_dmac_issue_tasklet_fn(unsigned long arg)
index a7293e186e03fc44ccb271405e99fbfaef06d770..9c4e6199b854d38c585ae1464d9056a754e4de33 100644 (file)
@@ -47,6 +47,7 @@
 #include <linux/mmc/sdio.h>
 #include <linux/scatterlist.h>
 #include <linux/spinlock.h>
+#include <linux/swiotlb.h>
 #include <linux/workqueue.h>
 
 #include "tmio_mmc.h"
@@ -1215,6 +1216,18 @@ int tmio_mmc_host_probe(struct tmio_mmc_host *_host,
        mmc->max_blk_count = pdata->max_blk_count ? :
                (PAGE_SIZE / mmc->max_blk_size) * mmc->max_segs;
        mmc->max_req_size = mmc->max_blk_size * mmc->max_blk_count;
+       /*
+        * Since swiotlb has memory size limitation, this will calculate
+        * the maximum size locally (because we don't have any APIs for it now)
+        * and check the current max_req_size. And then, this will update
+        * the max_req_size if needed as a workaround.
+        */
+       if (swiotlb_max_segment()) {
+               unsigned int max_size = (1 << IO_TLB_SHIFT) * IO_TLB_SEGSIZE;
+
+               if (mmc->max_req_size > max_size)
+                       mmc->max_req_size = max_size;
+       }
        mmc->max_seg_size = mmc->max_req_size;
 
        _host->native_hotplug = !(pdata->flags & TMIO_MMC_USE_GPIO_CD ||
index 68ef0a4cd82153cd65699ab0a4d80a5a201393e6..b0c80859f7467ef32a2683a506757c41ad13cb28 100644 (file)
@@ -342,7 +342,7 @@ static int sun4i_can_start(struct net_device *dev)
 
        /* enter the selected mode */
        mod_reg_val = readl(priv->base + SUN4I_REG_MSEL_ADDR);
-       if (priv->can.ctrlmode & CAN_CTRLMODE_PRESUME_ACK)
+       if (priv->can.ctrlmode & CAN_CTRLMODE_LOOPBACK)
                mod_reg_val |= SUN4I_MSEL_LOOPBACK_MODE;
        else if (priv->can.ctrlmode & CAN_CTRLMODE_LISTENONLY)
                mod_reg_val |= SUN4I_MSEL_LISTEN_ONLY_MODE;
@@ -811,7 +811,6 @@ static int sun4ican_probe(struct platform_device *pdev)
        priv->can.ctrlmode_supported = CAN_CTRLMODE_BERR_REPORTING |
                                       CAN_CTRLMODE_LISTENONLY |
                                       CAN_CTRLMODE_LOOPBACK |
-                                      CAN_CTRLMODE_PRESUME_ACK |
                                       CAN_CTRLMODE_3_SAMPLES;
        priv->base = addr;
        priv->clk = clk;
index 18cc529fb807a4ad88fc06a201b18456040c5859..9b18d96ef52633ab34bb5ff39f4f643023dc308a 100644 (file)
@@ -137,6 +137,7 @@ static inline bool kvaser_is_usbcan(const struct usb_device_id *id)
 #define CMD_RESET_ERROR_COUNTER                49
 #define CMD_TX_ACKNOWLEDGE             50
 #define CMD_CAN_ERROR_EVENT            51
+#define CMD_FLUSH_QUEUE_REPLY          68
 
 #define CMD_LEAF_USB_THROTTLE          77
 #define CMD_LEAF_LOG_MESSAGE           106
@@ -1301,6 +1302,11 @@ static void kvaser_usb_handle_message(const struct kvaser_usb *dev,
                        goto warn;
                break;
 
+       case CMD_FLUSH_QUEUE_REPLY:
+               if (dev->family != KVASER_LEAF)
+                       goto warn;
+               break;
+
        default:
 warn:          dev_warn(dev->udev->dev.parent,
                         "Unhandled message (%d)\n", msg->id);
@@ -1609,7 +1615,8 @@ static int kvaser_usb_close(struct net_device *netdev)
        if (err)
                netdev_warn(netdev, "Cannot flush queue, error %d\n", err);
 
-       if (kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel))
+       err = kvaser_usb_send_simple_msg(dev, CMD_RESET_CHIP, priv->channel);
+       if (err)
                netdev_warn(netdev, "Cannot reset card, error %d\n", err);
 
        err = kvaser_usb_stop_chip(priv);
index 36520634c96ae127aea4c2994bd6c86ff42e3376..e77192683dbad9a1fca22816e411abf4c3c25d8c 100644 (file)
@@ -2369,8 +2369,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
                        priv->enet_ver = AE_VERSION_2;
 
                ae_node = of_parse_phandle(dev->of_node, "ae-handle", 0);
-               if (IS_ERR_OR_NULL(ae_node)) {
-                       ret = PTR_ERR(ae_node);
+               if (!ae_node) {
+                       ret = -ENODEV;
                        dev_err(dev, "not find ae-handle\n");
                        goto out_read_prop_fail;
                }
index ec8aa4562cc90a90dff844872278722b24daec3c..3b3983a1ffbba1d6795ead832c5aceb801023969 100644 (file)
@@ -1824,11 +1824,12 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
 {
        struct e1000_adapter *adapter = netdev_priv(netdev);
        int i;
-       char *p = NULL;
        const struct e1000_stats *stat = e1000_gstrings_stats;
 
        e1000_update_stats(adapter);
-       for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++) {
+       for (i = 0; i < E1000_GLOBAL_STATS_LEN; i++, stat++) {
+               char *p;
+
                switch (stat->type) {
                case NETDEV_STATS:
                        p = (char *)netdev + stat->stat_offset;
@@ -1839,15 +1840,13 @@ static void e1000_get_ethtool_stats(struct net_device *netdev,
                default:
                        WARN_ONCE(1, "Invalid E1000 stat type: %u index %d\n",
                                  stat->type, i);
-                       break;
+                       continue;
                }
 
                if (stat->sizeof_stat == sizeof(u64))
                        data[i] = *(u64 *)p;
                else
                        data[i] = *(u32 *)p;
-
-               stat++;
        }
 /* BUG_ON(i != E1000_STATS_LEN); */
 }
index 98375e1e1185e7b8136515d0d3e2a90464495ccd..1982f7917a8d5d68776b2e052ac1df809f11c065 100644 (file)
@@ -520,8 +520,6 @@ void e1000_down(struct e1000_adapter *adapter)
        struct net_device *netdev = adapter->netdev;
        u32 rctl, tctl;
 
-       netif_carrier_off(netdev);
-
        /* disable receives in the hardware */
        rctl = er32(RCTL);
        ew32(RCTL, rctl & ~E1000_RCTL_EN);
@@ -537,6 +535,15 @@ void e1000_down(struct e1000_adapter *adapter)
        E1000_WRITE_FLUSH();
        msleep(10);
 
+       /* Set the carrier off after transmits have been disabled in the
+        * hardware, to avoid race conditions with e1000_watchdog() (which
+        * may be running concurrently to us, checking for the carrier
+        * bit to decide whether it should enable transmits again). Such
+        * a race condition would result into transmission being disabled
+        * in the hardware until the next IFF_DOWN+IFF_UP cycle.
+        */
+       netif_carrier_off(netdev);
+
        napi_disable(&adapter->napi);
 
        e1000_irq_disable(adapter);
index 2756131495f07f269f4c7f2e223dda4dcb7153f0..120c68f78951dd1ae7a2218b4b64c049aee40340 100644 (file)
@@ -2102,6 +2102,7 @@ static int i40e_clean_rx_irq(struct i40e_ring *rx_ring, int budget)
 
                if (unlikely(i40e_rx_is_programming_status(qword))) {
                        i40e_clean_programming_status(rx_ring, rx_desc, qword);
+                       cleaned_count++;
                        continue;
                }
                size = (qword & I40E_RXD_QW1_LENGTH_PBUF_MASK) >>
@@ -2269,7 +2270,7 @@ static inline void i40e_update_enable_itr(struct i40e_vsi *vsi,
                goto enable_int;
        }
 
-       if (ITR_IS_DYNAMIC(tx_itr_setting)) {
+       if (ITR_IS_DYNAMIC(rx_itr_setting)) {
                rx = i40e_set_new_dynamic_itr(&q_vector->rx);
                rxval = i40e_buildreg_itr(I40E_RX_ITR, q_vector->rx.itr);
        }
index fd4a46b03cc8317f44f0c4d3ee5141dd05858244..ea69af267d63522ae7f545c2cbb8a7a6e601adbc 100644 (file)
@@ -5326,7 +5326,7 @@ dma_error:
                                       DMA_TO_DEVICE);
                dma_unmap_len_set(tx_buffer, len, 0);
 
-               if (i--)
+               if (i-- == 0)
                        i += tx_ring->count;
                tx_buffer = &tx_ring->tx_buffer_info[i];
        }
index 4d76afd13868574854759d844af34b2b3879a780..6d5f31e943583df77f5fa1e6aa3e2703fff33518 100644 (file)
@@ -8020,29 +8020,23 @@ static int ixgbe_tx_map(struct ixgbe_ring *tx_ring,
        return 0;
 dma_error:
        dev_err(tx_ring->dev, "TX DMA map failed\n");
-       tx_buffer = &tx_ring->tx_buffer_info[i];
 
        /* clear dma mappings for failed tx_buffer_info map */
-       while (tx_buffer != first) {
+       for (;;) {
+               tx_buffer = &tx_ring->tx_buffer_info[i];
                if (dma_unmap_len(tx_buffer, len))
                        dma_unmap_page(tx_ring->dev,
                                       dma_unmap_addr(tx_buffer, dma),
                                       dma_unmap_len(tx_buffer, len),
                                       DMA_TO_DEVICE);
                dma_unmap_len_set(tx_buffer, len, 0);
-
-               if (i--)
+               if (tx_buffer == first)
+                       break;
+               if (i == 0)
                        i += tx_ring->count;
-               tx_buffer = &tx_ring->tx_buffer_info[i];
+               i--;
        }
 
-       if (dma_unmap_len(tx_buffer, len))
-               dma_unmap_single(tx_ring->dev,
-                                dma_unmap_addr(tx_buffer, dma),
-                                dma_unmap_len(tx_buffer, len),
-                                DMA_TO_DEVICE);
-       dma_unmap_len_set(tx_buffer, len, 0);
-
        dev_kfree_skb_any(first->skb);
        first->skb = NULL;
 
index 9c86cb7cb988a7ee3f89e3d2ec86a37f0a0344dc..a37af5813f33758d1ed8debf6bcd77590363f349 100644 (file)
@@ -1167,6 +1167,11 @@ struct mvpp2_bm_pool {
        u32 port_map;
 };
 
+#define IS_TSO_HEADER(txq_pcpu, addr) \
+       ((addr) >= (txq_pcpu)->tso_headers_dma && \
+        (addr) < (txq_pcpu)->tso_headers_dma + \
+        (txq_pcpu)->size * TSO_HEADER_SIZE)
+
 /* Queue modes */
 #define MVPP2_QDIST_SINGLE_MODE        0
 #define MVPP2_QDIST_MULTI_MODE 1
@@ -1534,7 +1539,7 @@ static bool mvpp2_prs_tcam_data_cmp(struct mvpp2_prs_entry *pe, int offs,
        int off = MVPP2_PRS_TCAM_DATA_BYTE(offs);
        u16 tcam_data;
 
-       tcam_data = (8 << pe->tcam.byte[off + 1]) | pe->tcam.byte[off];
+       tcam_data = (pe->tcam.byte[off + 1] << 8) | pe->tcam.byte[off];
        if (tcam_data != data)
                return false;
        return true;
@@ -2609,8 +2614,8 @@ static void mvpp2_prs_mac_init(struct mvpp2 *priv)
        /* place holders only - no ports */
        mvpp2_prs_mac_drop_all_set(priv, 0, false);
        mvpp2_prs_mac_promisc_set(priv, 0, false);
-       mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_ALL, 0, false);
-       mvpp2_prs_mac_multi_set(priv, MVPP2_PE_MAC_MC_IP6, 0, false);
+       mvpp2_prs_mac_multi_set(priv, 0, MVPP2_PE_MAC_MC_ALL, false);
+       mvpp2_prs_mac_multi_set(priv, 0, MVPP2_PE_MAC_MC_IP6, false);
 }
 
 /* Set default entries for various types of dsa packets */
@@ -3391,7 +3396,7 @@ mvpp2_prs_mac_da_range_find(struct mvpp2 *priv, int pmap, const u8 *da,
        struct mvpp2_prs_entry *pe;
        int tid;
 
-       pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+       pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
        if (!pe)
                return NULL;
        mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
@@ -3453,7 +3458,7 @@ static int mvpp2_prs_mac_da_accept(struct mvpp2 *priv, int port,
                if (tid < 0)
                        return tid;
 
-               pe = kzalloc(sizeof(*pe), GFP_KERNEL);
+               pe = kzalloc(sizeof(*pe), GFP_ATOMIC);
                if (!pe)
                        return -ENOMEM;
                mvpp2_prs_tcam_lu_set(pe, MVPP2_PRS_LU_MAC);
@@ -5321,8 +5326,9 @@ static void mvpp2_txq_bufs_free(struct mvpp2_port *port,
                struct mvpp2_txq_pcpu_buf *tx_buf =
                        txq_pcpu->buffs + txq_pcpu->txq_get_index;
 
-               dma_unmap_single(port->dev->dev.parent, tx_buf->dma,
-                                tx_buf->size, DMA_TO_DEVICE);
+               if (!IS_TSO_HEADER(txq_pcpu, tx_buf->dma))
+                       dma_unmap_single(port->dev->dev.parent, tx_buf->dma,
+                                        tx_buf->size, DMA_TO_DEVICE);
                if (tx_buf->skb)
                        dev_kfree_skb_any(tx_buf->skb);
 
@@ -5609,7 +5615,7 @@ static int mvpp2_txq_init(struct mvpp2_port *port,
 
                txq_pcpu->tso_headers =
                        dma_alloc_coherent(port->dev->dev.parent,
-                                          MVPP2_AGGR_TXQ_SIZE * TSO_HEADER_SIZE,
+                                          txq_pcpu->size * TSO_HEADER_SIZE,
                                           &txq_pcpu->tso_headers_dma,
                                           GFP_KERNEL);
                if (!txq_pcpu->tso_headers)
@@ -5623,7 +5629,7 @@ cleanup:
                kfree(txq_pcpu->buffs);
 
                dma_free_coherent(port->dev->dev.parent,
-                                 MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+                                 txq_pcpu->size * TSO_HEADER_SIZE,
                                  txq_pcpu->tso_headers,
                                  txq_pcpu->tso_headers_dma);
        }
@@ -5647,7 +5653,7 @@ static void mvpp2_txq_deinit(struct mvpp2_port *port,
                kfree(txq_pcpu->buffs);
 
                dma_free_coherent(port->dev->dev.parent,
-                                 MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+                                 txq_pcpu->size * TSO_HEADER_SIZE,
                                  txq_pcpu->tso_headers,
                                  txq_pcpu->tso_headers_dma);
        }
@@ -6212,12 +6218,15 @@ static inline void
 tx_desc_unmap_put(struct mvpp2_port *port, struct mvpp2_tx_queue *txq,
                  struct mvpp2_tx_desc *desc)
 {
+       struct mvpp2_txq_pcpu *txq_pcpu = this_cpu_ptr(txq->pcpu);
+
        dma_addr_t buf_dma_addr =
                mvpp2_txdesc_dma_addr_get(port, desc);
        size_t buf_sz =
                mvpp2_txdesc_size_get(port, desc);
-       dma_unmap_single(port->dev->dev.parent, buf_dma_addr,
-                        buf_sz, DMA_TO_DEVICE);
+       if (!IS_TSO_HEADER(txq_pcpu, buf_dma_addr))
+               dma_unmap_single(port->dev->dev.parent, buf_dma_addr,
+                                buf_sz, DMA_TO_DEVICE);
        mvpp2_txq_desc_put(txq);
 }
 
@@ -6490,7 +6499,7 @@ out:
        }
 
        /* Finalize TX processing */
-       if (txq_pcpu->count >= txq->done_pkts_coal)
+       if (!port->has_tx_irqs && txq_pcpu->count >= txq->done_pkts_coal)
                mvpp2_txq_done(port, txq, txq_pcpu);
 
        /* Set the timer in case not all frags were processed */
index ff60cf7342ca5a4170a477ad7fff0ead65cf5df8..fc281712869b2e1c5c3321b46d1e8c5c562fcb74 100644 (file)
@@ -77,35 +77,41 @@ static void add_delayed_event(struct mlx5_priv *priv,
        list_add_tail(&delayed_event->list, &priv->waiting_events_list);
 }
 
-static void fire_delayed_event_locked(struct mlx5_device_context *dev_ctx,
-                                     struct mlx5_core_dev *dev,
-                                     struct mlx5_priv *priv)
+static void delayed_event_release(struct mlx5_device_context *dev_ctx,
+                                 struct mlx5_priv *priv)
 {
+       struct mlx5_core_dev *dev = container_of(priv, struct mlx5_core_dev, priv);
        struct mlx5_delayed_event *de;
        struct mlx5_delayed_event *n;
+       struct list_head temp;
 
-       /* stop delaying events */
-       priv->is_accum_events = false;
+       INIT_LIST_HEAD(&temp);
+
+       spin_lock_irq(&priv->ctx_lock);
 
-       /* fire all accumulated events before new event comes */
-       list_for_each_entry_safe(de, n, &priv->waiting_events_list, list) {
+       priv->is_accum_events = false;
+       list_splice_init(&priv->waiting_events_list, &temp);
+       if (!dev_ctx->context)
+               goto out;
+       list_for_each_entry_safe(de, n, &priv->waiting_events_list, list)
                dev_ctx->intf->event(dev, dev_ctx->context, de->event, de->param);
+
+out:
+       spin_unlock_irq(&priv->ctx_lock);
+
+       list_for_each_entry_safe(de, n, &temp, list) {
                list_del(&de->list);
                kfree(de);
        }
 }
 
-static void cleanup_delayed_evets(struct mlx5_priv *priv)
+/* accumulating events that can come after mlx5_ib calls to
+ * ib_register_device, till adding that interface to the events list.
+ */
+static void delayed_event_start(struct mlx5_priv *priv)
 {
-       struct mlx5_delayed_event *de;
-       struct mlx5_delayed_event *n;
-
        spin_lock_irq(&priv->ctx_lock);
-       priv->is_accum_events = false;
-       list_for_each_entry_safe(de, n, &priv->waiting_events_list, list) {
-               list_del(&de->list);
-               kfree(de);
-       }
+       priv->is_accum_events = true;
        spin_unlock_irq(&priv->ctx_lock);
 }
 
@@ -122,11 +128,8 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
                return;
 
        dev_ctx->intf = intf;
-       /* accumulating events that can come after mlx5_ib calls to
-        * ib_register_device, till adding that interface to the events list.
-        */
 
-       priv->is_accum_events = true;
+       delayed_event_start(priv);
 
        dev_ctx->context = intf->add(dev);
        set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state);
@@ -137,8 +140,6 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
                spin_lock_irq(&priv->ctx_lock);
                list_add_tail(&dev_ctx->list, &priv->ctx_list);
 
-               fire_delayed_event_locked(dev_ctx, dev, priv);
-
 #ifdef CONFIG_INFINIBAND_ON_DEMAND_PAGING
                if (dev_ctx->intf->pfault) {
                        if (priv->pfault) {
@@ -150,11 +151,12 @@ void mlx5_add_device(struct mlx5_interface *intf, struct mlx5_priv *priv)
                }
 #endif
                spin_unlock_irq(&priv->ctx_lock);
-       } else {
-               kfree(dev_ctx);
-                /* delete all accumulated events */
-               cleanup_delayed_evets(priv);
        }
+
+       delayed_event_release(dev_ctx, priv);
+
+       if (!dev_ctx->context)
+               kfree(dev_ctx);
 }
 
 static struct mlx5_device_context *mlx5_get_device(struct mlx5_interface *intf,
@@ -205,17 +207,21 @@ static void mlx5_attach_interface(struct mlx5_interface *intf, struct mlx5_priv
        if (!dev_ctx)
                return;
 
+       delayed_event_start(priv);
        if (intf->attach) {
                if (test_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state))
-                       return;
+                       goto out;
                intf->attach(dev, dev_ctx->context);
                set_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state);
        } else {
                if (test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state))
-                       return;
+                       goto out;
                dev_ctx->context = intf->add(dev);
                set_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state);
        }
+
+out:
+       delayed_event_release(dev_ctx, priv);
 }
 
 void mlx5_attach_device(struct mlx5_core_dev *dev)
@@ -414,8 +420,14 @@ void mlx5_core_event(struct mlx5_core_dev *dev, enum mlx5_dev_event event,
        if (priv->is_accum_events)
                add_delayed_event(priv, dev, event, param);
 
+       /* After mlx5_detach_device, the dev_ctx->intf is still set and dev_ctx is
+        * still in priv->ctx_list. In this case, only notify the dev_ctx if its
+        * ADDED or ATTACHED bit are set.
+        */
        list_for_each_entry(dev_ctx, &priv->ctx_list, list)
-               if (dev_ctx->intf->event)
+               if (dev_ctx->intf->event &&
+                   (test_bit(MLX5_INTERFACE_ADDED, &dev_ctx->state) ||
+                    test_bit(MLX5_INTERFACE_ATTACHED, &dev_ctx->state)))
                        dev_ctx->intf->event(dev, dev_ctx->context, event, param);
 
        spin_unlock_irqrestore(&priv->ctx_lock, flags);
index c1d384fca4dc1195a1d0b76677176b7dfcbad538..51c4cc00a186589734121efc796f2606c0e2c3fe 100644 (file)
 #define MLX5E_CEE_STATE_UP    1
 #define MLX5E_CEE_STATE_DOWN  0
 
+enum {
+       MLX5E_VENDOR_TC_GROUP_NUM = 7,
+       MLX5E_LOWEST_PRIO_GROUP   = 0,
+};
+
 /* If dcbx mode is non-host set the dcbx mode to host.
  */
 static int mlx5e_dcbnl_set_dcbx_mode(struct mlx5e_priv *priv,
@@ -85,6 +90,9 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
 {
        struct mlx5e_priv *priv = netdev_priv(netdev);
        struct mlx5_core_dev *mdev = priv->mdev;
+       u8 tc_group[IEEE_8021QAZ_MAX_TCS];
+       bool is_tc_group_6_exist = false;
+       bool is_zero_bw_ets_tc = false;
        int err = 0;
        int i;
 
@@ -96,37 +104,64 @@ static int mlx5e_dcbnl_ieee_getets(struct net_device *netdev,
                err = mlx5_query_port_prio_tc(mdev, i, &ets->prio_tc[i]);
                if (err)
                        return err;
-       }
 
-       for (i = 0; i < ets->ets_cap; i++) {
+               err = mlx5_query_port_tc_group(mdev, i, &tc_group[i]);
+               if (err)
+                       return err;
+
                err = mlx5_query_port_tc_bw_alloc(mdev, i, &ets->tc_tx_bw[i]);
                if (err)
                        return err;
+
+               if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC &&
+                   tc_group[i] == (MLX5E_LOWEST_PRIO_GROUP + 1))
+                       is_zero_bw_ets_tc = true;
+
+               if (tc_group[i] == (MLX5E_VENDOR_TC_GROUP_NUM - 1))
+                       is_tc_group_6_exist = true;
+       }
+
+       /* Report 0% ets tc if exits*/
+       if (is_zero_bw_ets_tc) {
+               for (i = 0; i < ets->ets_cap; i++)
+                       if (tc_group[i] == MLX5E_LOWEST_PRIO_GROUP)
+                               ets->tc_tx_bw[i] = 0;
+       }
+
+       /* Update tc_tsa based on fw setting*/
+       for (i = 0; i < ets->ets_cap; i++) {
                if (ets->tc_tx_bw[i] < MLX5E_MAX_BW_ALLOC)
                        priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_ETS;
+               else if (tc_group[i] == MLX5E_VENDOR_TC_GROUP_NUM &&
+                        !is_tc_group_6_exist)
+                       priv->dcbx.tc_tsa[i] = IEEE_8021QAZ_TSA_VENDOR;
        }
-
        memcpy(ets->tc_tsa, priv->dcbx.tc_tsa, sizeof(ets->tc_tsa));
 
        return err;
 }
 
-enum {
-       MLX5E_VENDOR_TC_GROUP_NUM = 7,
-       MLX5E_ETS_TC_GROUP_NUM    = 0,
-};
-
 static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc)
 {
        bool any_tc_mapped_to_ets = false;
+       bool ets_zero_bw = false;
        int strict_group;
        int i;
 
-       for (i = 0; i <= max_tc; i++)
-               if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS)
+       for (i = 0; i <= max_tc; i++) {
+               if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
                        any_tc_mapped_to_ets = true;
+                       if (!ets->tc_tx_bw[i])
+                               ets_zero_bw = true;
+               }
+       }
 
-       strict_group = any_tc_mapped_to_ets ? 1 : 0;
+       /* strict group has higher priority than ets group */
+       strict_group = MLX5E_LOWEST_PRIO_GROUP;
+       if (any_tc_mapped_to_ets)
+               strict_group++;
+       if (ets_zero_bw)
+               strict_group++;
 
        for (i = 0; i <= max_tc; i++) {
                switch (ets->tc_tsa[i]) {
@@ -137,7 +172,9 @@ static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc)
                        tc_group[i] = strict_group++;
                        break;
                case IEEE_8021QAZ_TSA_ETS:
-                       tc_group[i] = MLX5E_ETS_TC_GROUP_NUM;
+                       tc_group[i] = MLX5E_LOWEST_PRIO_GROUP;
+                       if (ets->tc_tx_bw[i] && ets_zero_bw)
+                               tc_group[i] = MLX5E_LOWEST_PRIO_GROUP + 1;
                        break;
                }
        }
@@ -146,8 +183,22 @@ static void mlx5e_build_tc_group(struct ieee_ets *ets, u8 *tc_group, int max_tc)
 static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw,
                                 u8 *tc_group, int max_tc)
 {
+       int bw_for_ets_zero_bw_tc = 0;
+       int last_ets_zero_bw_tc = -1;
+       int num_ets_zero_bw = 0;
        int i;
 
+       for (i = 0; i <= max_tc; i++) {
+               if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS &&
+                   !ets->tc_tx_bw[i]) {
+                       num_ets_zero_bw++;
+                       last_ets_zero_bw_tc = i;
+               }
+       }
+
+       if (num_ets_zero_bw)
+               bw_for_ets_zero_bw_tc = MLX5E_MAX_BW_ALLOC / num_ets_zero_bw;
+
        for (i = 0; i <= max_tc; i++) {
                switch (ets->tc_tsa[i]) {
                case IEEE_8021QAZ_TSA_VENDOR:
@@ -157,12 +208,26 @@ static void mlx5e_build_tc_tx_bw(struct ieee_ets *ets, u8 *tc_tx_bw,
                        tc_tx_bw[i] = MLX5E_MAX_BW_ALLOC;
                        break;
                case IEEE_8021QAZ_TSA_ETS:
-                       tc_tx_bw[i] = ets->tc_tx_bw[i];
+                       tc_tx_bw[i] = ets->tc_tx_bw[i] ?
+                                     ets->tc_tx_bw[i] :
+                                     bw_for_ets_zero_bw_tc;
                        break;
                }
        }
+
+       /* Make sure the total bw for ets zero bw group is 100% */
+       if (last_ets_zero_bw_tc != -1)
+               tc_tx_bw[last_ets_zero_bw_tc] +=
+                       MLX5E_MAX_BW_ALLOC % num_ets_zero_bw;
 }
 
+/* If there are ETS BW 0,
+ *   Set ETS group # to 1 for all ETS non zero BW tcs. Their sum must be 100%.
+ *   Set group #0 to all the ETS BW 0 tcs and
+ *     equally splits the 100% BW between them
+ *   Report both group #0 and #1 as ETS type.
+ *     All the tcs in group #0 will be reported with 0% BW.
+ */
 int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
 {
        struct mlx5_core_dev *mdev = priv->mdev;
@@ -188,7 +253,6 @@ int mlx5e_dcbnl_ieee_setets_core(struct mlx5e_priv *priv, struct ieee_ets *ets)
                return err;
 
        memcpy(priv->dcbx.tc_tsa, ets->tc_tsa, sizeof(ets->tc_tsa));
-
        return err;
 }
 
@@ -209,17 +273,9 @@ static int mlx5e_dbcnl_validate_ets(struct net_device *netdev,
        }
 
        /* Validate Bandwidth Sum */
-       for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
-               if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS) {
-                       if (!ets->tc_tx_bw[i]) {
-                               netdev_err(netdev,
-                                          "Failed to validate ETS: BW 0 is illegal\n");
-                               return -EINVAL;
-                       }
-
+       for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
+               if (ets->tc_tsa[i] == IEEE_8021QAZ_TSA_ETS)
                        bw_sum += ets->tc_tx_bw[i];
-               }
-       }
 
        if (bw_sum != 0 && bw_sum != 100) {
                netdev_err(netdev,
@@ -533,8 +589,7 @@ static void mlx5e_dcbnl_getpgtccfgtx(struct net_device *netdev,
 static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
                                      int pgid, u8 *bw_pct)
 {
-       struct mlx5e_priv *priv = netdev_priv(netdev);
-       struct mlx5_core_dev *mdev = priv->mdev;
+       struct ieee_ets ets;
 
        if (pgid >= CEE_DCBX_MAX_PGS) {
                netdev_err(netdev,
@@ -542,8 +597,8 @@ static void mlx5e_dcbnl_getpgbwgcfgtx(struct net_device *netdev,
                return;
        }
 
-       if (mlx5_query_port_tc_bw_alloc(mdev, pgid, bw_pct))
-               *bw_pct = 0;
+       mlx5e_dcbnl_ieee_getets(netdev, &ets);
+       *bw_pct = ets.tc_tx_bw[pgid];
 }
 
 static void mlx5e_dcbnl_setpfccfg(struct net_device *netdev,
@@ -739,8 +794,6 @@ static void mlx5e_ets_init(struct mlx5e_priv *priv)
                ets.prio_tc[i] = i;
        }
 
-       memcpy(priv->dcbx.tc_tsa, ets.tc_tsa, sizeof(ets.tc_tsa));
-
        /* tclass[prio=0]=1, tclass[prio=1]=0, tclass[prio=i]=i (for i>1) */
        ets.prio_tc[0] = 1;
        ets.prio_tc[1] = 0;
index 1aa2028ed995d8c4017e0442546a8c466b9a7056..9ba1f72060aae4c57a55c9d7a4c049e1a6f8a69b 100644 (file)
@@ -78,9 +78,11 @@ struct mlx5e_tc_flow {
 };
 
 struct mlx5e_tc_flow_parse_attr {
+       struct ip_tunnel_info tun_info;
        struct mlx5_flow_spec spec;
        int num_mod_hdr_actions;
        void *mod_hdr_actions;
+       int mirred_ifindex;
 };
 
 enum {
@@ -322,6 +324,12 @@ static void mlx5e_tc_del_nic_flow(struct mlx5e_priv *priv,
 static void mlx5e_detach_encap(struct mlx5e_priv *priv,
                               struct mlx5e_tc_flow *flow);
 
+static int mlx5e_attach_encap(struct mlx5e_priv *priv,
+                             struct ip_tunnel_info *tun_info,
+                             struct net_device *mirred_dev,
+                             struct net_device **encap_dev,
+                             struct mlx5e_tc_flow *flow);
+
 static struct mlx5_flow_handle *
 mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
                      struct mlx5e_tc_flow_parse_attr *parse_attr,
@@ -329,9 +337,27 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
 {
        struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5_esw_flow_attr *attr = flow->esw_attr;
-       struct mlx5_flow_handle *rule;
+       struct net_device *out_dev, *encap_dev = NULL;
+       struct mlx5_flow_handle *rule = NULL;
+       struct mlx5e_rep_priv *rpriv;
+       struct mlx5e_priv *out_priv;
        int err;
 
+       if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP) {
+               out_dev = __dev_get_by_index(dev_net(priv->netdev),
+                                            attr->parse_attr->mirred_ifindex);
+               err = mlx5e_attach_encap(priv, &parse_attr->tun_info,
+                                        out_dev, &encap_dev, flow);
+               if (err) {
+                       rule = ERR_PTR(err);
+                       if (err != -EAGAIN)
+                               goto err_attach_encap;
+               }
+               out_priv = netdev_priv(encap_dev);
+               rpriv = out_priv->ppriv;
+               attr->out_rep = rpriv->rep;
+       }
+
        err = mlx5_eswitch_add_vlan_action(esw, attr);
        if (err) {
                rule = ERR_PTR(err);
@@ -347,10 +373,14 @@ mlx5e_tc_add_fdb_flow(struct mlx5e_priv *priv,
                }
        }
 
-       rule = mlx5_eswitch_add_offloaded_rule(esw, &parse_attr->spec, attr);
-       if (IS_ERR(rule))
-               goto err_add_rule;
-
+       /* we get here if (1) there's no error (rule being null) or when
+        * (2) there's an encap action and we're on -EAGAIN (no valid neigh)
+        */
+       if (rule != ERR_PTR(-EAGAIN)) {
+               rule = mlx5_eswitch_add_offloaded_rule(esw, &parse_attr->spec, attr);
+               if (IS_ERR(rule))
+                       goto err_add_rule;
+       }
        return rule;
 
 err_add_rule:
@@ -361,6 +391,7 @@ err_mod_hdr:
 err_add_vlan:
        if (attr->action & MLX5_FLOW_CONTEXT_ACTION_ENCAP)
                mlx5e_detach_encap(priv, flow);
+err_attach_encap:
        return rule;
 }
 
@@ -389,6 +420,8 @@ static void mlx5e_tc_del_fdb_flow(struct mlx5e_priv *priv,
 void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
                              struct mlx5e_encap_entry *e)
 {
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
+       struct mlx5_esw_flow_attr *esw_attr;
        struct mlx5e_tc_flow *flow;
        int err;
 
@@ -404,10 +437,9 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
        mlx5e_rep_queue_neigh_stats_work(priv);
 
        list_for_each_entry(flow, &e->flows, encap) {
-               flow->esw_attr->encap_id = e->encap_id;
-               flow->rule = mlx5e_tc_add_fdb_flow(priv,
-                                                  flow->esw_attr->parse_attr,
-                                                  flow);
+               esw_attr = flow->esw_attr;
+               esw_attr->encap_id = e->encap_id;
+               flow->rule = mlx5_eswitch_add_offloaded_rule(esw, &esw_attr->parse_attr->spec, esw_attr);
                if (IS_ERR(flow->rule)) {
                        err = PTR_ERR(flow->rule);
                        mlx5_core_warn(priv->mdev, "Failed to update cached encapsulation flow, %d\n",
@@ -421,15 +453,13 @@ void mlx5e_tc_encap_flows_add(struct mlx5e_priv *priv,
 void mlx5e_tc_encap_flows_del(struct mlx5e_priv *priv,
                              struct mlx5e_encap_entry *e)
 {
+       struct mlx5_eswitch *esw = priv->mdev->priv.eswitch;
        struct mlx5e_tc_flow *flow;
-       struct mlx5_fc *counter;
 
        list_for_each_entry(flow, &e->flows, encap) {
                if (flow->flags & MLX5E_TC_FLOW_OFFLOADED) {
                        flow->flags &= ~MLX5E_TC_FLOW_OFFLOADED;
-                       counter = mlx5_flow_rule_counter(flow->rule);
-                       mlx5_del_flow_rules(flow->rule);
-                       mlx5_fc_destroy(priv->mdev, counter);
+                       mlx5_eswitch_del_offloaded_rule(esw, flow->rule, flow->esw_attr);
                }
        }
 
@@ -1942,7 +1972,7 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
 
                if (is_tcf_mirred_egress_redirect(a)) {
                        int ifindex = tcf_mirred_ifindex(a);
-                       struct net_device *out_dev, *encap_dev = NULL;
+                       struct net_device *out_dev;
                        struct mlx5e_priv *out_priv;
 
                        out_dev = __dev_get_by_index(dev_net(priv->netdev), ifindex);
@@ -1955,17 +1985,13 @@ static int parse_tc_fdb_actions(struct mlx5e_priv *priv, struct tcf_exts *exts,
                                rpriv = out_priv->ppriv;
                                attr->out_rep = rpriv->rep;
                        } else if (encap) {
-                               err = mlx5e_attach_encap(priv, info,
-                                                        out_dev, &encap_dev, flow);
-                               if (err && err != -EAGAIN)
-                                       return err;
+                               parse_attr->mirred_ifindex = ifindex;
+                               parse_attr->tun_info = *info;
+                               attr->parse_attr = parse_attr;
                                attr->action |= MLX5_FLOW_CONTEXT_ACTION_ENCAP |
                                        MLX5_FLOW_CONTEXT_ACTION_FWD_DEST |
                                        MLX5_FLOW_CONTEXT_ACTION_COUNT;
-                               out_priv = netdev_priv(encap_dev);
-                               rpriv = out_priv->ppriv;
-                               attr->out_rep = rpriv->rep;
-                               attr->parse_attr = parse_attr;
+                               /* attr->out_rep is resolved when we handle encap */
                        } else {
                                pr_err("devices %s %s not on same switch HW, can't offload forwarding\n",
                                       priv->netdev->name, out_dev->name);
@@ -2047,7 +2073,7 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
        if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
                err = parse_tc_fdb_actions(priv, f->exts, parse_attr, flow);
                if (err < 0)
-                       goto err_handle_encap_flow;
+                       goto err_free;
                flow->rule = mlx5e_tc_add_fdb_flow(priv, parse_attr, flow);
        } else {
                err = parse_tc_nic_actions(priv, f->exts, parse_attr, flow);
@@ -2058,10 +2084,13 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
 
        if (IS_ERR(flow->rule)) {
                err = PTR_ERR(flow->rule);
-               goto err_free;
+               if (err != -EAGAIN)
+                       goto err_free;
        }
 
-       flow->flags |= MLX5E_TC_FLOW_OFFLOADED;
+       if (err != -EAGAIN)
+               flow->flags |= MLX5E_TC_FLOW_OFFLOADED;
+
        err = rhashtable_insert_fast(&tc->ht, &flow->node,
                                     tc->ht_params);
        if (err)
@@ -2075,16 +2104,6 @@ int mlx5e_configure_flower(struct mlx5e_priv *priv,
 err_del_rule:
        mlx5e_tc_del_flow(priv, flow);
 
-err_handle_encap_flow:
-       if (err == -EAGAIN) {
-               err = rhashtable_insert_fast(&tc->ht, &flow->node,
-                                            tc->ht_params);
-               if (err)
-                       mlx5e_tc_del_flow(priv, flow);
-               else
-                       return 0;
-       }
-
 err_free:
        kvfree(parse_attr);
        kfree(flow);
index 8aea0a065e5636badb85c5a5f8d33c73bdac2502..db86e1506c8b67fa8849940c4adc958fb783ac92 100644 (file)
@@ -356,10 +356,11 @@ void mlx5_drain_health_wq(struct mlx5_core_dev *dev)
 void mlx5_drain_health_recovery(struct mlx5_core_dev *dev)
 {
        struct mlx5_core_health *health = &dev->priv.health;
+       unsigned long flags;
 
-       spin_lock(&health->wq_lock);
+       spin_lock_irqsave(&health->wq_lock, flags);
        set_bit(MLX5_DROP_NEW_RECOVERY_WORK, &health->flags);
-       spin_unlock(&health->wq_lock);
+       spin_unlock_irqrestore(&health->wq_lock, flags);
        cancel_delayed_work_sync(&dev->priv.health.recover_work);
 }
 
index 1975d4388d4f77d2380209ad6bd6bfd9733e402e..e07061f565d6432d1c6c88b78468e038f20572cc 100644 (file)
@@ -677,6 +677,27 @@ int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, u8 *tc_group)
 }
 EXPORT_SYMBOL_GPL(mlx5_set_port_tc_group);
 
+int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
+                            u8 tc, u8 *tc_group)
+{
+       u32 out[MLX5_ST_SZ_DW(qetc_reg)];
+       void *ets_tcn_conf;
+       int err;
+
+       err = mlx5_query_port_qetcr_reg(mdev, out, sizeof(out));
+       if (err)
+               return err;
+
+       ets_tcn_conf = MLX5_ADDR_OF(qetc_reg, out,
+                                   tc_configuration[tc]);
+
+       *tc_group = MLX5_GET(ets_tcn_config_reg, ets_tcn_conf,
+                            group);
+
+       return 0;
+}
+EXPORT_SYMBOL_GPL(mlx5_query_port_tc_group);
+
 int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw)
 {
        u32 in[MLX5_ST_SZ_DW(qetc_reg)] = {0};
index 12c3a44491203824ef4eaa51acdee5b91dfdb194..c0dcfa05b0771589631e1c20fa68801622abb6c4 100644 (file)
@@ -294,7 +294,7 @@ mlxsw_i2c_write(struct device *dev, size_t in_mbox_size, u8 *in_mbox, int num,
                write_tran.len = MLXSW_I2C_ADDR_WIDTH + chunk_size;
                mlxsw_i2c_set_slave_addr(tran_buf, off);
                memcpy(&tran_buf[MLXSW_I2C_ADDR_BUF_SIZE], in_mbox +
-                      chunk_size * i, chunk_size);
+                      MLXSW_I2C_BLK_MAX * i, chunk_size);
 
                j = 0;
                end = jiffies + timeout;
index 4afc8486eb9a7ee5242d58393fbba643e2b75d74..5acfbe5b8b9d2f51f49a403e04f9e75314e1df49 100644 (file)
@@ -5827,6 +5827,29 @@ MLXSW_ITEM32(reg, mtmp, mtr, 0x08, 30, 1);
  */
 MLXSW_ITEM32(reg, mtmp, max_temperature, 0x08, 0, 16);
 
+/* reg_mtmp_tee
+ * Temperature Event Enable.
+ * 0 - Do not generate event
+ * 1 - Generate event
+ * 2 - Generate single event
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mtmp, tee, 0x0C, 30, 2);
+
+#define MLXSW_REG_MTMP_THRESH_HI 0x348 /* 105 Celsius */
+
+/* reg_mtmp_temperature_threshold_hi
+ * High threshold for Temperature Warning Event. In 0.125 Celsius.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mtmp, temperature_threshold_hi, 0x0C, 0, 16);
+
+/* reg_mtmp_temperature_threshold_lo
+ * Low threshold for Temperature Warning Event. In 0.125 Celsius.
+ * Access: RW
+ */
+MLXSW_ITEM32(reg, mtmp, temperature_threshold_lo, 0x10, 0, 16);
+
 #define MLXSW_REG_MTMP_SENSOR_NAME_SIZE 8
 
 /* reg_mtmp_sensor_name
@@ -5843,6 +5866,8 @@ static inline void mlxsw_reg_mtmp_pack(char *payload, u8 sensor_index,
        mlxsw_reg_mtmp_sensor_index_set(payload, sensor_index);
        mlxsw_reg_mtmp_mte_set(payload, max_temp_enable);
        mlxsw_reg_mtmp_mtr_set(payload, max_temp_reset);
+       mlxsw_reg_mtmp_temperature_threshold_hi_set(payload,
+                                                   MLXSW_REG_MTMP_THRESH_HI);
 }
 
 static inline void mlxsw_reg_mtmp_unpack(char *payload, unsigned int *p_temp,
index db9750695dc7f63cf8d9861026995098aa9cbcf0..8ea9320014ee78141f71f883452bb81926e208c6 100644 (file)
@@ -110,6 +110,8 @@ nfp_fl_output(struct nfp_fl_output *output, const struct tc_action *action,
         */
        if (!switchdev_port_same_parent_id(in_dev, out_dev))
                return -EOPNOTSUPP;
+       if (!nfp_netdev_is_nfp_repr(out_dev))
+               return -EOPNOTSUPP;
 
        output->port = cpu_to_be32(nfp_repr_get_port_id(out_dev));
        if (!output->port)
index 5efef8001edf237a8539118f8b32727eb1816b15..3256e5cbad2717c0d3928109cbb677c095e3247c 100644 (file)
@@ -74,7 +74,7 @@ static int dwc_eth_dwmac_config_dt(struct platform_device *pdev,
                plat_dat->axi->axi_wr_osr_lmt--;
        }
 
-       if (of_property_read_u32(np, "read,read-requests",
+       if (of_property_read_u32(np, "snps,read-requests",
                                 &plat_dat->axi->axi_rd_osr_lmt)) {
                /**
                 * Since the register has a reset value of 1, if property
index 8a280b48e3a9fd0c7ada914f2ceea3618e9e34cf..6383695004a53ef14e6c72beba5b4f8b1677d5f5 100644 (file)
@@ -150,6 +150,13 @@ static void stmmac_mtl_setup(struct platform_device *pdev,
        plat->rx_queues_to_use = 1;
        plat->tx_queues_to_use = 1;
 
+       /* First Queue must always be in DCB mode. As MTL_QUEUE_DCB = 1 we need
+        * to always set this, otherwise Queue will be classified as AVB
+        * (because MTL_QUEUE_AVB = 0).
+        */
+       plat->rx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+       plat->tx_queues_cfg[0].mode_to_use = MTL_QUEUE_DCB;
+
        rx_node = of_parse_phandle(pdev->dev.of_node, "snps,mtl-rx-config", 0);
        if (!rx_node)
                return;
index 5dea2063dbc878d1f45a56c7cfea470f820ec601..0bcc07f346c3ecb26e5d8354adb1fcd547733e84 100644 (file)
@@ -197,8 +197,8 @@ static int ipvtap_init(void)
 {
        int err;
 
-       err = tap_create_cdev(&ipvtap_cdev, &ipvtap_major, "ipvtap");
-
+       err = tap_create_cdev(&ipvtap_cdev, &ipvtap_major, "ipvtap",
+                             THIS_MODULE);
        if (err)
                goto out1;
 
index c2d0ea2fb01933d46e43b84fbf255901f18e5b91..cba5cb3b849a78c7073d5545bd1f8067f6e1db5f 100644 (file)
@@ -204,8 +204,8 @@ static int macvtap_init(void)
 {
        int err;
 
-       err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap");
-
+       err = tap_create_cdev(&macvtap_cdev, &macvtap_major, "macvtap",
+                             THIS_MODULE);
        if (err)
                goto out1;
 
index 15cbcdba618a81363765a78217f4d875518386cc..4d02b27df0445e7c1ad6f0774e44a5b7013bb05e 100644 (file)
@@ -681,9 +681,11 @@ static int m88e1116r_config_init(struct phy_device *phydev)
        if (err < 0)
                return err;
 
-       err = m88e1121_config_aneg_rgmii_delays(phydev);
-       if (err < 0)
-               return err;
+       if (phy_interface_is_rgmii(phydev)) {
+               err = m88e1121_config_aneg_rgmii_delays(phydev);
+               if (err < 0)
+                       return err;
+       }
 
        err = genphy_soft_reset(phydev);
        if (err < 0)
index 21b71ae947fdbc2e3bbf7d5ef7c17d17aa560ba2..6c0c84c33e1fb62f259881de910934470b6a8929 100644 (file)
@@ -517,6 +517,10 @@ static int tap_open(struct inode *inode, struct file *file)
                                             &tap_proto, 0);
        if (!q)
                goto err;
+       if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL)) {
+               sk_free(&q->sk);
+               goto err;
+       }
 
        RCU_INIT_POINTER(q->sock.wq, &q->wq);
        init_waitqueue_head(&q->wq.wait);
@@ -540,22 +544,18 @@ static int tap_open(struct inode *inode, struct file *file)
        if ((tap->dev->features & NETIF_F_HIGHDMA) && (tap->dev->features & NETIF_F_SG))
                sock_set_flag(&q->sk, SOCK_ZEROCOPY);
 
-       err = -ENOMEM;
-       if (skb_array_init(&q->skb_array, tap->dev->tx_queue_len, GFP_KERNEL))
-               goto err_array;
-
        err = tap_set_queue(tap, file, q);
-       if (err)
-               goto err_queue;
+       if (err) {
+               /* tap_sock_destruct() will take care of freeing skb_array */
+               goto err_put;
+       }
 
        dev_put(tap->dev);
 
        rtnl_unlock();
        return err;
 
-err_queue:
-       skb_array_cleanup(&q->skb_array);
-err_array:
+err_put:
        sock_put(&q->sk);
 err:
        if (tap)
@@ -1032,6 +1032,8 @@ static long tap_ioctl(struct file *file, unsigned int cmd,
        case TUNSETSNDBUF:
                if (get_user(s, sp))
                        return -EFAULT;
+               if (s <= 0)
+                       return -EINVAL;
 
                q->sk.sk_sndbuf = s;
                return 0;
@@ -1249,8 +1251,8 @@ static int tap_list_add(dev_t major, const char *device_name)
        return 0;
 }
 
-int tap_create_cdev(struct cdev *tap_cdev,
-                   dev_t *tap_major, const char *device_name)
+int tap_create_cdev(struct cdev *tap_cdev, dev_t *tap_major,
+                   const char *device_name, struct module *module)
 {
        int err;
 
@@ -1259,6 +1261,7 @@ int tap_create_cdev(struct cdev *tap_cdev,
                goto out1;
 
        cdev_init(tap_cdev, &tap_fops);
+       tap_cdev->owner = module;
        err = cdev_add(tap_cdev, *tap_major, TAP_NUM_DEVS);
        if (err)
                goto out2;
index e21bf90b819f8f77e4886a6d1ff7c7b5ca12bad0..42bb820a56c92e812d93e66ae2e87a9e0648f001 100644 (file)
@@ -1286,6 +1286,7 @@ static struct sk_buff *tun_build_skb(struct tun_struct *tun,
        buflen += SKB_DATA_ALIGN(len + pad);
        rcu_read_unlock();
 
+       alloc_frag->offset = ALIGN((u64)alloc_frag->offset, SMP_CACHE_BYTES);
        if (unlikely(!skb_page_frag_refill(buflen, alloc_frag, GFP_KERNEL)))
                return ERR_PTR(-ENOMEM);
 
@@ -2028,7 +2029,7 @@ static int tun_set_iff(struct net *net, struct file *file, struct ifreq *ifr)
                if (!dev)
                        return -ENOMEM;
                err = dev_get_valid_name(net, dev, name);
-               if (err)
+               if (err < 0)
                        goto err_free_dev;
 
                dev_net_set(dev, net);
@@ -2428,6 +2429,10 @@ static long __tun_chr_ioctl(struct file *file, unsigned int cmd,
                        ret = -EFAULT;
                        break;
                }
+               if (sndbuf <= 0) {
+                       ret = -EINVAL;
+                       break;
+               }
 
                tun->sndbuf = sndbuf;
                tun_set_sndbuf(tun);
index 52ea80bcd6392eaeb5917f6f9600196ae08af9fe..3e7a3ac3a36236054b897bc7beda770a765a95e5 100644 (file)
@@ -561,6 +561,7 @@ static const struct driver_info wwan_info = {
 #define HP_VENDOR_ID           0x03f0
 #define MICROSOFT_VENDOR_ID    0x045e
 #define UBLOX_VENDOR_ID                0x1546
+#define TPLINK_VENDOR_ID       0x2357
 
 static const struct usb_device_id      products[] = {
 /* BLACKLIST !!
@@ -813,6 +814,13 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+       /* TP-LINK UE300 USB 3.0 Ethernet Adapters (based on Realtek RTL8153) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(TPLINK_VENDOR_ID, 0x0601, USB_CLASS_COMM,
+                       USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* WHITELIST!!!
  *
  * CDC Ether uses two interfaces, not necessarily consecutive.
@@ -863,6 +871,12 @@ static const struct usb_device_id  products[] = {
        USB_DEVICE_AND_INTERFACE_INFO(DELL_VENDOR_ID, 0x81ba, USB_CLASS_COMM,
                        USB_CDC_SUBCLASS_ETHERNET, USB_CDC_PROTO_NONE),
        .driver_info = (kernel_ulong_t)&wwan_info,
+}, {
+       /* Huawei ME906 and ME909 */
+       USB_DEVICE_AND_INTERFACE_INFO(HUAWEI_VENDOR_ID, 0x15c1, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
+       .driver_info = (unsigned long)&wwan_info,
 }, {
        /* ZTE modules */
        USB_VENDOR_AND_INTERFACE_INFO(ZTE_VENDOR_ID, USB_CLASS_COMM,
index 941ece08ba7852e5fa9151082af294dec1482192..d51d9abf7986b203350167d6a2fcdcfcddf8b972 100644 (file)
@@ -615,6 +615,7 @@ enum rtl8152_flags {
 #define VENDOR_ID_LENOVO               0x17ef
 #define VENDOR_ID_LINKSYS              0x13b1
 #define VENDOR_ID_NVIDIA               0x0955
+#define VENDOR_ID_TPLINK               0x2357
 
 #define MCU_TYPE_PLA                   0x0100
 #define MCU_TYPE_USB                   0x0000
@@ -5319,6 +5320,7 @@ static const struct usb_device_id rtl8152_table[] = {
        {REALTEK_USB_DEVICE(VENDOR_ID_LENOVO,  0x7214)},
        {REALTEK_USB_DEVICE(VENDOR_ID_LINKSYS, 0x0041)},
        {REALTEK_USB_DEVICE(VENDOR_ID_NVIDIA,  0x09ff)},
+       {REALTEK_USB_DEVICE(VENDOR_ID_TPLINK,  0x0601)},
        {}
 };
 
index 63f749078a1f1051f3f46bec13f1f60c7c64ea5f..0e3f8ed84660e9363552cbf52fc31bff004a08c3 100644 (file)
@@ -346,7 +346,6 @@ out:
 fail:
        dev_put(dev);
        free_netdev(ndev);
-       kfree(lapbeth);
        goto out;
 }
 
index a3f5dc78353fb2fdddbdb6806457b2bc2ece2ac8..0aeeb233af780469fcc907ba5ee0bb53086d606a 100644 (file)
@@ -550,6 +550,11 @@ static int ath10k_htt_rx_crypto_param_len(struct ath10k *ar,
                return IEEE80211_TKIP_IV_LEN;
        case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
                return IEEE80211_CCMP_HDR_LEN;
+       case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2:
+               return IEEE80211_CCMP_256_HDR_LEN;
+       case HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2:
+       case HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2:
+               return IEEE80211_GCMP_HDR_LEN;
        case HTT_RX_MPDU_ENCRYPT_WEP128:
        case HTT_RX_MPDU_ENCRYPT_WAPI:
                break;
@@ -575,6 +580,11 @@ static int ath10k_htt_rx_crypto_tail_len(struct ath10k *ar,
                return IEEE80211_TKIP_ICV_LEN;
        case HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2:
                return IEEE80211_CCMP_MIC_LEN;
+       case HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2:
+               return IEEE80211_CCMP_256_MIC_LEN;
+       case HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2:
+       case HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2:
+               return IEEE80211_GCMP_MIC_LEN;
        case HTT_RX_MPDU_ENCRYPT_WEP128:
        case HTT_RX_MPDU_ENCRYPT_WAPI:
                break;
@@ -1051,9 +1061,21 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
        hdr = (void *)msdu->data;
 
        /* Tail */
-       if (status->flag & RX_FLAG_IV_STRIPPED)
+       if (status->flag & RX_FLAG_IV_STRIPPED) {
                skb_trim(msdu, msdu->len -
                         ath10k_htt_rx_crypto_tail_len(ar, enctype));
+       } else {
+               /* MIC */
+               if ((status->flag & RX_FLAG_MIC_STRIPPED) &&
+                   enctype == HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
+                       skb_trim(msdu, msdu->len - 8);
+
+               /* ICV */
+               if (status->flag & RX_FLAG_ICV_STRIPPED &&
+                   enctype != HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2)
+                       skb_trim(msdu, msdu->len -
+                                ath10k_htt_rx_crypto_tail_len(ar, enctype));
+       }
 
        /* MMIC */
        if ((status->flag & RX_FLAG_MMIC_STRIPPED) &&
@@ -1075,7 +1097,8 @@ static void ath10k_htt_rx_h_undecap_raw(struct ath10k *ar,
 static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
                                          struct sk_buff *msdu,
                                          struct ieee80211_rx_status *status,
-                                         const u8 first_hdr[64])
+                                         const u8 first_hdr[64],
+                                         enum htt_rx_mpdu_encrypt_type enctype)
 {
        struct ieee80211_hdr *hdr;
        struct htt_rx_desc *rxd;
@@ -1083,6 +1106,7 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
        u8 da[ETH_ALEN];
        u8 sa[ETH_ALEN];
        int l3_pad_bytes;
+       int bytes_aligned = ar->hw_params.decap_align_bytes;
 
        /* Delivered decapped frame:
         * [nwifi 802.11 header] <-- replaced with 802.11 hdr
@@ -1111,6 +1135,14 @@ static void ath10k_htt_rx_h_undecap_nwifi(struct ath10k *ar,
        /* push original 802.11 header */
        hdr = (struct ieee80211_hdr *)first_hdr;
        hdr_len = ieee80211_hdrlen(hdr->frame_control);
+
+       if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
+               memcpy(skb_push(msdu,
+                               ath10k_htt_rx_crypto_param_len(ar, enctype)),
+                      (void *)hdr + round_up(hdr_len, bytes_aligned),
+                       ath10k_htt_rx_crypto_param_len(ar, enctype));
+       }
+
        memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
 
        /* original 802.11 header has a different DA and in
@@ -1171,6 +1203,7 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
        u8 sa[ETH_ALEN];
        int l3_pad_bytes;
        struct htt_rx_desc *rxd;
+       int bytes_aligned = ar->hw_params.decap_align_bytes;
 
        /* Delivered decapped frame:
         * [eth header] <-- replaced with 802.11 hdr & rfc1042/llc
@@ -1199,6 +1232,14 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
        /* push original 802.11 header */
        hdr = (struct ieee80211_hdr *)first_hdr;
        hdr_len = ieee80211_hdrlen(hdr->frame_control);
+
+       if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
+               memcpy(skb_push(msdu,
+                               ath10k_htt_rx_crypto_param_len(ar, enctype)),
+                      (void *)hdr + round_up(hdr_len, bytes_aligned),
+                       ath10k_htt_rx_crypto_param_len(ar, enctype));
+       }
+
        memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
 
        /* original 802.11 header has a different DA and in
@@ -1212,12 +1253,14 @@ static void ath10k_htt_rx_h_undecap_eth(struct ath10k *ar,
 static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
                                         struct sk_buff *msdu,
                                         struct ieee80211_rx_status *status,
-                                        const u8 first_hdr[64])
+                                        const u8 first_hdr[64],
+                                        enum htt_rx_mpdu_encrypt_type enctype)
 {
        struct ieee80211_hdr *hdr;
        size_t hdr_len;
        int l3_pad_bytes;
        struct htt_rx_desc *rxd;
+       int bytes_aligned = ar->hw_params.decap_align_bytes;
 
        /* Delivered decapped frame:
         * [amsdu header] <-- replaced with 802.11 hdr
@@ -1233,6 +1276,14 @@ static void ath10k_htt_rx_h_undecap_snap(struct ath10k *ar,
 
        hdr = (struct ieee80211_hdr *)first_hdr;
        hdr_len = ieee80211_hdrlen(hdr->frame_control);
+
+       if (!(status->flag & RX_FLAG_IV_STRIPPED)) {
+               memcpy(skb_push(msdu,
+                               ath10k_htt_rx_crypto_param_len(ar, enctype)),
+                      (void *)hdr + round_up(hdr_len, bytes_aligned),
+                       ath10k_htt_rx_crypto_param_len(ar, enctype));
+       }
+
        memcpy(skb_push(msdu, hdr_len), hdr, hdr_len);
 }
 
@@ -1267,13 +1318,15 @@ static void ath10k_htt_rx_h_undecap(struct ath10k *ar,
                                            is_decrypted);
                break;
        case RX_MSDU_DECAP_NATIVE_WIFI:
-               ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr);
+               ath10k_htt_rx_h_undecap_nwifi(ar, msdu, status, first_hdr,
+                                             enctype);
                break;
        case RX_MSDU_DECAP_ETHERNET2_DIX:
                ath10k_htt_rx_h_undecap_eth(ar, msdu, status, first_hdr, enctype);
                break;
        case RX_MSDU_DECAP_8023_SNAP_LLC:
-               ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr);
+               ath10k_htt_rx_h_undecap_snap(ar, msdu, status, first_hdr,
+                                            enctype);
                break;
        }
 }
@@ -1316,7 +1369,8 @@ static void ath10k_htt_rx_h_csum_offload(struct sk_buff *msdu)
 
 static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                                 struct sk_buff_head *amsdu,
-                                struct ieee80211_rx_status *status)
+                                struct ieee80211_rx_status *status,
+                                bool fill_crypt_header)
 {
        struct sk_buff *first;
        struct sk_buff *last;
@@ -1326,7 +1380,6 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
        enum htt_rx_mpdu_encrypt_type enctype;
        u8 first_hdr[64];
        u8 *qos;
-       size_t hdr_len;
        bool has_fcs_err;
        bool has_crypto_err;
        bool has_tkip_err;
@@ -1351,15 +1404,17 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
         * decapped header. It'll be used for undecapping of each MSDU.
         */
        hdr = (void *)rxd->rx_hdr_status;
-       hdr_len = ieee80211_hdrlen(hdr->frame_control);
-       memcpy(first_hdr, hdr, hdr_len);
+       memcpy(first_hdr, hdr, RX_HTT_HDR_STATUS_LEN);
 
        /* Each A-MSDU subframe will use the original header as the base and be
         * reported as a separate MSDU so strip the A-MSDU bit from QoS Ctl.
         */
        hdr = (void *)first_hdr;
-       qos = ieee80211_get_qos_ctl(hdr);
-       qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+
+       if (ieee80211_is_data_qos(hdr->frame_control)) {
+               qos = ieee80211_get_qos_ctl(hdr);
+               qos[0] &= ~IEEE80211_QOS_CTL_A_MSDU_PRESENT;
+       }
 
        /* Some attention flags are valid only in the last MSDU. */
        last = skb_peek_tail(amsdu);
@@ -1406,9 +1461,14 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                status->flag |= RX_FLAG_DECRYPTED;
 
                if (likely(!is_mgmt))
-                       status->flag |= RX_FLAG_IV_STRIPPED |
-                                       RX_FLAG_MMIC_STRIPPED;
-}
+                       status->flag |= RX_FLAG_MMIC_STRIPPED;
+
+               if (fill_crypt_header)
+                       status->flag |= RX_FLAG_MIC_STRIPPED |
+                                       RX_FLAG_ICV_STRIPPED;
+               else
+                       status->flag |= RX_FLAG_IV_STRIPPED;
+       }
 
        skb_queue_walk(amsdu, msdu) {
                ath10k_htt_rx_h_csum_offload(msdu);
@@ -1424,6 +1484,9 @@ static void ath10k_htt_rx_h_mpdu(struct ath10k *ar,
                if (is_mgmt)
                        continue;
 
+               if (fill_crypt_header)
+                       continue;
+
                hdr = (void *)msdu->data;
                hdr->frame_control &= ~__cpu_to_le16(IEEE80211_FCTL_PROTECTED);
        }
@@ -1434,6 +1497,9 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
                                    struct ieee80211_rx_status *status)
 {
        struct sk_buff *msdu;
+       struct sk_buff *first_subframe;
+
+       first_subframe = skb_peek(amsdu);
 
        while ((msdu = __skb_dequeue(amsdu))) {
                /* Setup per-MSDU flags */
@@ -1442,6 +1508,13 @@ static void ath10k_htt_rx_h_deliver(struct ath10k *ar,
                else
                        status->flag |= RX_FLAG_AMSDU_MORE;
 
+               if (msdu == first_subframe) {
+                       first_subframe = NULL;
+                       status->flag &= ~RX_FLAG_ALLOW_SAME_PN;
+               } else {
+                       status->flag |= RX_FLAG_ALLOW_SAME_PN;
+               }
+
                ath10k_process_rx(ar, status, msdu);
        }
 }
@@ -1584,7 +1657,7 @@ static int ath10k_htt_rx_handle_amsdu(struct ath10k_htt *htt)
                ath10k_htt_rx_h_unchain(ar, &amsdu);
 
        ath10k_htt_rx_h_filter(ar, &amsdu, rx_status);
-       ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status);
+       ath10k_htt_rx_h_mpdu(ar, &amsdu, rx_status, true);
        ath10k_htt_rx_h_deliver(ar, &amsdu, rx_status);
 
        return num_msdus;
@@ -1745,8 +1818,7 @@ static void ath10k_htt_rx_delba(struct ath10k *ar, struct htt_resp *resp)
 }
 
 static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
-                                      struct sk_buff_head *amsdu,
-                                      int budget_left)
+                                      struct sk_buff_head *amsdu)
 {
        struct sk_buff *msdu;
        struct htt_rx_desc *rxd;
@@ -1757,9 +1829,8 @@ static int ath10k_htt_rx_extract_amsdu(struct sk_buff_head *list,
        if (WARN_ON(!skb_queue_empty(amsdu)))
                return -EINVAL;
 
-       while ((msdu = __skb_dequeue(list)) && budget_left) {
+       while ((msdu = __skb_dequeue(list))) {
                __skb_queue_tail(amsdu, msdu);
-               budget_left--;
 
                rxd = (void *)msdu->data - sizeof(*rxd);
                if (rxd->msdu_end.common.info0 &
@@ -1850,8 +1921,7 @@ static int ath10k_htt_rx_h_rx_offload(struct ath10k *ar,
        return num_msdu;
 }
 
-static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb,
-                                   int budget_left)
+static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb)
 {
        struct ath10k_htt *htt = &ar->htt;
        struct htt_resp *resp = (void *)skb->data;
@@ -1908,9 +1978,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb,
        if (offload)
                num_msdus = ath10k_htt_rx_h_rx_offload(ar, &list);
 
-       while (!skb_queue_empty(&list) && budget_left) {
+       while (!skb_queue_empty(&list)) {
                __skb_queue_head_init(&amsdu);
-               ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu, budget_left);
+               ret = ath10k_htt_rx_extract_amsdu(&list, &amsdu);
                switch (ret) {
                case 0:
                        /* Note: The in-order indication may report interleaved
@@ -1920,10 +1990,9 @@ static int ath10k_htt_rx_in_ord_ind(struct ath10k *ar, struct sk_buff *skb,
                         * should still give an idea about rx rate to the user.
                         */
                        num_msdus += skb_queue_len(&amsdu);
-                       budget_left -= skb_queue_len(&amsdu);
                        ath10k_htt_rx_h_ppdu(ar, &amsdu, status, vdev_id);
                        ath10k_htt_rx_h_filter(ar, &amsdu, status);
-                       ath10k_htt_rx_h_mpdu(ar, &amsdu, status);
+                       ath10k_htt_rx_h_mpdu(ar, &amsdu, status, false);
                        ath10k_htt_rx_h_deliver(ar, &amsdu, status);
                        break;
                case -EAGAIN:
@@ -2563,8 +2632,7 @@ int ath10k_htt_txrx_compl_task(struct ath10k *ar, int budget)
                }
 
                spin_lock_bh(&htt->rx_ring.lock);
-               num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb,
-                                                       (budget - quota));
+               num_rx_msdus = ath10k_htt_rx_in_ord_ind(ar, skb);
                spin_unlock_bh(&htt->rx_ring.lock);
                if (num_rx_msdus < 0) {
                        resched_napi = true;
index c1022a1cf8555b97b91af020185b810a05899bf8..28da143989518f625498d25d4614165712fe0121 100644 (file)
@@ -239,6 +239,9 @@ enum htt_rx_mpdu_encrypt_type {
        HTT_RX_MPDU_ENCRYPT_WAPI             = 5,
        HTT_RX_MPDU_ENCRYPT_AES_CCM_WPA2     = 6,
        HTT_RX_MPDU_ENCRYPT_NONE             = 7,
+       HTT_RX_MPDU_ENCRYPT_AES_CCM256_WPA2  = 8,
+       HTT_RX_MPDU_ENCRYPT_AES_GCMP_WPA2    = 9,
+       HTT_RX_MPDU_ENCRYPT_AES_GCMP256_WPA2 = 10,
 };
 
 #define RX_MPDU_START_INFO0_PEER_IDX_MASK     0x000007ff
index 35bd50bcbbd51e2615c7b63108fbff8d78ced466..b83f01d6e3ddd842e115a19266cb79d4dfcc6421 100644 (file)
@@ -812,7 +812,6 @@ static void wcn36xx_bss_info_changed(struct ieee80211_hw *hw,
                        if (!sta) {
                                wcn36xx_err("sta %pM is not found\n",
                                              bss_conf->bssid);
-                               rcu_read_unlock();
                                goto out;
                        }
                        sta_priv = wcn36xx_sta_to_priv(sta);
index 5a14cc7f28ee75e930f8aca11e35443812720536..37f9039bb9cab29892f783ddb45a459809c3805c 100644 (file)
@@ -1249,6 +1249,7 @@ static int nvme_revalidate_disk(struct gendisk *disk)
                goto out;
        }
 
+       __nvme_revalidate_disk(disk, id);
        nvme_report_ns_ids(ctrl, ns->ns_id, id, eui64, nguid, &uuid);
        if (!uuid_equal(&ns->uuid, &uuid) ||
            memcmp(&ns->nguid, &nguid, sizeof(ns->nguid)) ||
index af075e9989449e97d7b32038d8e30a1cf0875ad6..be49d0f793816cae0a9629665230acf248ab85ec 100644 (file)
@@ -2545,10 +2545,10 @@ nvme_fc_delete_association(struct nvme_fc_ctrl *ctrl)
        nvme_fc_abort_aen_ops(ctrl);
 
        /* wait for all io that had to be aborted */
-       spin_lock_irqsave(&ctrl->lock, flags);
+       spin_lock_irq(&ctrl->lock);
        wait_event_lock_irq(ctrl->ioabort_wait, ctrl->iocnt == 0, ctrl->lock);
        ctrl->flags &= ~FCCTRL_TERMIO;
-       spin_unlock_irqrestore(&ctrl->lock, flags);
+       spin_unlock_irq(&ctrl->lock);
 
        nvme_fc_term_aen_ops(ctrl);
 
@@ -2734,7 +2734,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
 {
        struct nvme_fc_ctrl *ctrl;
        unsigned long flags;
-       int ret, idx;
+       int ret, idx, retry;
 
        if (!(rport->remoteport.port_role &
            (FC_PORT_ROLE_NVME_DISCOVERY | FC_PORT_ROLE_NVME_TARGET))) {
@@ -2760,6 +2760,7 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        ctrl->rport = rport;
        ctrl->dev = lport->dev;
        ctrl->cnum = idx;
+       init_waitqueue_head(&ctrl->ioabort_wait);
 
        get_device(ctrl->dev);
        kref_init(&ctrl->ref);
@@ -2825,9 +2826,37 @@ nvme_fc_init_ctrl(struct device *dev, struct nvmf_ctrl_options *opts,
        list_add_tail(&ctrl->ctrl_list, &rport->ctrl_list);
        spin_unlock_irqrestore(&rport->lock, flags);
 
-       ret = nvme_fc_create_association(ctrl);
+       /*
+        * It's possible that transactions used to create the association
+        * may fail. Examples: CreateAssociation LS or CreateIOConnection
+        * LS gets dropped/corrupted/fails; or a frame gets dropped or a
+        * command times out for one of the actions to init the controller
+        * (Connect, Get/Set_Property, Set_Features, etc). Many of these
+        * transport errors (frame drop, LS failure) inherently must kill
+        * the association. The transport is coded so that any command used
+        * to create the association (prior to a LIVE state transition
+        * while NEW or RECONNECTING) will fail if it completes in error or
+        * times out.
+        *
+        * As such: as the connect request was mostly likely due to a
+        * udev event that discovered the remote port, meaning there is
+        * not an admin or script there to restart if the connect
+        * request fails, retry the initial connection creation up to
+        * three times before giving up and declaring failure.
+        */
+       for (retry = 0; retry < 3; retry++) {
+               ret = nvme_fc_create_association(ctrl);
+               if (!ret)
+                       break;
+       }
+
        if (ret) {
+               /* couldn't schedule retry - fail out */
+               dev_err(ctrl->ctrl.device,
+                       "NVME-FC{%d}: Connect retry failed\n", ctrl->cnum);
+
                ctrl->ctrl.opts = NULL;
+
                /* initiate nvme ctrl ref counting teardown */
                nvme_uninit_ctrl(&ctrl->ctrl);
                nvme_put_ctrl(&ctrl->ctrl);
index 92a03ff5fb4d4392c8726a8cd556d9476fc5c0a1..0ebb539f3bd3a7d7a6e18753bc4fefa402a1b626 100644 (file)
@@ -571,6 +571,12 @@ static void nvme_rdma_free_queue(struct nvme_rdma_queue *queue)
        if (test_and_set_bit(NVME_RDMA_Q_DELETING, &queue->flags))
                return;
 
+       if (nvme_rdma_queue_idx(queue) == 0) {
+               nvme_rdma_free_qe(queue->device->dev,
+                       &queue->ctrl->async_event_sqe,
+                       sizeof(struct nvme_command), DMA_TO_DEVICE);
+       }
+
        nvme_rdma_destroy_queue_ib(queue);
        rdma_destroy_id(queue->cm_id);
 }
@@ -739,8 +745,6 @@ out:
 static void nvme_rdma_destroy_admin_queue(struct nvme_rdma_ctrl *ctrl,
                bool remove)
 {
-       nvme_rdma_free_qe(ctrl->queues[0].device->dev, &ctrl->async_event_sqe,
-                       sizeof(struct nvme_command), DMA_TO_DEVICE);
        nvme_rdma_stop_queue(&ctrl->queues[0]);
        if (remove) {
                blk_cleanup_queue(ctrl->ctrl.admin_q);
@@ -765,8 +769,10 @@ static int nvme_rdma_configure_admin_queue(struct nvme_rdma_ctrl *ctrl,
 
        if (new) {
                ctrl->ctrl.admin_tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, true);
-               if (IS_ERR(ctrl->ctrl.admin_tagset))
+               if (IS_ERR(ctrl->ctrl.admin_tagset)) {
+                       error = PTR_ERR(ctrl->ctrl.admin_tagset);
                        goto out_free_queue;
+               }
 
                ctrl->ctrl.admin_q = blk_mq_init_queue(&ctrl->admin_tag_set);
                if (IS_ERR(ctrl->ctrl.admin_q)) {
@@ -846,8 +852,10 @@ static int nvme_rdma_configure_io_queues(struct nvme_rdma_ctrl *ctrl, bool new)
 
        if (new) {
                ctrl->ctrl.tagset = nvme_rdma_alloc_tagset(&ctrl->ctrl, false);
-               if (IS_ERR(ctrl->ctrl.tagset))
+               if (IS_ERR(ctrl->ctrl.tagset)) {
+                       ret = PTR_ERR(ctrl->ctrl.tagset);
                        goto out_free_io_queues;
+               }
 
                ctrl->ctrl.connect_q = blk_mq_init_queue(&ctrl->tag_set);
                if (IS_ERR(ctrl->ctrl.connect_q)) {
@@ -1606,12 +1614,15 @@ nvme_rdma_queue_is_ready(struct nvme_rdma_queue *queue, struct request *rq)
                        /*
                         * reconnecting state means transport disruption, which
                         * can take a long time and even might fail permanently,
-                        * so we can't let incoming I/O be requeued forever.
-                        * fail it fast to allow upper layers a chance to
-                        * failover.
+                        * fail fast to give upper layers a chance to failover.
+                        * deleting state means that the ctrl will never accept
+                        * commands again, fail it permanently.
                         */
-                       if (queue->ctrl->ctrl.state == NVME_CTRL_RECONNECTING)
+                       if (queue->ctrl->ctrl.state == NVME_CTRL_RECONNECTING ||
+                           queue->ctrl->ctrl.state == NVME_CTRL_DELETING) {
+                               nvme_req(rq)->status = NVME_SC_ABORT_REQ;
                                return BLK_STS_IOERR;
+                       }
                        return BLK_STS_RESOURCE; /* try again later */
                }
        }
index 1b208beeef5097c6e4a2bd38e112543b8818af19..645ba7eee35db7a66a0249d39c7adba514173229 100644 (file)
@@ -387,12 +387,21 @@ struct nvmet_ns *nvmet_ns_alloc(struct nvmet_subsys *subsys, u32 nsid)
 
 static void __nvmet_req_complete(struct nvmet_req *req, u16 status)
 {
+       u32 old_sqhd, new_sqhd;
+       u16 sqhd;
+
        if (status)
                nvmet_set_status(req, status);
 
-       if (req->sq->size)
-               req->sq->sqhd = (req->sq->sqhd + 1) % req->sq->size;
-       req->rsp->sq_head = cpu_to_le16(req->sq->sqhd);
+       if (req->sq->size) {
+               do {
+                       old_sqhd = req->sq->sqhd;
+                       new_sqhd = (old_sqhd + 1) % req->sq->size;
+               } while (cmpxchg(&req->sq->sqhd, old_sqhd, new_sqhd) !=
+                                       old_sqhd);
+       }
+       sqhd = req->sq->sqhd & 0x0000FFFF;
+       req->rsp->sq_head = cpu_to_le16(sqhd);
        req->rsp->sq_id = cpu_to_le16(req->sq->qid);
        req->rsp->command_id = req->cmd->common.command_id;
 
index 7b8e20adf76029f293569688e8a5c71013c6393d..87e429bfcd8a0c918f2aae018c247bb0014d3d0b 100644 (file)
@@ -74,7 +74,7 @@ struct nvmet_sq {
        struct percpu_ref       ref;
        u16                     qid;
        u16                     size;
-       u16                     sqhd;
+       u32                     sqhd;
        struct completion       free_done;
        struct completion       confirm_done;
 };
index 3f6b34febbf11249cf2a30e400647038f4a66f33..433af328d9817a028f4bccce07492fbc6ac27a68 100644 (file)
@@ -534,8 +534,16 @@ static irqreturn_t amd_gpio_irq_handler(int irq, void *dev_id)
                                continue;
                        irq = irq_find_mapping(gc->irqdomain, irqnr + i);
                        generic_handle_irq(irq);
-                       /* Clear interrupt */
+
+                       /* Clear interrupt.
+                        * We must read the pin register again, in case the
+                        * value was changed while executing
+                        * generic_handle_irq() above.
+                        */
+                       raw_spin_lock_irqsave(&gpio_dev->lock, flags);
+                       regval = readl(regs + i);
                        writel(regval, regs + i);
+                       raw_spin_unlock_irqrestore(&gpio_dev->lock, flags);
                        ret = IRQ_HANDLED;
                }
        }
index 3e40d4245512e286166ac1b838567f6c55a881a0..9c950bbf07bab62cf72dcb74cbed6fa20b04598b 100644 (file)
@@ -407,10 +407,10 @@ static int mcp23s08_get(struct gpio_chip *chip, unsigned offset)
        ret = mcp_read(mcp, MCP_GPIO, &status);
        if (ret < 0)
                status = 0;
-       else
+       else {
+               mcp->cached_gpio = status;
                status = !!(status & (1 << offset));
-
-       mcp->cached_gpio = status;
+       }
 
        mutex_unlock(&mcp->lock);
        return status;
index bb792a52248b63d1c16a4fefc67a32de0e58101b..e03fa31446ca83b107c220e438db53db38c44e80 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/suspend.h>
 #include <linux/acpi.h>
 #include <linux/io-64-nonatomic-lo-hi.h>
+#include <linux/spinlock.h>
 
 #include <asm/intel_pmc_ipc.h>
 
@@ -131,6 +132,7 @@ static struct intel_pmc_ipc_dev {
        /* gcr */
        void __iomem *gcr_mem_base;
        bool has_gcr_regs;
+       spinlock_t gcr_lock;
 
        /* punit */
        struct platform_device *punit_dev;
@@ -225,17 +227,17 @@ int intel_pmc_gcr_read(u32 offset, u32 *data)
 {
        int ret;
 
-       mutex_lock(&ipclock);
+       spin_lock(&ipcdev.gcr_lock);
 
        ret = is_gcr_valid(offset);
        if (ret < 0) {
-               mutex_unlock(&ipclock);
+               spin_unlock(&ipcdev.gcr_lock);
                return ret;
        }
 
        *data = readl(ipcdev.gcr_mem_base + offset);
 
-       mutex_unlock(&ipclock);
+       spin_unlock(&ipcdev.gcr_lock);
 
        return 0;
 }
@@ -255,17 +257,17 @@ int intel_pmc_gcr_write(u32 offset, u32 data)
 {
        int ret;
 
-       mutex_lock(&ipclock);
+       spin_lock(&ipcdev.gcr_lock);
 
        ret = is_gcr_valid(offset);
        if (ret < 0) {
-               mutex_unlock(&ipclock);
+               spin_unlock(&ipcdev.gcr_lock);
                return ret;
        }
 
        writel(data, ipcdev.gcr_mem_base + offset);
 
-       mutex_unlock(&ipclock);
+       spin_unlock(&ipcdev.gcr_lock);
 
        return 0;
 }
@@ -287,7 +289,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
        u32 new_val;
        int ret = 0;
 
-       mutex_lock(&ipclock);
+       spin_lock(&ipcdev.gcr_lock);
 
        ret = is_gcr_valid(offset);
        if (ret < 0)
@@ -309,7 +311,7 @@ int intel_pmc_gcr_update(u32 offset, u32 mask, u32 val)
        }
 
 gcr_ipc_unlock:
-       mutex_unlock(&ipclock);
+       spin_unlock(&ipcdev.gcr_lock);
        return ret;
 }
 EXPORT_SYMBOL_GPL(intel_pmc_gcr_update);
@@ -480,52 +482,41 @@ static irqreturn_t ioc(int irq, void *dev_id)
 
 static int ipc_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 {
-       resource_size_t pci_resource;
+       struct intel_pmc_ipc_dev *pmc = &ipcdev;
        int ret;
-       int len;
 
-       ipcdev.dev = &pci_dev_get(pdev)->dev;
-       ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
+       /* Only one PMC is supported */
+       if (pmc->dev)
+               return -EBUSY;
 
-       ret = pci_enable_device(pdev);
+       pmc->irq_mode = IPC_TRIGGER_MODE_IRQ;
+
+       spin_lock_init(&ipcdev.gcr_lock);
+
+       ret = pcim_enable_device(pdev);
        if (ret)
                return ret;
 
-       ret = pci_request_regions(pdev, "intel_pmc_ipc");
+       ret = pcim_iomap_regions(pdev, 1 << 0, pci_name(pdev));
        if (ret)
                return ret;
 
-       pci_resource = pci_resource_start(pdev, 0);
-       len = pci_resource_len(pdev, 0);
-       if (!pci_resource || !len) {
-               dev_err(&pdev->dev, "Failed to get resource\n");
-               return -ENOMEM;
-       }
+       init_completion(&pmc->cmd_complete);
 
-       init_completion(&ipcdev.cmd_complete);
+       pmc->ipc_base = pcim_iomap_table(pdev)[0];
 
-       if (request_irq(pdev->irq, ioc, 0, "intel_pmc_ipc", &ipcdev)) {
+       ret = devm_request_irq(&pdev->dev, pdev->irq, ioc, 0, "intel_pmc_ipc",
+                               pmc);
+       if (ret) {
                dev_err(&pdev->dev, "Failed to request irq\n");
-               return -EBUSY;
+               return ret;
        }
 
-       ipcdev.ipc_base = ioremap_nocache(pci_resource, len);
-       if (!ipcdev.ipc_base) {
-               dev_err(&pdev->dev, "Failed to ioremap ipc base\n");
-               free_irq(pdev->irq, &ipcdev);
-               ret = -ENOMEM;
-       }
+       pmc->dev = &pdev->dev;
 
-       return ret;
-}
+       pci_set_drvdata(pdev, pmc);
 
-static void ipc_pci_remove(struct pci_dev *pdev)
-{
-       free_irq(pdev->irq, &ipcdev);
-       pci_release_regions(pdev);
-       pci_dev_put(pdev);
-       iounmap(ipcdev.ipc_base);
-       ipcdev.dev = NULL;
+       return 0;
 }
 
 static const struct pci_device_id ipc_pci_ids[] = {
@@ -540,7 +531,6 @@ static struct pci_driver ipc_pci_driver = {
        .name = "intel_pmc_ipc",
        .id_table = ipc_pci_ids,
        .probe = ipc_pci_probe,
-       .remove = ipc_pci_remove,
 };
 
 static ssize_t intel_pmc_ipc_simple_cmd_store(struct device *dev,
@@ -850,17 +840,12 @@ static int ipc_plat_get_res(struct platform_device *pdev)
                return -ENXIO;
        }
        size = PLAT_RESOURCE_IPC_SIZE + PLAT_RESOURCE_GCR_SIZE;
+       res->end = res->start + size - 1;
+
+       addr = devm_ioremap_resource(&pdev->dev, res);
+       if (IS_ERR(addr))
+               return PTR_ERR(addr);
 
-       if (!request_mem_region(res->start, size, pdev->name)) {
-               dev_err(&pdev->dev, "Failed to request ipc resource\n");
-               return -EBUSY;
-       }
-       addr = ioremap_nocache(res->start, size);
-       if (!addr) {
-               dev_err(&pdev->dev, "I/O memory remapping failed\n");
-               release_mem_region(res->start, size);
-               return -ENOMEM;
-       }
        ipcdev.ipc_base = addr;
 
        ipcdev.gcr_mem_base = addr + PLAT_RESOURCE_GCR_OFFSET;
@@ -917,12 +902,12 @@ MODULE_DEVICE_TABLE(acpi, ipc_acpi_ids);
 
 static int ipc_plat_probe(struct platform_device *pdev)
 {
-       struct resource *res;
        int ret;
 
        ipcdev.dev = &pdev->dev;
        ipcdev.irq_mode = IPC_TRIGGER_MODE_IRQ;
        init_completion(&ipcdev.cmd_complete);
+       spin_lock_init(&ipcdev.gcr_lock);
 
        ipcdev.irq = platform_get_irq(pdev, 0);
        if (ipcdev.irq < 0) {
@@ -939,11 +924,11 @@ static int ipc_plat_probe(struct platform_device *pdev)
        ret = ipc_create_pmc_devices();
        if (ret) {
                dev_err(&pdev->dev, "Failed to create pmc devices\n");
-               goto err_device;
+               return ret;
        }
 
-       if (request_irq(ipcdev.irq, ioc, IRQF_NO_SUSPEND,
-                       "intel_pmc_ipc", &ipcdev)) {
+       if (devm_request_irq(&pdev->dev, ipcdev.irq, ioc, IRQF_NO_SUSPEND,
+                            "intel_pmc_ipc", &ipcdev)) {
                dev_err(&pdev->dev, "Failed to request irq\n");
                ret = -EBUSY;
                goto err_irq;
@@ -960,40 +945,22 @@ static int ipc_plat_probe(struct platform_device *pdev)
 
        return 0;
 err_sys:
-       free_irq(ipcdev.irq, &ipcdev);
+       devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
 err_irq:
        platform_device_unregister(ipcdev.tco_dev);
        platform_device_unregister(ipcdev.punit_dev);
        platform_device_unregister(ipcdev.telemetry_dev);
-err_device:
-       iounmap(ipcdev.ipc_base);
-       res = platform_get_resource(pdev, IORESOURCE_MEM,
-                                   PLAT_RESOURCE_IPC_INDEX);
-       if (res) {
-               release_mem_region(res->start,
-                                  PLAT_RESOURCE_IPC_SIZE +
-                                  PLAT_RESOURCE_GCR_SIZE);
-       }
+
        return ret;
 }
 
 static int ipc_plat_remove(struct platform_device *pdev)
 {
-       struct resource *res;
-
        sysfs_remove_group(&pdev->dev.kobj, &intel_ipc_group);
-       free_irq(ipcdev.irq, &ipcdev);
+       devm_free_irq(&pdev->dev, ipcdev.irq, &ipcdev);
        platform_device_unregister(ipcdev.tco_dev);
        platform_device_unregister(ipcdev.punit_dev);
        platform_device_unregister(ipcdev.telemetry_dev);
-       iounmap(ipcdev.ipc_base);
-       res = platform_get_resource(pdev, IORESOURCE_MEM,
-                                   PLAT_RESOURCE_IPC_INDEX);
-       if (res) {
-               release_mem_region(res->start,
-                                  PLAT_RESOURCE_IPC_SIZE +
-                                  PLAT_RESOURCE_GCR_SIZE);
-       }
        ipcdev.dev = NULL;
        return 0;
 }
index f18b36dd57dd44a2f1d94302f6e1492ea6e54f88..376a99b7cf5da150794cbb3b2f1c72078985166c 100644 (file)
@@ -590,7 +590,7 @@ static bool axp20x_is_polyphase_slave(struct axp20x_dev *axp20x, int id)
                case AXP803_DCDC3:
                        return !!(reg & BIT(6));
                case AXP803_DCDC6:
-                       return !!(reg & BIT(7));
+                       return !!(reg & BIT(5));
                }
                break;
 
index ef2be56460fe2779765311473944c48e9bb9ba85..790a4a73ea2c8f94c3fb80c8567827d0e8b0860b 100644 (file)
@@ -29,7 +29,7 @@ static const struct regulator_ops rn5t618_reg_ops = {
 };
 
 #define REG(rid, ereg, emask, vreg, vmask, min, max, step)             \
-       [RN5T618_##rid] = {                                             \
+       {                                                               \
                .name           = #rid,                                 \
                .of_match       = of_match_ptr(#rid),                   \
                .regulators_node = of_match_ptr("regulators"),          \
index 82ac331d91254e72debc5d021808a6282e93dc1b..84752152d41fd682c5ae350ddb4bd3ac80d47cde 100644 (file)
@@ -357,6 +357,8 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
 
        adapter->next_port_scan = jiffies;
 
+       adapter->erp_action.adapter = adapter;
+
        if (zfcp_qdio_setup(adapter))
                goto failed;
 
@@ -513,6 +515,9 @@ struct zfcp_port *zfcp_port_enqueue(struct zfcp_adapter *adapter, u64 wwpn,
        port->dev.groups = zfcp_port_attr_groups;
        port->dev.release = zfcp_port_release;
 
+       port->erp_action.adapter = adapter;
+       port->erp_action.port = port;
+
        if (dev_set_name(&port->dev, "0x%016llx", (unsigned long long)wwpn)) {
                kfree(port);
                goto err_out;
index 6f848aeacec28ea501acaae213b551fd70cd8c00..cbb8156bf5e0c4979896b3f1edd8004c93837cfb 100644 (file)
@@ -194,9 +194,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE,
                                &zfcp_sdev->status);
                erp_action = &zfcp_sdev->erp_action;
-               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
-               erp_action->port = port;
-               erp_action->sdev = sdev;
+               WARN_ON_ONCE(erp_action->port != port);
+               WARN_ON_ONCE(erp_action->sdev != sdev);
                if (!(atomic_read(&zfcp_sdev->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -209,8 +208,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_port(port);
                atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &port->status);
                erp_action = &port->erp_action;
-               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
-               erp_action->port = port;
+               WARN_ON_ONCE(erp_action->port != port);
+               WARN_ON_ONCE(erp_action->sdev != NULL);
                if (!(atomic_read(&port->status) & ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
                break;
@@ -220,7 +219,8 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                zfcp_erp_action_dismiss_adapter(adapter);
                atomic_or(ZFCP_STATUS_COMMON_ERP_INUSE, &adapter->status);
                erp_action = &adapter->erp_action;
-               memset(erp_action, 0, sizeof(struct zfcp_erp_action));
+               WARN_ON_ONCE(erp_action->port != NULL);
+               WARN_ON_ONCE(erp_action->sdev != NULL);
                if (!(atomic_read(&adapter->status) &
                      ZFCP_STATUS_COMMON_RUNNING))
                        act_status |= ZFCP_STATUS_ERP_CLOSE_ONLY;
@@ -230,7 +230,11 @@ static struct zfcp_erp_action *zfcp_erp_setup_act(int need, u32 act_status,
                return NULL;
        }
 
-       erp_action->adapter = adapter;
+       WARN_ON_ONCE(erp_action->adapter != adapter);
+       memset(&erp_action->list, 0, sizeof(erp_action->list));
+       memset(&erp_action->timer, 0, sizeof(erp_action->timer));
+       erp_action->step = ZFCP_ERP_STEP_UNINITIALIZED;
+       erp_action->fsf_req_id = 0;
        erp_action->action = need;
        erp_action->status = act_status;
 
index ebea205f9de841fd5630fb71b9efa46377cc6319..4d2ba5682493221bf32f0c4000021da54dc57044 100644 (file)
@@ -116,10 +116,15 @@ static int zfcp_scsi_slave_alloc(struct scsi_device *sdev)
        struct zfcp_unit *unit;
        int npiv = adapter->connection_features & FSF_FEATURE_NPIV_MODE;
 
+       zfcp_sdev->erp_action.adapter = adapter;
+       zfcp_sdev->erp_action.sdev = sdev;
+
        port = zfcp_get_port_by_wwpn(adapter, rport->port_name);
        if (!port)
                return -ENXIO;
 
+       zfcp_sdev->erp_action.port = port;
+
        unit = zfcp_unit_find(port, zfcp_scsi_dev_lun(sdev));
        if (unit)
                put_device(&unit->dev);
index 97d269f1688863a90f0263c5668441650fd2cadc..1bc623ad3fafabd7025ce759c22aed725aa3bad5 100644 (file)
@@ -302,9 +302,11 @@ int aac_send_shutdown(struct aac_dev * dev)
                return -ENOMEM;
        aac_fib_init(fibctx);
 
-       mutex_lock(&dev->ioctl_mutex);
-       dev->adapter_shutdown = 1;
-       mutex_unlock(&dev->ioctl_mutex);
+       if (!dev->adapter_shutdown) {
+               mutex_lock(&dev->ioctl_mutex);
+               dev->adapter_shutdown = 1;
+               mutex_unlock(&dev->ioctl_mutex);
+       }
 
        cmd = (struct aac_close *) fib_data(fibctx);
        cmd->command = cpu_to_le32(VM_CloseAll);
index 62beb259646692c26ea9a05a72cfe26019d24eed..c9252b138c1fe0e21d217b0fb305cc45afc1545a 100644 (file)
@@ -1551,8 +1551,9 @@ static void __aac_shutdown(struct aac_dev * aac)
 {
        int i;
 
+       mutex_lock(&aac->ioctl_mutex);
        aac->adapter_shutdown = 1;
-       aac_send_shutdown(aac);
+       mutex_unlock(&aac->ioctl_mutex);
 
        if (aac->aif_thread) {
                int i;
@@ -1565,7 +1566,11 @@ static void __aac_shutdown(struct aac_dev * aac)
                }
                kthread_stop(aac->thread);
        }
+
+       aac_send_shutdown(aac);
+
        aac_adapter_disable_int(aac);
+
        if (aac_is_src(aac)) {
                if (aac->max_msix > 1) {
                        for (i = 0; i < aac->max_msix; i++) {
index 9abe81021484dc146755d0475a51ccd26231372d..4ed3d26ffdde809f457501abcbe9dee6ce644fe7 100644 (file)
@@ -4091,7 +4091,7 @@ static int hpsa_set_local_logical_count(struct ctlr_info *h,
        memset(id_ctlr, 0, sizeof(*id_ctlr));
        rc = hpsa_bmic_id_controller(h, id_ctlr, sizeof(*id_ctlr));
        if (!rc)
-               if (id_ctlr->configured_logical_drive_count < 256)
+               if (id_ctlr->configured_logical_drive_count < 255)
                        *nlocals = id_ctlr->configured_logical_drive_count;
                else
                        *nlocals = le16_to_cpu(
index 937209805bafc9052a71aa20562188a2942c148d..3bd956d3bc5d9597f92b612c8aa27f3c73f6fca0 100644 (file)
@@ -3061,6 +3061,8 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            host->max_cmd_len, host->max_channel, host->max_lun,
            host->transportt, sht->vendor_id);
 
+       INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn);
+
        /* Set up the irqs */
        ret = qla2x00_request_irqs(ha, rsp);
        if (ret)
@@ -3175,8 +3177,6 @@ qla2x00_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
            host->can_queue, base_vha->req,
            base_vha->mgmt_svr_loop_id, host->sg_tablesize);
 
-       INIT_WORK(&base_vha->iocb_work, qla2x00_iocb_work_fn);
-
        if (ha->mqenable) {
                bool mq = false;
                bool startit = false;
index 9cf6a80fe29754fc93d96d41edb090db2fdd67f4..ad3ea24f08859fb167e7297c2cacef81d646fb00 100644 (file)
@@ -1379,8 +1379,6 @@ static int scsi_prep_fn(struct request_queue *q, struct request *req)
 
        ret = scsi_setup_cmnd(sdev, req);
 out:
-       if (ret != BLKPREP_OK)
-               cmd->flags &= ~SCMD_INITIALIZED;
        return scsi_prep_return(q, req, ret);
 }
 
@@ -1900,7 +1898,6 @@ static int scsi_mq_prep_fn(struct request *req)
        struct scsi_device *sdev = req->q->queuedata;
        struct Scsi_Host *shost = sdev->host;
        struct scatterlist *sg;
-       int ret;
 
        scsi_init_command(sdev, cmd);
 
@@ -1934,10 +1931,7 @@ static int scsi_mq_prep_fn(struct request *req)
 
        blk_mq_start_request(req);
 
-       ret = scsi_setup_cmnd(sdev, req);
-       if (ret != BLK_STS_OK)
-               cmd->flags &= ~SCMD_INITIALIZED;
-       return ret;
+       return scsi_setup_cmnd(sdev, req);
 }
 
 static void scsi_mq_done(struct scsi_cmnd *cmd)
index 0419c2298eabdb8f80897357a04be66e85e9a4ac..aa28874e8fb92f5090d64c9ceb9523fce224eabe 100644 (file)
@@ -837,7 +837,7 @@ sg_fill_request_table(Sg_fd *sfp, sg_req_info_t *rinfo)
 
        val = 0;
        list_for_each_entry(srp, &sfp->rq_list, entry) {
-               if (val > SG_MAX_QUEUE)
+               if (val >= SG_MAX_QUEUE)
                        break;
                rinfo[val].req_state = srp->done + 1;
                rinfo[val].problem =
index 6c7d7a460689917d577973f7bb47a1e408470210..568e1c65aa82cb77a92b7df5ff066513c3d959a8 100644 (file)
 /* A3700_SPI_IF_TIME_REG */
 #define A3700_SPI_CLK_CAPT_EDGE                BIT(7)
 
-/* Flags and macros for struct a3700_spi */
-#define A3700_INSTR_CNT                        1
-#define A3700_ADDR_CNT                 3
-#define A3700_DUMMY_CNT                        1
-
 struct a3700_spi {
        struct spi_master *master;
        void __iomem *base;
@@ -117,9 +112,6 @@ struct a3700_spi {
        u8 byte_len;
        u32 wait_mask;
        struct completion done;
-       u32 addr_cnt;
-       u32 instr_cnt;
-       size_t hdr_cnt;
 };
 
 static u32 spireg_read(struct a3700_spi *a3700_spi, u32 offset)
@@ -161,7 +153,7 @@ static void a3700_spi_deactivate_cs(struct a3700_spi *a3700_spi,
 }
 
 static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
-                                 unsigned int pin_mode)
+                                 unsigned int pin_mode, bool receiving)
 {
        u32 val;
 
@@ -177,6 +169,9 @@ static int a3700_spi_pin_mode_set(struct a3700_spi *a3700_spi,
                break;
        case SPI_NBITS_QUAD:
                val |= A3700_SPI_DATA_PIN1;
+               /* RX during address reception uses 4-pin */
+               if (receiving)
+                       val |= A3700_SPI_ADDR_PIN;
                break;
        default:
                dev_err(&a3700_spi->master->dev, "wrong pin mode %u", pin_mode);
@@ -392,7 +387,8 @@ static bool a3700_spi_wait_completion(struct spi_device *spi)
 
        spireg_write(a3700_spi, A3700_SPI_INT_MASK_REG, 0);
 
-       return true;
+       /* Timeout was reached */
+       return false;
 }
 
 static bool a3700_spi_transfer_wait(struct spi_device *spi,
@@ -446,59 +442,43 @@ static void a3700_spi_set_cs(struct spi_device *spi, bool enable)
 
 static void a3700_spi_header_set(struct a3700_spi *a3700_spi)
 {
-       u32 instr_cnt = 0, addr_cnt = 0, dummy_cnt = 0;
+       unsigned int addr_cnt;
        u32 val = 0;
 
        /* Clear the header registers */
        spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, 0);
        spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, 0);
        spireg_write(a3700_spi, A3700_SPI_IF_RMODE_REG, 0);
+       spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, 0);
 
        /* Set header counters */
        if (a3700_spi->tx_buf) {
-               if (a3700_spi->buf_len <= a3700_spi->instr_cnt) {
-                       instr_cnt = a3700_spi->buf_len;
-               } else if (a3700_spi->buf_len <= (a3700_spi->instr_cnt +
-                                                 a3700_spi->addr_cnt)) {
-                       instr_cnt = a3700_spi->instr_cnt;
-                       addr_cnt = a3700_spi->buf_len - instr_cnt;
-               } else if (a3700_spi->buf_len <= a3700_spi->hdr_cnt) {
-                       instr_cnt = a3700_spi->instr_cnt;
-                       addr_cnt = a3700_spi->addr_cnt;
-                       /* Need to handle the normal write case with 1 byte
-                        * data
-                        */
-                       if (!a3700_spi->tx_buf[instr_cnt + addr_cnt])
-                               dummy_cnt = a3700_spi->buf_len - instr_cnt -
-                                           addr_cnt;
+               /*
+                * when tx data is not 4 bytes aligned, there will be unexpected
+                * bytes out of SPI output register, since it always shifts out
+                * as whole 4 bytes. This might cause incorrect transaction with
+                * some devices. To avoid that, use SPI header count feature to
+                * transfer up to 3 bytes of data first, and then make the rest
+                * of data 4-byte aligned.
+                */
+               addr_cnt = a3700_spi->buf_len % 4;
+               if (addr_cnt) {
+                       val = (addr_cnt & A3700_SPI_ADDR_CNT_MASK)
+                               << A3700_SPI_ADDR_CNT_BIT;
+                       spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val);
+
+                       /* Update the buffer length to be transferred */
+                       a3700_spi->buf_len -= addr_cnt;
+
+                       /* transfer 1~3 bytes through address count */
+                       val = 0;
+                       while (addr_cnt--) {
+                               val = (val << 8) | a3700_spi->tx_buf[0];
+                               a3700_spi->tx_buf++;
+                       }
+                       spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val);
                }
-               val |= ((instr_cnt & A3700_SPI_INSTR_CNT_MASK)
-                       << A3700_SPI_INSTR_CNT_BIT);
-               val |= ((addr_cnt & A3700_SPI_ADDR_CNT_MASK)
-                       << A3700_SPI_ADDR_CNT_BIT);
-               val |= ((dummy_cnt & A3700_SPI_DUMMY_CNT_MASK)
-                       << A3700_SPI_DUMMY_CNT_BIT);
        }
-       spireg_write(a3700_spi, A3700_SPI_IF_HDR_CNT_REG, val);
-
-       /* Update the buffer length to be transferred */
-       a3700_spi->buf_len -= (instr_cnt + addr_cnt + dummy_cnt);
-
-       /* Set Instruction */
-       val = 0;
-       while (instr_cnt--) {
-               val = (val << 8) | a3700_spi->tx_buf[0];
-               a3700_spi->tx_buf++;
-       }
-       spireg_write(a3700_spi, A3700_SPI_IF_INST_REG, val);
-
-       /* Set Address */
-       val = 0;
-       while (addr_cnt--) {
-               val = (val << 8) | a3700_spi->tx_buf[0];
-               a3700_spi->tx_buf++;
-       }
-       spireg_write(a3700_spi, A3700_SPI_IF_ADDR_REG, val);
 }
 
 static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi)
@@ -512,35 +492,12 @@ static int a3700_is_wfifo_full(struct a3700_spi *a3700_spi)
 static int a3700_spi_fifo_write(struct a3700_spi *a3700_spi)
 {
        u32 val;
-       int i = 0;
 
        while (!a3700_is_wfifo_full(a3700_spi) && a3700_spi->buf_len) {
-               val = 0;
-               if (a3700_spi->buf_len >= 4) {
-                       val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf);
-                       spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val);
-
-                       a3700_spi->buf_len -= 4;
-                       a3700_spi->tx_buf += 4;
-               } else {
-                       /*
-                        * If the remained buffer length is less than 4-bytes,
-                        * we should pad the write buffer with all ones. So that
-                        * it avoids overwrite the unexpected bytes following
-                        * the last one.
-                        */
-                       val = GENMASK(31, 0);
-                       while (a3700_spi->buf_len) {
-                               val &= ~(0xff << (8 * i));
-                               val |= *a3700_spi->tx_buf++ << (8 * i);
-                               i++;
-                               a3700_spi->buf_len--;
-
-                               spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG,
-                                            val);
-                       }
-                       break;
-               }
+               val = cpu_to_le32(*(u32 *)a3700_spi->tx_buf);
+               spireg_write(a3700_spi, A3700_SPI_DATA_OUT_REG, val);
+               a3700_spi->buf_len -= 4;
+               a3700_spi->tx_buf += 4;
        }
 
        return 0;
@@ -645,15 +602,18 @@ static int a3700_spi_transfer_one(struct spi_master *master,
        a3700_spi->rx_buf  = xfer->rx_buf;
        a3700_spi->buf_len = xfer->len;
 
-       /* SPI transfer headers */
-       a3700_spi_header_set(a3700_spi);
-
        if (xfer->tx_buf)
                nbits = xfer->tx_nbits;
        else if (xfer->rx_buf)
                nbits = xfer->rx_nbits;
 
-       a3700_spi_pin_mode_set(a3700_spi, nbits);
+       a3700_spi_pin_mode_set(a3700_spi, nbits, xfer->rx_buf ? true : false);
+
+       /* Flush the FIFOs */
+       a3700_spi_fifo_flush(a3700_spi);
+
+       /* Transfer first bytes of data when buffer is not 4-byte aligned */
+       a3700_spi_header_set(a3700_spi);
 
        if (xfer->rx_buf) {
                /* Set read data length */
@@ -733,16 +693,11 @@ static int a3700_spi_transfer_one(struct spi_master *master,
                                dev_err(&spi->dev, "wait wfifo empty timed out\n");
                                return -ETIMEDOUT;
                        }
-               } else {
-                       /*
-                        * If the instruction in SPI_INSTR does not require data
-                        * to be written to the SPI device, wait until SPI_RDY
-                        * is 1 for the SPI interface to be in idle.
-                        */
-                       if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) {
-                               dev_err(&spi->dev, "wait xfer ready timed out\n");
-                               return -ETIMEDOUT;
-                       }
+               }
+
+               if (!a3700_spi_transfer_wait(spi, A3700_SPI_XFER_RDY)) {
+                       dev_err(&spi->dev, "wait xfer ready timed out\n");
+                       return -ETIMEDOUT;
                }
 
                val = spireg_read(a3700_spi, A3700_SPI_IF_CFG_REG);
@@ -834,10 +789,6 @@ static int a3700_spi_probe(struct platform_device *pdev)
        memset(spi, 0, sizeof(struct a3700_spi));
 
        spi->master = master;
-       spi->instr_cnt = A3700_INSTR_CNT;
-       spi->addr_cnt = A3700_ADDR_CNT;
-       spi->hdr_cnt = A3700_INSTR_CNT + A3700_ADDR_CNT +
-                      A3700_DUMMY_CNT;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        spi->base = devm_ioremap_resource(dev, res);
index 6ef6c44f39f5f7e591710029814ca03128455299..a172ab299e80316ee904a1c9277a36755699e4d4 100644 (file)
@@ -1250,7 +1250,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
                        goto qspi_probe_err;
                }
        } else {
-               goto qspi_probe_err;
+               goto qspi_resource_err;
        }
 
        res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "bspi");
@@ -1272,7 +1272,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
                qspi->base[CHIP_SELECT]  = devm_ioremap_resource(dev, res);
                if (IS_ERR(qspi->base[CHIP_SELECT])) {
                        ret = PTR_ERR(qspi->base[CHIP_SELECT]);
-                       goto qspi_probe_err;
+                       goto qspi_resource_err;
                }
        }
 
@@ -1280,7 +1280,7 @@ int bcm_qspi_probe(struct platform_device *pdev,
                                GFP_KERNEL);
        if (!qspi->dev_ids) {
                ret = -ENOMEM;
-               goto qspi_probe_err;
+               goto qspi_resource_err;
        }
 
        for (val = 0; val < num_irqs; val++) {
@@ -1369,8 +1369,9 @@ qspi_reg_err:
        bcm_qspi_hw_uninit(qspi);
        clk_disable_unprepare(qspi->clk);
 qspi_probe_err:
-       spi_master_put(master);
        kfree(qspi->dev_ids);
+qspi_resource_err:
+       spi_master_put(master);
        return ret;
 }
 /* probe function to be called by SoC specific platform driver probe */
index 680cdf549506143d6041736f43552f868e3bf6db..ba9743fa2326d11689384e47c84da4068c9fc521 100644 (file)
@@ -263,8 +263,8 @@ static int stm32_spi_prepare_mbr(struct stm32_spi *spi, u32 speed_hz)
         * no need to check it there.
         * However, we need to ensure the following calculations.
         */
-       if ((div < SPI_MBR_DIV_MIN) &&
-           (div > SPI_MBR_DIV_MAX))
+       if (div < SPI_MBR_DIV_MIN ||
+           div > SPI_MBR_DIV_MAX)
                return -EINVAL;
 
        /* Determine the first power of 2 greater than or equal to div */
index 6e65524cbfd9b8f7e1ff21a4c304908531476f21..e8b5a5e21b2e692e8af31e93ee3102b0c26872d9 100644 (file)
@@ -45,7 +45,6 @@
 
 #define CREATE_TRACE_POINTS
 #include <trace/events/spi.h>
-#define SPI_DYN_FIRST_BUS_NUM 0
 
 static DEFINE_IDR(spi_master_idr);
 
@@ -2086,7 +2085,7 @@ int spi_register_controller(struct spi_controller *ctlr)
        struct device           *dev = ctlr->dev.parent;
        struct boardinfo        *bi;
        int                     status = -ENODEV;
-       int                     id;
+       int                     id, first_dynamic;
 
        if (!dev)
                return -ENODEV;
@@ -2116,9 +2115,15 @@ int spi_register_controller(struct spi_controller *ctlr)
                }
        }
        if (ctlr->bus_num < 0) {
+               first_dynamic = of_alias_get_highest_id("spi");
+               if (first_dynamic < 0)
+                       first_dynamic = 0;
+               else
+                       first_dynamic++;
+
                mutex_lock(&board_lock);
-               id = idr_alloc(&spi_master_idr, ctlr, SPI_DYN_FIRST_BUS_NUM, 0,
-                              GFP_KERNEL);
+               id = idr_alloc(&spi_master_idr, ctlr, first_dynamic,
+                              0, GFP_KERNEL);
                mutex_unlock(&board_lock);
                if (WARN(id < 0, "couldn't get idr"))
                        return id;
index 82360594fa8e49bcbad179a6bb349564286cf203..57efbd3b053b37ca43816483dd3364c3c48a761e 100644 (file)
@@ -1024,6 +1024,7 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
        mutex_unlock(&priv->lock);
 
        if (use_ptemod) {
+               map->pages_vm_start = vma->vm_start;
                err = apply_to_page_range(vma->vm_mm, vma->vm_start,
                                          vma->vm_end - vma->vm_start,
                                          find_grant_ptes, map);
@@ -1061,7 +1062,6 @@ static int gntdev_mmap(struct file *flip, struct vm_area_struct *vma)
                                            set_grant_ptes_as_special, NULL);
                }
 #endif
-               map->pages_vm_start = vma->vm_start;
        }
 
        return 0;
index e89136ab851e30c1aff97893615f72f2d5bf3cd7..b437fccd4e624e3b7a8972245e9e992fe77c2993 100644 (file)
@@ -57,7 +57,7 @@ static int register_balloon(struct device *dev);
 static void watch_target(struct xenbus_watch *watch,
                         const char *path, const char *token)
 {
-       unsigned long long new_target;
+       unsigned long long new_target, static_max;
        int err;
        static bool watch_fired;
        static long target_diff;
@@ -72,13 +72,20 @@ static void watch_target(struct xenbus_watch *watch,
         * pages. PAGE_SHIFT converts bytes to pages, hence PAGE_SHIFT - 10.
         */
        new_target >>= PAGE_SHIFT - 10;
-       if (watch_fired) {
-               balloon_set_new_target(new_target - target_diff);
-               return;
+
+       if (!watch_fired) {
+               watch_fired = true;
+               err = xenbus_scanf(XBT_NIL, "memory", "static-max", "%llu",
+                                  &static_max);
+               if (err != 1)
+                       static_max = new_target;
+               else
+                       static_max >>= PAGE_SHIFT - 10;
+               target_diff = xen_pv_domain() ? 0
+                               : static_max - balloon_stats.target_pages;
        }
 
-       watch_fired = true;
-       target_diff = new_target - balloon_stats.target_pages;
+       balloon_set_new_target(new_target - target_diff);
 }
 static struct xenbus_watch target_watch = {
        .node = "memory/target",
index 115a27d44bace898628bcd8259e0a09cc7e89ec0..ff5d32cf9578f77aa28bebd2634fd61cb3d27064 100644 (file)
@@ -1992,6 +1992,7 @@ static int try_flush_caps(struct inode *inode, u64 *ptid)
 retry:
        spin_lock(&ci->i_ceph_lock);
        if (ci->i_ceph_flags & CEPH_I_NOFLUSH) {
+               spin_unlock(&ci->i_ceph_lock);
                dout("try_flush_caps skipping %p I_NOFLUSH set\n", inode);
                goto out;
        }
@@ -2009,8 +2010,10 @@ retry:
                        mutex_lock(&session->s_mutex);
                        goto retry;
                }
-               if (cap->session->s_state < CEPH_MDS_SESSION_OPEN)
+               if (cap->session->s_state < CEPH_MDS_SESSION_OPEN) {
+                       spin_unlock(&ci->i_ceph_lock);
                        goto out;
+               }
 
                flushing = __mark_caps_flushing(inode, session, true,
                                                &flush_tid, &oldest_flush_tid);
index f7243617316c072b71817fe951532c758b8de064..d5b2e12b5d02212046f0a7b816550737cc3b45af 100644 (file)
@@ -5,9 +5,14 @@ config CIFS
        select CRYPTO
        select CRYPTO_MD4
        select CRYPTO_MD5
+       select CRYPTO_SHA256
+       select CRYPTO_CMAC
        select CRYPTO_HMAC
        select CRYPTO_ARC4
+       select CRYPTO_AEAD2
+       select CRYPTO_CCM
        select CRYPTO_ECB
+       select CRYPTO_AES
        select CRYPTO_DES
        help
          This is the client VFS module for the SMB3 family of NAS protocols,
index de5b2e1fcce5f35153a84c9cb1c191911b48a728..e185b2853eab7b1116dafc7ca8aeeb6d09b10687 100644 (file)
@@ -661,7 +661,9 @@ struct TCP_Server_Info {
 #endif
        unsigned int    max_read;
        unsigned int    max_write;
-       __u8            preauth_hash[512];
+#ifdef CONFIG_CIFS_SMB311
+       __u8    preauth_sha_hash[64]; /* save initital negprot hash */
+#endif /* 3.1.1 */
        struct delayed_work reconnect; /* reconnect workqueue job */
        struct mutex reconnect_mutex; /* prevent simultaneous reconnects */
        unsigned long echo_interval;
@@ -849,7 +851,9 @@ struct cifs_ses {
        __u8 smb3signingkey[SMB3_SIGN_KEY_SIZE];
        __u8 smb3encryptionkey[SMB3_SIGN_KEY_SIZE];
        __u8 smb3decryptionkey[SMB3_SIGN_KEY_SIZE];
-       __u8 preauth_hash[512];
+#ifdef CONFIG_CIFS_SMB311
+       __u8 preauth_sha_hash[64];
+#endif /* 3.1.1 */
 };
 
 static inline bool
index e702d48bd023411f3bbed69c6cc6a571f2fc059c..81ba6e0d88d8f3ec1d1c8b2e81e695819537c921 100644 (file)
@@ -204,7 +204,8 @@ check_name(struct dentry *direntry, struct cifs_tcon *tcon)
        struct cifs_sb_info *cifs_sb = CIFS_SB(direntry->d_sb);
        int i;
 
-       if (unlikely(direntry->d_name.len >
+       if (unlikely(tcon->fsAttrInfo.MaxPathNameComponentLength &&
+                    direntry->d_name.len >
                     le32_to_cpu(tcon->fsAttrInfo.MaxPathNameComponentLength)))
                return -ENAMETOOLONG;
 
@@ -520,7 +521,7 @@ cifs_atomic_open(struct inode *inode, struct dentry *direntry,
 
        rc = check_name(direntry, tcon);
        if (rc)
-               goto out_free_xid;
+               goto out;
 
        server = tcon->ses->server;
 
index 7ca9808a0daa01bfb149690964bbd165d9c6af20..62c88dfed57b3f66fff931f4abbcc8126ca4cf11 100644 (file)
@@ -214,7 +214,7 @@ static const struct status_to_posix_error smb2_error_map_table[] = {
        {STATUS_DATATYPE_MISALIGNMENT, -EIO, "STATUS_DATATYPE_MISALIGNMENT"},
        {STATUS_BREAKPOINT, -EIO, "STATUS_BREAKPOINT"},
        {STATUS_SINGLE_STEP, -EIO, "STATUS_SINGLE_STEP"},
-       {STATUS_BUFFER_OVERFLOW, -EIO, "STATUS_BUFFER_OVERFLOW"},
+       {STATUS_BUFFER_OVERFLOW, -E2BIG, "STATUS_BUFFER_OVERFLOW"},
        {STATUS_NO_MORE_FILES, -ENODATA, "STATUS_NO_MORE_FILES"},
        {STATUS_WAKE_SYSTEM_DEBUGGER, -EIO, "STATUS_WAKE_SYSTEM_DEBUGGER"},
        {STATUS_HANDLES_CLOSED, -EIO, "STATUS_HANDLES_CLOSED"},
index 0dafdbae1f8cb35539a138e73330a214f7f72da3..bdb963d0ba32069035bdd23c9046985b41feb2bb 100644 (file)
@@ -522,6 +522,7 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
        struct cifs_open_parms oparms;
        struct cifs_fid fid;
        struct smb2_file_full_ea_info *smb2_data;
+       int ea_buf_size = SMB2_MIN_EA_BUF;
 
        utf16_path = cifs_convert_path_to_utf16(path, cifs_sb);
        if (!utf16_path)
@@ -541,14 +542,32 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
                return rc;
        }
 
-       smb2_data = kzalloc(SMB2_MAX_EA_BUF, GFP_KERNEL);
-       if (smb2_data == NULL) {
-               SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
-               return -ENOMEM;
+       while (1) {
+               smb2_data = kzalloc(ea_buf_size, GFP_KERNEL);
+               if (smb2_data == NULL) {
+                       SMB2_close(xid, tcon, fid.persistent_fid,
+                                  fid.volatile_fid);
+                       return -ENOMEM;
+               }
+
+               rc = SMB2_query_eas(xid, tcon, fid.persistent_fid,
+                                   fid.volatile_fid,
+                                   ea_buf_size, smb2_data);
+
+               if (rc != -E2BIG)
+                       break;
+
+               kfree(smb2_data);
+               ea_buf_size <<= 1;
+
+               if (ea_buf_size > SMB2_MAX_EA_BUF) {
+                       cifs_dbg(VFS, "EA size is too large\n");
+                       SMB2_close(xid, tcon, fid.persistent_fid,
+                                  fid.volatile_fid);
+                       return -ENOMEM;
+               }
        }
 
-       rc = SMB2_query_eas(xid, tcon, fid.persistent_fid, fid.volatile_fid,
-                           smb2_data);
        SMB2_close(xid, tcon, fid.persistent_fid, fid.volatile_fid);
 
        if (!rc)
index 6f0e6343c15e7e329e6de896220c693f337d9829..5331631386a23bd4a7458ecb5fb96efe1773cf71 100644 (file)
@@ -648,7 +648,7 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
 {
        int rc = 0;
        struct validate_negotiate_info_req vneg_inbuf;
-       struct validate_negotiate_info_rsp *pneg_rsp;
+       struct validate_negotiate_info_rsp *pneg_rsp = NULL;
        u32 rsplen;
        u32 inbuflen; /* max of 4 dialects */
 
@@ -727,8 +727,9 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
                         rsplen);
 
                /* relax check since Mac returns max bufsize allowed on ioctl */
-               if (rsplen > CIFSMaxBufSize)
-                       return -EIO;
+               if ((rsplen > CIFSMaxBufSize)
+                    || (rsplen < sizeof(struct validate_negotiate_info_rsp)))
+                       goto err_rsp_free;
        }
 
        /* check validate negotiate info response matches what we got earlier */
@@ -747,10 +748,13 @@ int smb3_validate_negotiate(const unsigned int xid, struct cifs_tcon *tcon)
 
        /* validate negotiate successful */
        cifs_dbg(FYI, "validate negotiate info successful\n");
+       kfree(pneg_rsp);
        return 0;
 
 vneg_out:
        cifs_dbg(VFS, "protocol revalidation - security settings mismatch\n");
+err_rsp_free:
+       kfree(pneg_rsp);
        return -EIO;
 }
 
@@ -1255,7 +1259,7 @@ SMB2_tcon(const unsigned int xid, struct cifs_ses *ses, const char *tree,
        struct smb2_tree_connect_req *req;
        struct smb2_tree_connect_rsp *rsp = NULL;
        struct kvec iov[2];
-       struct kvec rsp_iov;
+       struct kvec rsp_iov = { NULL, 0 };
        int rc = 0;
        int resp_buftype;
        int unc_path_len;
@@ -1372,7 +1376,7 @@ tcon_exit:
        return rc;
 
 tcon_error_exit:
-       if (rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
+       if (rsp && rsp->hdr.sync_hdr.Status == STATUS_BAD_NETWORK_NAME) {
                cifs_dbg(VFS, "BAD_NETWORK_NAME: %s\n", tree);
        }
        goto tcon_exit;
@@ -1975,6 +1979,9 @@ SMB2_ioctl(const unsigned int xid, struct cifs_tcon *tcon, u64 persistent_fid,
        } else
                iov[0].iov_len = get_rfc1002_length(req) + 4;
 
+       /* validate negotiate request must be signed - see MS-SMB2 3.2.5.5 */
+       if (opcode == FSCTL_VALIDATE_NEGOTIATE_INFO)
+               req->hdr.sync_hdr.Flags |= SMB2_FLAGS_SIGNED;
 
        rc = SendReceive2(xid, ses, iov, n_iov, &resp_buftype, flags, &rsp_iov);
        cifs_small_buf_release(req);
@@ -2191,9 +2198,13 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
        req->PersistentFileId = persistent_fid;
        req->VolatileFileId = volatile_fid;
        req->AdditionalInformation = cpu_to_le32(additional_info);
-       /* 4 for rfc1002 length field and 1 for Buffer */
-       req->InputBufferOffset =
-               cpu_to_le16(sizeof(struct smb2_query_info_req) - 1 - 4);
+
+       /*
+        * We do not use the input buffer (do not send extra byte)
+        */
+       req->InputBufferOffset = 0;
+       inc_rfc1001_len(req, -1);
+
        req->OutputBufferLength = cpu_to_le32(output_len);
 
        iov[0].iov_base = (char *)req;
@@ -2233,12 +2244,12 @@ qinf_exit:
 }
 
 int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
-       u64 persistent_fid, u64 volatile_fid,
-       struct smb2_file_full_ea_info *data)
+                  u64 persistent_fid, u64 volatile_fid,
+                  int ea_buf_size, struct smb2_file_full_ea_info *data)
 {
        return query_info(xid, tcon, persistent_fid, volatile_fid,
                          FILE_FULL_EA_INFORMATION, SMB2_O_INFO_FILE, 0,
-                         SMB2_MAX_EA_BUF,
+                         ea_buf_size,
                          sizeof(struct smb2_file_full_ea_info),
                          (void **)&data,
                          NULL);
index 6c9653a130c8bf38f5c38d6965cea32d105e708d..c2ec934be96891a645537140df279b0fb3e2fcbe 100644 (file)
@@ -832,7 +832,7 @@ struct smb2_flush_rsp {
 /* Channel field for read and write: exactly one of following flags can be set*/
 #define SMB2_CHANNEL_NONE              0x00000000
 #define SMB2_CHANNEL_RDMA_V1           0x00000001 /* SMB3 or later */
-#define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000001 /* SMB3.02 or later */
+#define SMB2_CHANNEL_RDMA_V1_INVALIDATE 0x00000002 /* SMB3.02 or later */
 
 /* SMB2 read request without RFC1001 length at the beginning */
 struct smb2_read_plain_req {
@@ -1178,7 +1178,8 @@ struct smb2_file_link_info { /* encoding of request for level 11 */
        char   FileName[0];     /* Name to be assigned to new link */
 } __packed; /* level 11 Set */
 
-#define SMB2_MAX_EA_BUF 2048
+#define SMB2_MIN_EA_BUF  2048
+#define SMB2_MAX_EA_BUF 65536
 
 struct smb2_file_full_ea_info { /* encoding of response for level 15 */
        __le32 next_entry_offset;
index 003217099ef3e6831a36ed81f7c13f1f611efb9d..e9ab5227e7a8ac3d69e69afe678cee78566056a8 100644 (file)
@@ -134,6 +134,7 @@ extern int SMB2_flush(const unsigned int xid, struct cifs_tcon *tcon,
                      u64 persistent_file_id, u64 volatile_file_id);
 extern int SMB2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
                          u64 persistent_file_id, u64 volatile_file_id,
+                         int ea_buf_size,
                          struct smb2_file_full_ea_info *data);
 extern int SMB2_query_info(const unsigned int xid, struct cifs_tcon *tcon,
                           u64 persistent_file_id, u64 volatile_file_id,
index 67367cf1f8cd2391359ff041836f0ae34a2091f4..99493946e2f9abcf02673bf685238b0313da4180 100644 (file)
@@ -390,6 +390,7 @@ generate_smb30signingkey(struct cifs_ses *ses)
        return generate_smb3signingkey(ses, &triplet);
 }
 
+#ifdef CONFIG_CIFS_SMB311
 int
 generate_smb311signingkey(struct cifs_ses *ses)
 
@@ -398,25 +399,26 @@ generate_smb311signingkey(struct cifs_ses *ses)
        struct derivation *d;
 
        d = &triplet.signing;
-       d->label.iov_base = "SMB2AESCMAC";
-       d->label.iov_len = 12;
-       d->context.iov_base = "SmbSign";
-       d->context.iov_len = 8;
+       d->label.iov_base = "SMBSigningKey";
+       d->label.iov_len = 14;
+       d->context.iov_base = ses->preauth_sha_hash;
+       d->context.iov_len = 64;
 
        d = &triplet.encryption;
-       d->label.iov_base = "SMB2AESCCM";
-       d->label.iov_len = 11;
-       d->context.iov_base = "ServerIn ";
-       d->context.iov_len = 10;
+       d->label.iov_base = "SMBC2SCipherKey";
+       d->label.iov_len = 16;
+       d->context.iov_base = ses->preauth_sha_hash;
+       d->context.iov_len = 64;
 
        d = &triplet.decryption;
-       d->label.iov_base = "SMB2AESCCM";
-       d->label.iov_len = 11;
-       d->context.iov_base = "ServerOut";
-       d->context.iov_len = 10;
+       d->label.iov_base = "SMBS2CCipherKey";
+       d->label.iov_len = 16;
+       d->context.iov_base = ses->preauth_sha_hash;
+       d->context.iov_len = 64;
 
        return generate_smb3signingkey(ses, &triplet);
 }
+#endif /* 311 */
 
 int
 smb3_calc_signature(struct smb_rqst *rqst, struct TCP_Server_Info *server)
index 622081b97426d5b439bb1db5ee57dc4c3eead253..24967382a7b15271ae0646c3cb5522b3e58c37d0 100644 (file)
@@ -1308,7 +1308,8 @@ static int parse_dirplusfile(char *buf, size_t nbytes, struct file *file,
                        */
                        over = !dir_emit(ctx, dirent->name, dirent->namelen,
                                       dirent->ino, dirent->type);
-                       ctx->pos = dirent->off;
+                       if (!over)
+                               ctx->pos = dirent->off;
                }
 
                buf += reclen;
index a619addecafcf05713b3a41e7e05a9e0866847a1..321511ed8c4235e102adfe84b98ac17c247eeadb 100644 (file)
@@ -598,18 +598,30 @@ static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry,
        return true;
 }
 
-struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry)
+struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry,
+                           struct dentry *index)
 {
        struct dentry *lowerdentry = ovl_dentry_lower(dentry);
        struct inode *realinode = upperdentry ? d_inode(upperdentry) : NULL;
        struct inode *inode;
+       /* Already indexed or could be indexed on copy up? */
+       bool indexed = (index || (ovl_indexdir(dentry->d_sb) && !upperdentry));
+
+       if (WARN_ON(upperdentry && indexed && !lowerdentry))
+               return ERR_PTR(-EIO);
 
        if (!realinode)
                realinode = d_inode(lowerdentry);
 
-       if (!S_ISDIR(realinode->i_mode) &&
-           (upperdentry || (lowerdentry && ovl_indexdir(dentry->d_sb)))) {
-               struct inode *key = d_inode(lowerdentry ?: upperdentry);
+       /*
+        * Copy up origin (lower) may exist for non-indexed upper, but we must
+        * not use lower as hash key in that case.
+        * Hash inodes that are or could be indexed by origin inode and
+        * non-indexed upper inodes that could be hard linked by upper inode.
+        */
+       if (!S_ISDIR(realinode->i_mode) && (upperdentry || indexed)) {
+               struct inode *key = d_inode(indexed ? lowerdentry :
+                                                     upperdentry);
                unsigned int nlink;
 
                inode = iget5_locked(dentry->d_sb, (unsigned long) key,
index 654bea1a5ac9f38c587919d1fac6d53fd6867ee0..a12dc10bf726351a4a47a75f92b66d3b87043174 100644 (file)
@@ -405,14 +405,13 @@ int ovl_verify_index(struct dentry *index, struct path *lowerstack,
         * be treated as stale (i.e. after unlink of the overlay inode).
         * We don't know the verification rules for directory and whiteout
         * index entries, because they have not been implemented yet, so return
-        * EROFS if those entries are found to avoid corrupting an index that
-        * was created by a newer kernel.
+        * EINVAL if those entries are found to abort the mount to avoid
+        * corrupting an index that was created by a newer kernel.
         */
-       err = -EROFS;
+       err = -EINVAL;
        if (d_is_dir(index) || ovl_is_whiteout(index))
                goto fail;
 
-       err = -EINVAL;
        if (index->d_name.len < sizeof(struct ovl_fh)*2)
                goto fail;
 
@@ -507,6 +506,10 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
        index = lookup_one_len_unlocked(name.name, ofs->indexdir, name.len);
        if (IS_ERR(index)) {
                err = PTR_ERR(index);
+               if (err == -ENOENT) {
+                       index = NULL;
+                       goto out;
+               }
                pr_warn_ratelimited("overlayfs: failed inode index lookup (ino=%lu, key=%*s, err=%i);\n"
                                    "overlayfs: mount with '-o index=off' to disable inodes index.\n",
                                    d_inode(origin)->i_ino, name.len, name.name,
@@ -516,18 +519,9 @@ static struct dentry *ovl_lookup_index(struct dentry *dentry,
 
        inode = d_inode(index);
        if (d_is_negative(index)) {
-               if (upper && d_inode(origin)->i_nlink > 1) {
-                       pr_warn_ratelimited("overlayfs: hard link with origin but no index (ino=%lu).\n",
-                                           d_inode(origin)->i_ino);
-                       goto fail;
-               }
-
-               dput(index);
-               index = NULL;
+               goto out_dput;
        } else if (upper && d_inode(upper) != inode) {
-               pr_warn_ratelimited("overlayfs: wrong index found (index=%pd2, ino=%lu, upper ino=%lu).\n",
-                                   index, inode->i_ino, d_inode(upper)->i_ino);
-               goto fail;
+               goto out_dput;
        } else if (ovl_dentry_weird(index) || ovl_is_whiteout(index) ||
                   ((inode->i_mode ^ d_inode(origin)->i_mode) & S_IFMT)) {
                /*
@@ -547,6 +541,11 @@ out:
        kfree(name.name);
        return index;
 
+out_dput:
+       dput(index);
+       index = NULL;
+       goto out;
+
 fail:
        dput(index);
        index = ERR_PTR(-EIO);
@@ -635,6 +634,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                }
 
                if (d.redirect) {
+                       err = -ENOMEM;
                        upperredirect = kstrdup(d.redirect, GFP_KERNEL);
                        if (!upperredirect)
                                goto out_put_upper;
@@ -709,7 +709,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
                upperdentry = dget(index);
 
        if (upperdentry || ctr) {
-               inode = ovl_get_inode(dentry, upperdentry);
+               inode = ovl_get_inode(dentry, upperdentry, index);
                err = PTR_ERR(inode);
                if (IS_ERR(inode))
                        goto out_free_oe;
index c706a6f999288136b567d75777f5f6742682a9a2..d9a0edd4e57e40c6157613a652d0dffe86335c07 100644 (file)
@@ -286,7 +286,8 @@ int ovl_update_time(struct inode *inode, struct timespec *ts, int flags);
 bool ovl_is_private_xattr(const char *name);
 
 struct inode *ovl_new_inode(struct super_block *sb, umode_t mode, dev_t rdev);
-struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry);
+struct inode *ovl_get_inode(struct dentry *dentry, struct dentry *upperdentry,
+                           struct dentry *index);
 static inline void ovl_copyattr(struct inode *from, struct inode *to)
 {
        to->i_uid = from->i_uid;
index 0f85ee9c3268adb320dcc6c4d37e88ae3ea92013..698b74dd750ee6a9fb2586d0f8d42853111e6bd1 100644 (file)
@@ -1021,13 +1021,12 @@ int ovl_indexdir_cleanup(struct dentry *dentry, struct vfsmount *mnt,
                        break;
                }
                err = ovl_verify_index(index, lowerstack, numlower);
-               if (err) {
-                       if (err == -EROFS)
-                               break;
+               /* Cleanup stale and orphan index entries */
+               if (err && (err == -ESTALE || err == -ENOENT))
                        err = ovl_cleanup(dir, index);
-                       if (err)
-                               break;
-               }
+               if (err)
+                       break;
+
                dput(index);
                index = NULL;
        }
index 092d150643c12061407be0ecab554a38fe88d9fc..f5738e96a052fe06c892923b69cd4708d8b24f70 100644 (file)
@@ -174,6 +174,9 @@ static struct inode *ovl_alloc_inode(struct super_block *sb)
 {
        struct ovl_inode *oi = kmem_cache_alloc(ovl_inode_cachep, GFP_KERNEL);
 
+       if (!oi)
+               return NULL;
+
        oi->cache = NULL;
        oi->redirect = NULL;
        oi->version = 0;
index 56d0e526870c61970939373fabaddaeecfa0253c..6526ef0e2a234965e7895e823b544f24faedb81a 100644 (file)
@@ -237,11 +237,13 @@ xfs_file_dax_read(
        if (!count)
                return 0; /* skip atime */
 
-       if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
-               if (iocb->ki_flags & IOCB_NOWAIT)
+       if (iocb->ki_flags & IOCB_NOWAIT) {
+               if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
                        return -EAGAIN;
+       } else {
                xfs_ilock(ip, XFS_IOLOCK_SHARED);
        }
+
        ret = dax_iomap_rw(iocb, to, &xfs_iomap_ops);
        xfs_iunlock(ip, XFS_IOLOCK_SHARED);
 
@@ -259,9 +261,10 @@ xfs_file_buffered_aio_read(
 
        trace_xfs_file_buffered_read(ip, iov_iter_count(to), iocb->ki_pos);
 
-       if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED)) {
-               if (iocb->ki_flags & IOCB_NOWAIT)
+       if (iocb->ki_flags & IOCB_NOWAIT) {
+               if (!xfs_ilock_nowait(ip, XFS_IOLOCK_SHARED))
                        return -EAGAIN;
+       } else {
                xfs_ilock(ip, XFS_IOLOCK_SHARED);
        }
        ret = generic_file_read_iter(iocb, to);
@@ -552,9 +555,10 @@ xfs_file_dio_aio_write(
                iolock = XFS_IOLOCK_SHARED;
        }
 
-       if (!xfs_ilock_nowait(ip, iolock)) {
-               if (iocb->ki_flags & IOCB_NOWAIT)
+       if (iocb->ki_flags & IOCB_NOWAIT) {
+               if (!xfs_ilock_nowait(ip, iolock))
                        return -EAGAIN;
+       } else {
                xfs_ilock(ip, iolock);
        }
 
@@ -606,9 +610,10 @@ xfs_file_dax_write(
        size_t                  count;
        loff_t                  pos;
 
-       if (!xfs_ilock_nowait(ip, iolock)) {
-               if (iocb->ki_flags & IOCB_NOWAIT)
+       if (iocb->ki_flags & IOCB_NOWAIT) {
+               if (!xfs_ilock_nowait(ip, iolock))
                        return -EAGAIN;
+       } else {
                xfs_ilock(ip, iolock);
        }
 
index 0d7b56d913087590d7db17d7b29290b048812162..13edf19ce9fb5e1eddeb366bc315cb9a92ba691e 100644 (file)
@@ -74,8 +74,8 @@ void tap_del_queues(struct tap_dev *tap);
 int tap_get_minor(dev_t major, struct tap_dev *tap);
 void tap_free_minor(dev_t major, struct tap_dev *tap);
 int tap_queue_resize(struct tap_dev *tap);
-int tap_create_cdev(struct cdev *tap_cdev,
-                   dev_t *tap_major, const char *device_name);
+int tap_create_cdev(struct cdev *tap_cdev, dev_t *tap_major,
+                   const char *device_name, struct module *module);
 void tap_destroy_cdev(dev_t major, struct cdev *tap_cdev);
 
 #endif /*_LINUX_IF_TAP_H_*/
index c57d4b7de3a80203719f36319d17fb4794dd40b7..c59af8ab753a4f9eb35cb5da124fd7a0990339d0 100644 (file)
@@ -157,6 +157,8 @@ int mlx5_set_port_prio_tc(struct mlx5_core_dev *mdev, u8 *prio_tc);
 int mlx5_query_port_prio_tc(struct mlx5_core_dev *mdev,
                            u8 prio, u8 *tc);
 int mlx5_set_port_tc_group(struct mlx5_core_dev *mdev, u8 *tc_group);
+int mlx5_query_port_tc_group(struct mlx5_core_dev *mdev,
+                            u8 tc, u8 *tc_group);
 int mlx5_set_port_tc_bw_alloc(struct mlx5_core_dev *mdev, u8 *tc_bw);
 int mlx5_query_port_tc_bw_alloc(struct mlx5_core_dev *mdev,
                                u8 tc, u8 *bw_pct);
index 82b171e1aa0b8e0f074b0300f630c909a91d6a16..da803dfc7a3980a732ed328db276e12a1ae75e03 100644 (file)
@@ -231,7 +231,7 @@ struct sctp_datahdr {
        __be32 tsn;
        __be16 stream;
        __be16 ssn;
-       __be32 ppid;
+       __u32 ppid;
        __u8  payload[0];
 };
 
@@ -716,28 +716,28 @@ struct sctp_reconf_chunk {
 
 struct sctp_strreset_outreq {
        struct sctp_paramhdr param_hdr;
-       __u32 request_seq;
-       __u32 response_seq;
-       __u32 send_reset_at_tsn;
-       __u16 list_of_streams[0];
+       __be32 request_seq;
+       __be32 response_seq;
+       __be32 send_reset_at_tsn;
+       __be16 list_of_streams[0];
 };
 
 struct sctp_strreset_inreq {
        struct sctp_paramhdr param_hdr;
-       __u32 request_seq;
-       __u16 list_of_streams[0];
+       __be32 request_seq;
+       __be16 list_of_streams[0];
 };
 
 struct sctp_strreset_tsnreq {
        struct sctp_paramhdr param_hdr;
-       __u32 request_seq;
+       __be32 request_seq;
 };
 
 struct sctp_strreset_addstrm {
        struct sctp_paramhdr param_hdr;
-       __u32 request_seq;
-       __u16 number_of_streams;
-       __u16 reserved;
+       __be32 request_seq;
+       __be16 number_of_streams;
+       __be16 reserved;
 };
 
 enum {
@@ -752,16 +752,16 @@ enum {
 
 struct sctp_strreset_resp {
        struct sctp_paramhdr param_hdr;
-       __u32 response_seq;
-       __u32 result;
+       __be32 response_seq;
+       __be32 result;
 };
 
 struct sctp_strreset_resptsn {
        struct sctp_paramhdr param_hdr;
-       __u32 response_seq;
-       __u32 result;
-       __u32 senders_next_tsn;
-       __u32 receivers_next_tsn;
+       __be32 response_seq;
+       __be32 result;
+       __be32 senders_next_tsn;
+       __be32 receivers_next_tsn;
 };
 
 #endif /* __LINUX_SCTP_H__ */
index 29c9eb48ca89a1a26d39459bd7f2036e3cb46e4c..c98aaf6774665ea9970968f83bc45707a977757d 100644 (file)
 /*
  * Simple wait queues
  *
- * While these are very similar to the other/complex wait queues (wait.h) the
- * most important difference is that the simple waitqueue allows for
- * deterministic behaviour -- IOW it has strictly bounded IRQ and lock hold
- * times.
+ * While these are very similar to regular wait queues (wait.h) the most
+ * important difference is that the simple waitqueue allows for deterministic
+ * behaviour -- IOW it has strictly bounded IRQ and lock hold times.
  *
- * In order to make this so, we had to drop a fair number of features of the
- * other waitqueue code; notably:
+ * Mainly, this is accomplished by two things. Firstly not allowing swake_up_all
+ * from IRQ disabled, and dropping the lock upon every wakeup, giving a higher
+ * priority task a chance to run.
+ *
+ * Secondly, we had to drop a fair number of features of the other waitqueue
+ * code; notably:
  *
  *  - mixing INTERRUPTIBLE and UNINTERRUPTIBLE sleeps on the same waitqueue;
  *    all wakeups are TASK_NORMAL in order to avoid O(n) lookups for the right
  *  - the exclusive mode; because this requires preserving the list order
  *    and this is hard.
  *
- *  - custom wake functions; because you cannot give any guarantees about
- *    random code.
- *
- * As a side effect of this; the data structures are slimmer.
+ *  - custom wake callback functions; because you cannot give any guarantees
+ *    about random code. This also allows swait to be used in RT, such that
+ *    raw spinlock can be used for the swait queue head.
  *
- * One would recommend using this wait queue where possible.
+ * As a side effect of these; the data structures are slimmer albeit more ad-hoc.
+ * For all the above, note that simple wait queues should _only_ be used under
+ * very specific realtime constraints -- it is best to stick with the regular
+ * wait queues in most cases.
  */
 
 struct task_struct;
index 4e6131cd3f43dfb711049a1925abbea6074ec25b..ac1a2317941e7186abd01d3df0bf9ebc055be38b 100644 (file)
@@ -146,6 +146,7 @@ static void fq_tin_enqueue(struct fq *fq,
                           fq_flow_get_default_t get_default_func)
 {
        struct fq_flow *flow;
+       bool oom;
 
        lockdep_assert_held(&fq->lock);
 
@@ -167,8 +168,8 @@ static void fq_tin_enqueue(struct fq *fq,
        }
 
        __skb_queue_tail(&flow->queue, skb);
-
-       if (fq->backlog > fq->limit || fq->memory_usage > fq->memory_limit) {
+       oom = (fq->memory_usage > fq->memory_limit);
+       while (fq->backlog > fq->limit || oom) {
                flow = list_first_entry_or_null(&fq->backlogs,
                                                struct fq_flow,
                                                backlogchain);
@@ -183,8 +184,10 @@ static void fq_tin_enqueue(struct fq *fq,
 
                flow->tin->overlimit++;
                fq->overlimit++;
-               if (fq->memory_usage > fq->memory_limit)
+               if (oom) {
                        fq->overmemory++;
+                       oom = (fq->memory_usage > fq->memory_limit);
+               }
        }
 }
 
index 425752f768d2f1a0efb13964204e07f27609e9db..db8162dd8c0bcbcaffcb1a0f6da1be139a5008d4 100644 (file)
@@ -132,6 +132,12 @@ static inline int inet_request_bound_dev_if(const struct sock *sk,
        return sk->sk_bound_dev_if;
 }
 
+static inline struct ip_options_rcu *ireq_opt_deref(const struct inet_request_sock *ireq)
+{
+       return rcu_dereference_check(ireq->ireq_opt,
+                                    refcount_read(&ireq->req.rsk_refcnt) > 0);
+}
+
 struct inet_cork {
        unsigned int            flags;
        __be32                  addr;
index 13b23f3ed69a2d0384ecd17d243e19b1f31128ab..70ca2437740e41284d7b40b5c202d85fc2e6668b 100644 (file)
@@ -3,6 +3,7 @@
 #define __NET_PKT_CLS_H
 
 #include <linux/pkt_cls.h>
+#include <linux/workqueue.h>
 #include <net/sch_generic.h>
 #include <net/act_api.h>
 
@@ -18,6 +19,8 @@ struct tcf_walker {
 int register_tcf_proto_ops(struct tcf_proto_ops *ops);
 int unregister_tcf_proto_ops(struct tcf_proto_ops *ops);
 
+bool tcf_queue_work(struct work_struct *work);
+
 #ifdef CONFIG_NET_CLS
 struct tcf_chain *tcf_chain_get(struct tcf_block *block, u32 chain_index,
                                bool create);
index 1b33a6c8b477d5d7d098596085dd0f0fc809ff05..236bfe5b2ffe5252ecb1ae9e59251d597315bc6d 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/dynamic_queue_limits.h>
 #include <linux/list.h>
 #include <linux/refcount.h>
+#include <linux/workqueue.h>
 #include <net/gen_stats.h>
 #include <net/rtnetlink.h>
 
@@ -272,6 +273,7 @@ struct tcf_chain {
 
 struct tcf_block {
        struct list_head chain_list;
+       struct work_struct work;
 };
 
 static inline void qdisc_cb_private_validate(const struct sk_buff *skb, int sz)
index 2db3d3a9ce1d2cd053954bff3d66d06a9246e5c1..88233cf8b8d4f1c4d59a7a897b7a4c4af9f8c779 100644 (file)
@@ -261,7 +261,7 @@ struct sctp_chunk *sctp_make_fwdtsn(const struct sctp_association *asoc,
                                    struct sctp_fwdtsn_skip *skiplist);
 struct sctp_chunk *sctp_make_auth(const struct sctp_association *asoc);
 struct sctp_chunk *sctp_make_strreset_req(const struct sctp_association *asoc,
-                                         __u16 stream_num, __u16 *stream_list,
+                                         __u16 stream_num, __be16 *stream_list,
                                          bool out, bool in);
 struct sctp_chunk *sctp_make_strreset_tsnreq(
                                        const struct sctp_association *asoc);
index b8c86ec1a8f5a4b3f025de849b8a6da5772b7427..231dc42f1da687b647bcf43d2fb856e252f4b881 100644 (file)
@@ -130,7 +130,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 
 struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
        const struct sctp_association *asoc, __u16 flags,
-       __u16 stream_num, __u16 *stream_list, gfp_t gfp);
+       __u16 stream_num, __be16 *stream_list, gfp_t gfp);
 
 struct sctp_ulpevent *sctp_ulpevent_make_assoc_reset_event(
        const struct sctp_association *asoc, __u16 flags,
index 7dc131d62ad5c3a5a8cb67c91d1f3d86e7207410..d96b59f45ebaac1280f1ca53bb923a0147ade6a9 100644 (file)
@@ -74,10 +74,9 @@ struct strparser {
        u32 unrecov_intr : 1;
 
        struct sk_buff **skb_nextp;
-       struct timer_list msg_timer;
        struct sk_buff *skb_head;
        unsigned int need_bytes;
-       struct delayed_work delayed_work;
+       struct delayed_work msg_timer_work;
        struct work_struct work;
        struct strp_stats stats;
        struct strp_callbacks cb;
index b1ef98ebce53cd259a2894f4575cb18cc7755331..e6d0002a1b0bc5f28c331a760823c8dc92f8fe24 100644 (file)
@@ -844,6 +844,7 @@ struct tcp_skb_cb {
                        __u32 key;
                        __u32 flags;
                        struct bpf_map *map;
+                       void *data_end;
                } bpf;
        };
 };
@@ -1770,12 +1771,12 @@ static inline void tcp_highest_sack_reset(struct sock *sk)
        tcp_sk(sk)->highest_sack = tcp_write_queue_head(sk);
 }
 
-/* Called when old skb is about to be deleted (to be combined with new skb) */
-static inline void tcp_highest_sack_combine(struct sock *sk,
+/* Called when old skb is about to be deleted and replaced by new skb */
+static inline void tcp_highest_sack_replace(struct sock *sk,
                                            struct sk_buff *old,
                                            struct sk_buff *new)
 {
-       if (tcp_sk(sk)->sacked_out && (old == tcp_sk(sk)->highest_sack))
+       if (old == tcp_highest_sack(sk))
                tcp_sk(sk)->highest_sack = new;
 }
 
index 8012b4ff959b6a748962411a6adc622001947e8b..30f2ce76b5170c8ea04f93a8f8f70f4633e4322b 100644 (file)
@@ -576,7 +576,7 @@ union bpf_attr {
  *     @map: pointer to sockmap
  *     @key: key to lookup sock in map
  *     @flags: reserved for future use
- *     Return: SK_REDIRECT
+ *     Return: SK_PASS
  *
  * int bpf_sock_map_update(skops, map, key, flags)
  *     @skops: pointer to bpf_sock_ops
@@ -787,9 +787,8 @@ struct xdp_md {
 };
 
 enum sk_action {
-       SK_ABORTED = 0,
-       SK_DROP,
-       SK_REDIRECT,
+       SK_DROP = 0,
+       SK_PASS,
 };
 
 #define BPF_TAG_SIZE   8
index 32df53012cbd06c3ecf4b3e8f2cfacf25e80b595..cfe9712968350263ded68a2702d781685a10de7e 100644 (file)
@@ -377,7 +377,7 @@ struct sctp_remote_error {
        __u16 sre_type;
        __u16 sre_flags;
        __u32 sre_length;
-       __u16 sre_error;
+       __be16 sre_error;
        sctp_assoc_t sre_assoc_id;
        __u8 sre_data[0];
 };
index ff0e381e7a77e2296928374c083cd907c22bc13a..c4253f0090d8c45d7221194938c680180e0c3240 100644 (file)
@@ -24,6 +24,7 @@
 #define SPIDEV_H
 
 #include <linux/types.h>
+#include <linux/ioctl.h>
 
 /* User space versions of kernel symbols for SPI clocking modes,
  * matching <linux/spi/spi.h>
index 78cb2461012ef530f2755a0a6a8458428ed19043..3c1faaa2af4aad761c427a092c929aeb1acb05f6 100644 (file)
@@ -1033,7 +1033,7 @@ endif
 
 choice
        prompt "Compiler optimization level"
-       default CONFIG_CC_OPTIMIZE_FOR_PERFORMANCE
+       default CC_OPTIMIZE_FOR_PERFORMANCE
 
 config CC_OPTIMIZE_FOR_PERFORMANCE
        bool "Optimize for performance"
index 2b6eb35ae5d39799a9ae33fe5bf07508d2b82a54..dbd7b322a86b5c3eb7150d2cc886223da6387b70 100644 (file)
@@ -93,13 +93,27 @@ static inline struct smap_psock *smap_psock_sk(const struct sock *sk)
        return rcu_dereference_sk_user_data(sk);
 }
 
+/* compute the linear packet data range [data, data_end) for skb when
+ * sk_skb type programs are in use.
+ */
+static inline void bpf_compute_data_end_sk_skb(struct sk_buff *skb)
+{
+       TCP_SKB_CB(skb)->bpf.data_end = skb->data + skb_headlen(skb);
+}
+
+enum __sk_action {
+       __SK_DROP = 0,
+       __SK_PASS,
+       __SK_REDIRECT,
+};
+
 static int smap_verdict_func(struct smap_psock *psock, struct sk_buff *skb)
 {
        struct bpf_prog *prog = READ_ONCE(psock->bpf_verdict);
        int rc;
 
        if (unlikely(!prog))
-               return SK_DROP;
+               return __SK_DROP;
 
        skb_orphan(skb);
        /* We need to ensure that BPF metadata for maps is also cleared
@@ -108,13 +122,16 @@ static int smap_verdict_func(struct smap_psock *psock, struct sk_buff *skb)
         */
        TCP_SKB_CB(skb)->bpf.map = NULL;
        skb->sk = psock->sock;
-       bpf_compute_data_end(skb);
+       bpf_compute_data_end_sk_skb(skb);
        preempt_disable();
        rc = (*prog->bpf_func)(skb, prog->insnsi);
        preempt_enable();
        skb->sk = NULL;
 
-       return rc;
+       /* Moving return codes from UAPI namespace into internal namespace */
+       return rc == SK_PASS ?
+               (TCP_SKB_CB(skb)->bpf.map ? __SK_REDIRECT : __SK_PASS) :
+               __SK_DROP;
 }
 
 static void smap_do_verdict(struct smap_psock *psock, struct sk_buff *skb)
@@ -124,7 +141,7 @@ static void smap_do_verdict(struct smap_psock *psock, struct sk_buff *skb)
 
        rc = smap_verdict_func(psock, skb);
        switch (rc) {
-       case SK_REDIRECT:
+       case __SK_REDIRECT:
                sk = do_sk_redirect_map(skb);
                if (likely(sk)) {
                        struct smap_psock *peer = smap_psock_sk(sk);
@@ -140,7 +157,7 @@ static void smap_do_verdict(struct smap_psock *psock, struct sk_buff *skb)
                        }
                }
        /* Fall through and free skb otherwise */
-       case SK_DROP:
+       case __SK_DROP:
        default:
                kfree_skb(skb);
        }
@@ -368,7 +385,7 @@ static int smap_parse_func_strparser(struct strparser *strp,
         * any socket yet.
         */
        skb->sk = psock->sock;
-       bpf_compute_data_end(skb);
+       bpf_compute_data_end_sk_skb(skb);
        rc = (*prog->bpf_func)(skb, prog->insnsi);
        skb->sk = NULL;
        rcu_read_unlock();
index 0518a0bfc746bab4f257f2fa81ef7361f99ff113..0d638f008bb13a2d6e70d3aa607e09564f5aa1c4 100644 (file)
@@ -1570,8 +1570,16 @@ static int futex_atomic_op_inuser(unsigned int encoded_op, u32 __user *uaddr)
        int oldval, ret;
 
        if (encoded_op & (FUTEX_OP_OPARG_SHIFT << 28)) {
-               if (oparg < 0 || oparg > 31)
-                       return -EINVAL;
+               if (oparg < 0 || oparg > 31) {
+                       char comm[sizeof(current->comm)];
+                       /*
+                        * kill this print and return -EINVAL when userspace
+                        * is sane again
+                        */
+                       pr_info_ratelimited("futex_wake_op: %s tries to shift op by %d; fix this program\n",
+                                       get_task_comm(comm, current), oparg);
+                       oparg &= 31;
+               }
                oparg = 1 << oparg;
        }
 
index 800a18f77732c14cf49d81bc615b01cd56d11933..8dcd8825b2dedf3f16c108808192f8751aa19c96 100644 (file)
@@ -2698,7 +2698,7 @@ enum siginfo_layout siginfo_layout(int sig, int si_code)
                        [SIGSEGV] = { NSIGSEGV, SIL_FAULT },
                        [SIGBUS]  = { NSIGBUS,  SIL_FAULT },
                        [SIGTRAP] = { NSIGTRAP, SIL_FAULT },
-#if defined(SIGMET) && defined(NSIGEMT)
+#if defined(SIGEMT) && defined(NSIGEMT)
                        [SIGEMT]  = { NSIGEMT,  SIL_FAULT },
 #endif
                        [SIGCHLD] = { NSIGCHLD, SIL_CHLD },
index 64d0edf428f850f2e5cfed94970cb74491eb6b61..a2dccfe1acec34bbda97a292344b997055e56d9a 100644 (file)
@@ -68,6 +68,7 @@ enum {
         * attach_mutex to avoid changing binding state while
         * worker_attach_to_pool() is in progress.
         */
+       POOL_MANAGER_ACTIVE     = 1 << 0,       /* being managed */
        POOL_DISASSOCIATED      = 1 << 2,       /* cpu can't serve workers */
 
        /* worker flags */
@@ -165,7 +166,6 @@ struct worker_pool {
                                                /* L: hash of busy workers */
 
        /* see manage_workers() for details on the two manager mutexes */
-       struct mutex            manager_arb;    /* manager arbitration */
        struct worker           *manager;       /* L: purely informational */
        struct mutex            attach_mutex;   /* attach/detach exclusion */
        struct list_head        workers;        /* A: attached workers */
@@ -299,6 +299,7 @@ static struct workqueue_attrs *wq_update_unbound_numa_attrs_buf;
 
 static DEFINE_MUTEX(wq_pool_mutex);    /* protects pools and workqueues list */
 static DEFINE_SPINLOCK(wq_mayday_lock);        /* protects wq->maydays list */
+static DECLARE_WAIT_QUEUE_HEAD(wq_manager_wait); /* wait for manager to go away */
 
 static LIST_HEAD(workqueues);          /* PR: list of all workqueues */
 static bool workqueue_freezing;                /* PL: have wqs started freezing? */
@@ -801,7 +802,7 @@ static bool need_to_create_worker(struct worker_pool *pool)
 /* Do we have too many workers and should some go away? */
 static bool too_many_workers(struct worker_pool *pool)
 {
-       bool managing = mutex_is_locked(&pool->manager_arb);
+       bool managing = pool->flags & POOL_MANAGER_ACTIVE;
        int nr_idle = pool->nr_idle + managing; /* manager is considered idle */
        int nr_busy = pool->nr_workers - nr_idle;
 
@@ -1980,24 +1981,17 @@ static bool manage_workers(struct worker *worker)
 {
        struct worker_pool *pool = worker->pool;
 
-       /*
-        * Anyone who successfully grabs manager_arb wins the arbitration
-        * and becomes the manager.  mutex_trylock() on pool->manager_arb
-        * failure while holding pool->lock reliably indicates that someone
-        * else is managing the pool and the worker which failed trylock
-        * can proceed to executing work items.  This means that anyone
-        * grabbing manager_arb is responsible for actually performing
-        * manager duties.  If manager_arb is grabbed and released without
-        * actual management, the pool may stall indefinitely.
-        */
-       if (!mutex_trylock(&pool->manager_arb))
+       if (pool->flags & POOL_MANAGER_ACTIVE)
                return false;
+
+       pool->flags |= POOL_MANAGER_ACTIVE;
        pool->manager = worker;
 
        maybe_create_worker(pool);
 
        pool->manager = NULL;
-       mutex_unlock(&pool->manager_arb);
+       pool->flags &= ~POOL_MANAGER_ACTIVE;
+       wake_up(&wq_manager_wait);
        return true;
 }
 
@@ -3248,7 +3242,6 @@ static int init_worker_pool(struct worker_pool *pool)
        setup_timer(&pool->mayday_timer, pool_mayday_timeout,
                    (unsigned long)pool);
 
-       mutex_init(&pool->manager_arb);
        mutex_init(&pool->attach_mutex);
        INIT_LIST_HEAD(&pool->workers);
 
@@ -3318,13 +3311,15 @@ static void put_unbound_pool(struct worker_pool *pool)
        hash_del(&pool->hash_node);
 
        /*
-        * Become the manager and destroy all workers.  Grabbing
-        * manager_arb prevents @pool's workers from blocking on
-        * attach_mutex.
+        * Become the manager and destroy all workers.  This prevents
+        * @pool's workers from blocking on attach_mutex.  We're the last
+        * manager and @pool gets freed with the flag set.
         */
-       mutex_lock(&pool->manager_arb);
-
        spin_lock_irq(&pool->lock);
+       wait_event_lock_irq(wq_manager_wait,
+                           !(pool->flags & POOL_MANAGER_ACTIVE), pool->lock);
+       pool->flags |= POOL_MANAGER_ACTIVE;
+
        while ((worker = first_idle_worker(pool)))
                destroy_worker(worker);
        WARN_ON(pool->nr_workers || pool->nr_idle);
@@ -3338,8 +3333,6 @@ static void put_unbound_pool(struct worker_pool *pool)
        if (pool->detach_completion)
                wait_for_completion(pool->detach_completion);
 
-       mutex_unlock(&pool->manager_arb);
-
        /* shut down the timers */
        del_timer_sync(&pool->idle_timer);
        del_timer_sync(&pool->mayday_timer);
index 0bd8a611eb83c99aad01fcee01143bbaad490845..fef5d2e114be1eef73b78653ce84a915da3e59d3 100644 (file)
@@ -284,6 +284,9 @@ next_op:
                                if (unlikely(len > datalen - dp))
                                        goto data_overrun_error;
                        }
+               } else {
+                       if (unlikely(len > datalen - dp))
+                               goto data_overrun_error;
                }
 
                if (flags & FLAG_CONS) {
index 155c55d8db5fccb3ded0047d1fb1fcfef7673072..4e53be8bc590dc2030a930aec5a2cac8c4fa6a30 100644 (file)
@@ -598,21 +598,31 @@ static bool assoc_array_insert_into_terminal_node(struct assoc_array_edit *edit,
                if ((edit->segment_cache[ASSOC_ARRAY_FAN_OUT] ^ base_seg) == 0)
                        goto all_leaves_cluster_together;
 
-               /* Otherwise we can just insert a new node ahead of the old
-                * one.
+               /* Otherwise all the old leaves cluster in the same slot, but
+                * the new leaf wants to go into a different slot - so we
+                * create a new node (n0) to hold the new leaf and a pointer to
+                * a new node (n1) holding all the old leaves.
+                *
+                * This can be done by falling through to the node splitting
+                * path.
                 */
-               goto present_leaves_cluster_but_not_new_leaf;
+               pr_devel("present leaves cluster but not new leaf\n");
        }
 
 split_node:
        pr_devel("split node\n");
 
-       /* We need to split the current node; we know that the node doesn't
-        * simply contain a full set of leaves that cluster together (it
-        * contains meta pointers and/or non-clustering leaves).
+       /* We need to split the current node.  The node must contain anything
+        * from a single leaf (in the one leaf case, this leaf will cluster
+        * with the new leaf) and the rest meta-pointers, to all leaves, some
+        * of which may cluster.
+        *
+        * It won't contain the case in which all the current leaves plus the
+        * new leaves want to cluster in the same slot.
         *
         * We need to expel at least two leaves out of a set consisting of the
-        * leaves in the node and the new leaf.
+        * leaves in the node and the new leaf.  The current meta pointers can
+        * just be copied as they shouldn't cluster with any of the leaves.
         *
         * We need a new node (n0) to replace the current one and a new node to
         * take the expelled nodes (n1).
@@ -717,33 +727,6 @@ found_slot_for_multiple_occupancy:
        pr_devel("<--%s() = ok [split node]\n", __func__);
        return true;
 
-present_leaves_cluster_but_not_new_leaf:
-       /* All the old leaves cluster in the same slot, but the new leaf wants
-        * to go into a different slot, so we create a new node to hold the new
-        * leaf and a pointer to a new node holding all the old leaves.
-        */
-       pr_devel("present leaves cluster but not new leaf\n");
-
-       new_n0->back_pointer = node->back_pointer;
-       new_n0->parent_slot = node->parent_slot;
-       new_n0->nr_leaves_on_branch = node->nr_leaves_on_branch;
-       new_n1->back_pointer = assoc_array_node_to_ptr(new_n0);
-       new_n1->parent_slot = edit->segment_cache[0];
-       new_n1->nr_leaves_on_branch = node->nr_leaves_on_branch;
-       edit->adjust_count_on = new_n0;
-
-       for (i = 0; i < ASSOC_ARRAY_FAN_OUT; i++)
-               new_n1->slots[i] = node->slots[i];
-
-       new_n0->slots[edit->segment_cache[0]] = assoc_array_node_to_ptr(new_n0);
-       edit->leaf_p = &new_n0->slots[edit->segment_cache[ASSOC_ARRAY_FAN_OUT]];
-
-       edit->set[0].ptr = &assoc_array_ptr_to_node(node->back_pointer)->slots[node->parent_slot];
-       edit->set[0].to = assoc_array_node_to_ptr(new_n0);
-       edit->excised_meta[0] = assoc_array_node_to_ptr(node);
-       pr_devel("<--%s() = ok [insert node before]\n", __func__);
-       return true;
-
 all_leaves_cluster_together:
        /* All the leaves, new and old, want to cluster together in this node
         * in the same slot, so we have to replace this node with a shortcut to
index ac7802b0a117aa07d203185265f002409cc618a5..b808a390e4c3e32d2789b059ab7752c6d533d7a3 100644 (file)
@@ -162,6 +162,7 @@ int ioremap_page_range(unsigned long addr,
        unsigned long next;
        int err;
 
+       might_sleep();
        BUG_ON(addr >= end);
 
        start = addr;
index aa0265997f930c86229ee1658063ba9718c6dc79..6ae94f825f72eb810b5252e10dd89cae66f8cbef 100644 (file)
@@ -1844,14 +1844,15 @@ BPF_CALL_4(bpf_sk_redirect_map, struct sk_buff *, skb,
 {
        struct tcp_skb_cb *tcb = TCP_SKB_CB(skb);
 
+       /* If user passes invalid input drop the packet. */
        if (unlikely(flags))
-               return SK_ABORTED;
+               return SK_DROP;
 
        tcb->bpf.key = key;
        tcb->bpf.flags = flags;
        tcb->bpf.map = map;
 
-       return SK_REDIRECT;
+       return SK_PASS;
 }
 
 struct sock *do_sk_redirect_map(struct sk_buff *skb)
@@ -4243,6 +4244,31 @@ static u32 sock_ops_convert_ctx_access(enum bpf_access_type type,
        return insn - insn_buf;
 }
 
+static u32 sk_skb_convert_ctx_access(enum bpf_access_type type,
+                                    const struct bpf_insn *si,
+                                    struct bpf_insn *insn_buf,
+                                    struct bpf_prog *prog, u32 *target_size)
+{
+       struct bpf_insn *insn = insn_buf;
+       int off;
+
+       switch (si->off) {
+       case offsetof(struct __sk_buff, data_end):
+               off  = si->off;
+               off -= offsetof(struct __sk_buff, data_end);
+               off += offsetof(struct sk_buff, cb);
+               off += offsetof(struct tcp_skb_cb, bpf.data_end);
+               *insn++ = BPF_LDX_MEM(BPF_SIZEOF(void *), si->dst_reg,
+                                     si->src_reg, off);
+               break;
+       default:
+               return bpf_convert_ctx_access(type, si, insn_buf, prog,
+                                             target_size);
+       }
+
+       return insn - insn_buf;
+}
+
 const struct bpf_verifier_ops sk_filter_prog_ops = {
        .get_func_proto         = sk_filter_func_proto,
        .is_valid_access        = sk_filter_is_valid_access,
@@ -4301,7 +4327,7 @@ const struct bpf_verifier_ops sock_ops_prog_ops = {
 const struct bpf_verifier_ops sk_skb_prog_ops = {
        .get_func_proto         = sk_skb_func_proto,
        .is_valid_access        = sk_skb_is_valid_access,
-       .convert_ctx_access     = bpf_convert_ctx_access,
+       .convert_ctx_access     = sk_skb_convert_ctx_access,
        .gen_prologue           = sk_skb_prologue,
 };
 
index 0490916864f93d5466e87f5b97dc524b3ee57a2e..e65fcb45c3f6c1edc70fc9898ebe6404175b102f 100644 (file)
@@ -495,7 +495,7 @@ static int dccp_v4_send_response(const struct sock *sk, struct request_sock *req
                                                              ireq->ir_rmt_addr);
                err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
                                            ireq->ir_rmt_addr,
-                                           rcu_dereference(ireq->ireq_opt));
+                                           ireq_opt_deref(ireq));
                err = net_xmit_eval(err);
        }
 
index 873af0108e243fc269f591ec7d7c59a9c8b374fc..045d8a1762793142de2619497da3034f0af55e0c 100644 (file)
@@ -496,14 +496,15 @@ static int dsa_cpu_parse(struct dsa_port *port, u32 index,
                if (!ethernet)
                        return -EINVAL;
                ethernet_dev = of_find_net_device_by_node(ethernet);
+               if (!ethernet_dev)
+                       return -EPROBE_DEFER;
        } else {
                ethernet_dev = dsa_dev_to_net_device(ds->cd->netdev[index]);
+               if (!ethernet_dev)
+                       return -EPROBE_DEFER;
                dev_put(ethernet_dev);
        }
 
-       if (!ethernet_dev)
-               return -EPROBE_DEFER;
-
        if (!dst->cpu_dp) {
                dst->cpu_dp = port;
                dst->cpu_dp->netdev = ethernet_dev;
index f360341c72eb10c05913645456f14ef1797ecff8..7d1ec76e7f433a2525581782a0bf14731548d4a8 100644 (file)
@@ -137,6 +137,6 @@ int ife_tlv_meta_encode(void *skbdata, u16 attrtype, u16 dlen, const void *dval)
 EXPORT_SYMBOL_GPL(ife_tlv_meta_encode);
 
 MODULE_AUTHOR("Jamal Hadi Salim <jhs@mojatatu.com>");
-MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>");
+MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>");
 MODULE_DESCRIPTION("Inter-FE LFB action");
 MODULE_LICENSE("GPL");
index 5ec9136a7c36933cb36e5cd50058eb6cf189a7c3..b47a59cb3573b3b77aa5cbb9c2739a12ef37a237 100644 (file)
@@ -543,7 +543,8 @@ struct dst_entry *inet_csk_route_req(const struct sock *sk,
        struct ip_options_rcu *opt;
        struct rtable *rt;
 
-       opt = rcu_dereference(ireq->ireq_opt);
+       opt = ireq_opt_deref(ireq);
+
        flowi4_init_output(fl4, ireq->ir_iif, ireq->ir_mark,
                           RT_CONN_FLAGS(sk), RT_SCOPE_UNIVERSE,
                           sk->sk_protocol, inet_sk_flowi_flags(sk),
index fb1ad22b5e292d5669c70b5640ad3207c353c6bb..cdd627355ed106ae8228ee4a995f5f3b4588a842 100644 (file)
@@ -128,43 +128,68 @@ static struct rtnl_link_ops ipip_link_ops __read_mostly;
 
 static int ipip_err(struct sk_buff *skb, u32 info)
 {
-
-/* All the routers (except for Linux) return only
-   8 bytes of packet payload. It means, that precise relaying of
-   ICMP in the real Internet is absolutely infeasible.
- */
+       /* All the routers (except for Linux) return only
+        * 8 bytes of packet payload. It means, that precise relaying of
+        * ICMP in the real Internet is absolutely infeasible.
+        */
        struct net *net = dev_net(skb->dev);
        struct ip_tunnel_net *itn = net_generic(net, ipip_net_id);
        const struct iphdr *iph = (const struct iphdr *)skb->data;
-       struct ip_tunnel *t;
-       int err;
        const int type = icmp_hdr(skb)->type;
        const int code = icmp_hdr(skb)->code;
+       struct ip_tunnel *t;
+       int err = 0;
+
+       switch (type) {
+       case ICMP_DEST_UNREACH:
+               switch (code) {
+               case ICMP_SR_FAILED:
+                       /* Impossible event. */
+                       goto out;
+               default:
+                       /* All others are translated to HOST_UNREACH.
+                        * rfc2003 contains "deep thoughts" about NET_UNREACH,
+                        * I believe they are just ether pollution. --ANK
+                        */
+                       break;
+               }
+               break;
+
+       case ICMP_TIME_EXCEEDED:
+               if (code != ICMP_EXC_TTL)
+                       goto out;
+               break;
+
+       case ICMP_REDIRECT:
+               break;
+
+       default:
+               goto out;
+       }
 
-       err = -ENOENT;
        t = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
                             iph->daddr, iph->saddr, 0);
-       if (!t)
+       if (!t) {
+               err = -ENOENT;
                goto out;
+       }
 
        if (type == ICMP_DEST_UNREACH && code == ICMP_FRAG_NEEDED) {
-               ipv4_update_pmtu(skb, dev_net(skb->dev), info,
-                                t->parms.link, 0, iph->protocol, 0);
-               err = 0;
+               ipv4_update_pmtu(skb, net, info, t->parms.link, 0,
+                                iph->protocol, 0);
                goto out;
        }
 
        if (type == ICMP_REDIRECT) {
-               ipv4_redirect(skb, dev_net(skb->dev), t->parms.link, 0,
-                             iph->protocol, 0);
-               err = 0;
+               ipv4_redirect(skb, net, t->parms.link, 0, iph->protocol, 0);
                goto out;
        }
 
-       if (t->parms.iph.daddr == 0)
+       if (t->parms.iph.daddr == 0) {
+               err = -ENOENT;
                goto out;
+       }
 
-       err = 0;
        if (t->parms.iph.ttl == 0 && type == ICMP_TIME_EXCEEDED)
                goto out;
 
index 4c43365c374c8bf868fc0b862333244ca26d5016..5b027c69cbc540d4e933189f9de5baab5472eadb 100644 (file)
@@ -877,7 +877,7 @@ static int tcp_v4_send_synack(const struct sock *sk, struct dst_entry *dst,
 
                err = ip_build_and_send_pkt(skb, sk, ireq->ir_loc_addr,
                                            ireq->ir_rmt_addr,
-                                           rcu_dereference(ireq->ireq_opt));
+                                           ireq_opt_deref(ireq));
                err = net_xmit_eval(err);
        }
 
index 0bc9e46a53696578eb6e911f2f75e6b34c80894f..823003eef3a21a5cc5c27e0be9f46159afa060df 100644 (file)
@@ -739,8 +739,10 @@ static void tcp_tsq_handler(struct sock *sk)
                struct tcp_sock *tp = tcp_sk(sk);
 
                if (tp->lost_out > tp->retrans_out &&
-                   tp->snd_cwnd > tcp_packets_in_flight(tp))
+                   tp->snd_cwnd > tcp_packets_in_flight(tp)) {
+                       tcp_mstamp_refresh(tp);
                        tcp_xmit_retransmit_queue(sk);
+               }
 
                tcp_write_xmit(sk, tcp_current_mss(sk), tp->nonagle,
                               0, GFP_ATOMIC);
@@ -2060,6 +2062,7 @@ static int tcp_mtu_probe(struct sock *sk)
        nskb->ip_summed = skb->ip_summed;
 
        tcp_insert_write_queue_before(nskb, skb, sk);
+       tcp_highest_sack_replace(sk, skb, nskb);
 
        len = 0;
        tcp_for_write_queue_from_safe(skb, next, sk) {
@@ -2237,6 +2240,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
 
        sent_pkts = 0;
 
+       tcp_mstamp_refresh(tp);
        if (!push_one) {
                /* Do MTU probing. */
                result = tcp_mtu_probe(sk);
@@ -2248,7 +2252,6 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
        }
 
        max_segs = tcp_tso_segs(sk, mss_now);
-       tcp_mstamp_refresh(tp);
        while ((skb = tcp_send_head(sk))) {
                unsigned int limit;
 
@@ -2663,7 +2666,7 @@ static bool tcp_collapse_retrans(struct sock *sk, struct sk_buff *skb)
                else if (!skb_shift(skb, next_skb, next_skb_size))
                        return false;
        }
-       tcp_highest_sack_combine(sk, next_skb, skb);
+       tcp_highest_sack_replace(sk, next_skb, skb);
 
        tcp_unlink_write_queue(next_skb, sk);
 
@@ -2841,8 +2844,10 @@ int __tcp_retransmit_skb(struct sock *sk, struct sk_buff *skb, int segs)
                nskb = __pskb_copy(skb, MAX_TCP_HEADER, GFP_ATOMIC);
                err = nskb ? tcp_transmit_skb(sk, nskb, 0, GFP_ATOMIC) :
                             -ENOBUFS;
-               if (!err)
+               if (!err) {
                        skb->skb_mstamp = tp->tcp_mstamp;
+                       tcp_rate_skb_sent(sk, skb);
+               }
        } else {
                err = tcp_transmit_skb(sk, skb, 1, GFP_ATOMIC);
        }
index 4a96ebbf8eda5f59a6ff88e836d666a404d2bf0d..8a1c846d3df949a4638589f187120db22a3525ba 100644 (file)
@@ -3335,6 +3335,7 @@ static void addrconf_permanent_addr(struct net_device *dev)
                if ((ifp->flags & IFA_F_PERMANENT) &&
                    fixup_permanent_addr(idev, ifp) < 0) {
                        write_unlock_bh(&idev->lock);
+                       in6_ifa_hold(ifp);
                        ipv6_del_addr(ifp);
                        write_lock_bh(&idev->lock);
 
index 1602b491b281123f691a4a7afc4ba5fe0a99ac55..59c121b932ac5140380e4592568e455caa64287e 100644 (file)
@@ -408,13 +408,16 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
        case ICMPV6_DEST_UNREACH:
                net_dbg_ratelimited("%s: Path to destination invalid or inactive!\n",
                                    t->parms.name);
-               break;
+               if (code != ICMPV6_PORT_UNREACH)
+                       break;
+               return;
        case ICMPV6_TIME_EXCEED:
                if (code == ICMPV6_EXC_HOPLIMIT) {
                        net_dbg_ratelimited("%s: Too small hop limit or routing loop in tunnel!\n",
                                            t->parms.name);
+                       break;
                }
-               break;
+               return;
        case ICMPV6_PARAMPROB:
                teli = 0;
                if (code == ICMPV6_HDR_FIELD)
@@ -430,7 +433,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                        net_dbg_ratelimited("%s: Recipient unable to parse tunneled packet!\n",
                                            t->parms.name);
                }
-               break;
+               return;
        case ICMPV6_PKT_TOOBIG:
                mtu = be32_to_cpu(info) - offset - t->tun_hlen;
                if (t->dev->type == ARPHRD_ETHER)
@@ -438,7 +441,7 @@ static void ip6gre_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
                if (mtu < IPV6_MIN_MTU)
                        mtu = IPV6_MIN_MTU;
                t->dev->mtu = mtu;
-               break;
+               return;
        }
 
        if (time_before(jiffies, t->err_time + IP6TUNNEL_ERR_TIMEO))
@@ -500,8 +503,8 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
                               __u32 *pmtu, __be16 proto)
 {
        struct ip6_tnl *tunnel = netdev_priv(dev);
-       __be16 protocol = (dev->type == ARPHRD_ETHER) ?
-                         htons(ETH_P_TEB) : proto;
+       struct dst_entry *dst = skb_dst(skb);
+       __be16 protocol;
 
        if (dev->type == ARPHRD_ETHER)
                IPCB(skb)->flags = 0;
@@ -515,9 +518,14 @@ static netdev_tx_t __gre6_xmit(struct sk_buff *skb,
                tunnel->o_seqno++;
 
        /* Push GRE header. */
+       protocol = (dev->type == ARPHRD_ETHER) ? htons(ETH_P_TEB) : proto;
        gre_build_header(skb, tunnel->tun_hlen, tunnel->parms.o_flags,
                         protocol, tunnel->parms.o_key, htonl(tunnel->o_seqno));
 
+       /* TooBig packet may have updated dst->dev's mtu */
+       if (dst && dst_mtu(dst) > dst->dev->mtu)
+               dst->ops->update_pmtu(dst, NULL, skb, dst->dev->mtu);
+
        return ip6_tnl_xmit(skb, dev, dsfield, fl6, encap_limit, pmtu,
                            NEXTHDR_GRE);
 }
index f50452b919d5ece9d70e2c25634bc8fef9962e6b..0c2738349442ba705f4240aed29fc4c1d9be727d 100644 (file)
@@ -584,6 +584,7 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
        u32 tunnel_id, peer_tunnel_id;
        u32 session_id, peer_session_id;
        bool drop_refcnt = false;
+       bool drop_tunnel = false;
        int ver = 2;
        int fd;
 
@@ -652,7 +653,9 @@ static int pppol2tp_connect(struct socket *sock, struct sockaddr *uservaddr,
        if (tunnel_id == 0)
                goto end;
 
-       tunnel = l2tp_tunnel_find(sock_net(sk), tunnel_id);
+       tunnel = l2tp_tunnel_get(sock_net(sk), tunnel_id);
+       if (tunnel)
+               drop_tunnel = true;
 
        /* Special case: create tunnel context if session_id and
         * peer_session_id is 0. Otherwise look up tunnel using supplied
@@ -781,6 +784,8 @@ out_no_ppp:
 end:
        if (drop_refcnt)
                l2tp_session_dec_refcount(session);
+       if (drop_tunnel)
+               l2tp_tunnel_dec_refcount(tunnel);
        release_sock(sk);
 
        return error;
index a354f1939e49b83a5c04bcebd54952d33e8dae8d..fb15d3b97cb214078f1533f880350fe280b57c69 100644 (file)
@@ -2727,12 +2727,6 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
        if (!ieee80211_sdata_running(sdata))
                return -ENETDOWN;
 
-       if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
-               ret = drv_set_bitrate_mask(local, sdata, mask);
-               if (ret)
-                       return ret;
-       }
-
        /*
         * If active validate the setting and reject it if it doesn't leave
         * at least one basic rate usable, since we really have to be able
@@ -2748,6 +2742,12 @@ static int ieee80211_set_bitrate_mask(struct wiphy *wiphy,
                        return -EINVAL;
        }
 
+       if (ieee80211_hw_check(&local->hw, HAS_RATE_CONTROL)) {
+               ret = drv_set_bitrate_mask(local, sdata, mask);
+               if (ret)
+                       return ret;
+       }
+
        for (i = 0; i < NUM_NL80211_BANDS; i++) {
                struct ieee80211_supported_band *sband = wiphy->bands[i];
                int j;
index ae995c8480db9639e1070a6f4743f1e6d6213e81..938049395f9073169035ded5f506cb0c192c41f7 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/slab.h>
 #include <linux/export.h>
 #include <net/mac80211.h>
+#include <crypto/algapi.h>
 #include <asm/unaligned.h>
 #include "ieee80211_i.h"
 #include "driver-ops.h"
@@ -609,6 +610,39 @@ void ieee80211_key_free_unused(struct ieee80211_key *key)
        ieee80211_key_free_common(key);
 }
 
+static bool ieee80211_key_identical(struct ieee80211_sub_if_data *sdata,
+                                   struct ieee80211_key *old,
+                                   struct ieee80211_key *new)
+{
+       u8 tkip_old[WLAN_KEY_LEN_TKIP], tkip_new[WLAN_KEY_LEN_TKIP];
+       u8 *tk_old, *tk_new;
+
+       if (!old || new->conf.keylen != old->conf.keylen)
+               return false;
+
+       tk_old = old->conf.key;
+       tk_new = new->conf.key;
+
+       /*
+        * In station mode, don't compare the TX MIC key, as it's never used
+        * and offloaded rekeying may not care to send it to the host. This
+        * is the case in iwlwifi, for example.
+        */
+       if (sdata->vif.type == NL80211_IFTYPE_STATION &&
+           new->conf.cipher == WLAN_CIPHER_SUITE_TKIP &&
+           new->conf.keylen == WLAN_KEY_LEN_TKIP &&
+           !(new->conf.flags & IEEE80211_KEY_FLAG_PAIRWISE)) {
+               memcpy(tkip_old, tk_old, WLAN_KEY_LEN_TKIP);
+               memcpy(tkip_new, tk_new, WLAN_KEY_LEN_TKIP);
+               memset(tkip_old + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
+               memset(tkip_new + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY, 0, 8);
+               tk_old = tkip_old;
+               tk_new = tkip_new;
+       }
+
+       return !crypto_memneq(tk_old, tk_new, new->conf.keylen);
+}
+
 int ieee80211_key_link(struct ieee80211_key *key,
                       struct ieee80211_sub_if_data *sdata,
                       struct sta_info *sta)
@@ -634,8 +668,7 @@ int ieee80211_key_link(struct ieee80211_key *key,
         * Silently accept key re-installation without really installing the
         * new version of the key to avoid nonce reuse or replay issues.
         */
-       if (old_key && key->conf.keylen == old_key->conf.keylen &&
-           !memcmp(key->conf.key, old_key->conf.key, key->conf.keylen)) {
+       if (ieee80211_key_identical(sdata, old_key, key)) {
                ieee80211_key_free_unused(key);
                ret = 0;
                goto out;
index 3a6ad0f438dc6423d450c098bb55001cdb5e83a6..64f95624f21939c946e0bb256a40d825588e0fd2 100644 (file)
@@ -296,6 +296,6 @@ static void __exit psample_module_exit(void)
 module_init(psample_module_init);
 module_exit(psample_module_exit);
 
-MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>");
+MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>");
 MODULE_DESCRIPTION("netlink channel for packet sampling");
 MODULE_LICENSE("GPL v2");
index 6ab39dbcca0197339cb8c2e9ec5676a778c4d23e..8557a1cae04170496887815a0f41e7c1abd2d979 100644 (file)
@@ -661,13 +661,15 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
                        }
                }
 
-               rds_ib_set_wr_signal_state(ic, send, 0);
+               rds_ib_set_wr_signal_state(ic, send, false);
 
                /*
                 * Always signal the last one if we're stopping due to flow control.
                 */
-               if (ic->i_flowctl && flow_controlled && i == (work_alloc-1))
-                       send->s_wr.send_flags |= IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+               if (ic->i_flowctl && flow_controlled && i == (work_alloc - 1)) {
+                       rds_ib_set_wr_signal_state(ic, send, true);
+                       send->s_wr.send_flags |= IB_SEND_SOLICITED;
+               }
 
                if (send->s_wr.send_flags & IB_SEND_SIGNALED)
                        nr_sig++;
@@ -705,11 +707,8 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
        if (scat == &rm->data.op_sg[rm->data.op_count]) {
                prev->s_op = ic->i_data_op;
                prev->s_wr.send_flags |= IB_SEND_SOLICITED;
-               if (!(prev->s_wr.send_flags & IB_SEND_SIGNALED)) {
-                       ic->i_unsignaled_wrs = rds_ib_sysctl_max_unsig_wrs;
-                       prev->s_wr.send_flags |= IB_SEND_SIGNALED;
-                       nr_sig++;
-               }
+               if (!(prev->s_wr.send_flags & IB_SEND_SIGNALED))
+                       nr_sig += rds_ib_set_wr_signal_state(ic, prev, true);
                ic->i_data_op = NULL;
        }
 
@@ -792,6 +791,7 @@ int rds_ib_xmit_atomic(struct rds_connection *conn, struct rm_atomic_op *op)
                send->s_atomic_wr.compare_add_mask = op->op_m_fadd.nocarry_mask;
                send->s_atomic_wr.swap_mask = 0;
        }
+       send->s_wr.send_flags = 0;
        nr_sig = rds_ib_set_wr_signal_state(ic, send, op->op_notify);
        send->s_atomic_wr.wr.num_sge = 1;
        send->s_atomic_wr.wr.next = NULL;
index ec986ae528089081ecdf8528437bbd82b7e840e1..8b5abcd2f32faeaa2a283bcc8fb388201f7a86e2 100644 (file)
@@ -264,12 +264,13 @@ static int __init sample_init_module(void)
 
 static void __exit sample_cleanup_module(void)
 {
+       rcu_barrier();
        tcf_unregister_action(&act_sample_ops, &sample_net_ops);
 }
 
 module_init(sample_init_module);
 module_exit(sample_cleanup_module);
 
-MODULE_AUTHOR("Yotam Gigi <yotamg@mellanox.com>");
+MODULE_AUTHOR("Yotam Gigi <yotam.gi@gmail.com>");
 MODULE_DESCRIPTION("Packet sampling action");
 MODULE_LICENSE("GPL v2");
index 0b2219adf520b33a471dd3b8e2fdf9f46271c3f9..b2d31074548724a3b59defbcd827d6538ac9bea6 100644 (file)
@@ -77,6 +77,8 @@ out:
 }
 EXPORT_SYMBOL(register_tcf_proto_ops);
 
+static struct workqueue_struct *tc_filter_wq;
+
 int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
 {
        struct tcf_proto_ops *t;
@@ -86,6 +88,7 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
         * tcf_proto_ops's destroy() handler.
         */
        rcu_barrier();
+       flush_workqueue(tc_filter_wq);
 
        write_lock(&cls_mod_lock);
        list_for_each_entry(t, &tcf_proto_base, head) {
@@ -100,6 +103,12 @@ int unregister_tcf_proto_ops(struct tcf_proto_ops *ops)
 }
 EXPORT_SYMBOL(unregister_tcf_proto_ops);
 
+bool tcf_queue_work(struct work_struct *work)
+{
+       return queue_work(tc_filter_wq, work);
+}
+EXPORT_SYMBOL(tcf_queue_work);
+
 /* Select new prio value from the range, managed by kernel. */
 
 static inline u32 tcf_auto_prio(struct tcf_proto *tp)
@@ -266,6 +275,23 @@ err_chain_create:
 }
 EXPORT_SYMBOL(tcf_block_get);
 
+static void tcf_block_put_final(struct work_struct *work)
+{
+       struct tcf_block *block = container_of(work, struct tcf_block, work);
+       struct tcf_chain *chain, *tmp;
+
+       rtnl_lock();
+       /* Only chain 0 should be still here. */
+       list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
+               tcf_chain_put(chain);
+       rtnl_unlock();
+       kfree(block);
+}
+
+/* XXX: Standalone actions are not allowed to jump to any chain, and bound
+ * actions should be all removed after flushing. However, filters are now
+ * destroyed in tc filter workqueue with RTNL lock, they can not race here.
+ */
 void tcf_block_put(struct tcf_block *block)
 {
        struct tcf_chain *chain, *tmp;
@@ -273,32 +299,15 @@ void tcf_block_put(struct tcf_block *block)
        if (!block)
                return;
 
-       /* XXX: Standalone actions are not allowed to jump to any chain, and
-        * bound actions should be all removed after flushing. However,
-        * filters are destroyed in RCU callbacks, we have to hold the chains
-        * first, otherwise we would always race with RCU callbacks on this list
-        * without proper locking.
-        */
-
-       /* Wait for existing RCU callbacks to cool down. */
-       rcu_barrier();
-
-       /* Hold a refcnt for all chains, except 0, in case they are gone. */
-       list_for_each_entry(chain, &block->chain_list, list)
-               if (chain->index)
-                       tcf_chain_hold(chain);
-
-       /* No race on the list, because no chain could be destroyed. */
-       list_for_each_entry(chain, &block->chain_list, list)
+       list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
                tcf_chain_flush(chain);
 
-       /* Wait for RCU callbacks to release the reference count. */
+       INIT_WORK(&block->work, tcf_block_put_final);
+       /* Wait for RCU callbacks to release the reference count and make
+        * sure their works have been queued before this.
+        */
        rcu_barrier();
-
-       /* At this point, all the chains should have refcnt == 1. */
-       list_for_each_entry_safe(chain, tmp, &block->chain_list, list)
-               tcf_chain_put(chain);
-       kfree(block);
+       tcf_queue_work(&block->work);
 }
 EXPORT_SYMBOL(tcf_block_put);
 
@@ -879,6 +888,7 @@ void tcf_exts_destroy(struct tcf_exts *exts)
 #ifdef CONFIG_NET_CLS_ACT
        LIST_HEAD(actions);
 
+       ASSERT_RTNL();
        tcf_exts_to_list(exts, &actions);
        tcf_action_destroy(&actions, TCA_ACT_UNBIND);
        kfree(exts->actions);
@@ -1030,6 +1040,10 @@ EXPORT_SYMBOL(tcf_exts_get_dev);
 
 static int __init tc_filter_init(void)
 {
+       tc_filter_wq = alloc_ordered_workqueue("tc_filter_workqueue", 0);
+       if (!tc_filter_wq)
+               return -ENOMEM;
+
        rtnl_register(PF_UNSPEC, RTM_NEWTFILTER, tc_ctl_tfilter, NULL, 0);
        rtnl_register(PF_UNSPEC, RTM_DELTFILTER, tc_ctl_tfilter, NULL, 0);
        rtnl_register(PF_UNSPEC, RTM_GETTFILTER, tc_ctl_tfilter,
index d89ebafd22390238b868425cb5a8bbd8dec2c268..f177649a24192a144f261d4e4a40b52ce7cdc91a 100644 (file)
@@ -34,7 +34,10 @@ struct basic_filter {
        struct tcf_result       res;
        struct tcf_proto        *tp;
        struct list_head        link;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
 };
 
 static int basic_classify(struct sk_buff *skb, const struct tcf_proto *tp,
@@ -82,15 +85,26 @@ static int basic_init(struct tcf_proto *tp)
        return 0;
 }
 
-static void basic_delete_filter(struct rcu_head *head)
+static void basic_delete_filter_work(struct work_struct *work)
 {
-       struct basic_filter *f = container_of(head, struct basic_filter, rcu);
+       struct basic_filter *f = container_of(work, struct basic_filter, work);
 
+       rtnl_lock();
        tcf_exts_destroy(&f->exts);
        tcf_em_tree_destroy(&f->ematches);
+       rtnl_unlock();
+
        kfree(f);
 }
 
+static void basic_delete_filter(struct rcu_head *head)
+{
+       struct basic_filter *f = container_of(head, struct basic_filter, rcu);
+
+       INIT_WORK(&f->work, basic_delete_filter_work);
+       tcf_queue_work(&f->work);
+}
+
 static void basic_destroy(struct tcf_proto *tp)
 {
        struct basic_head *head = rtnl_dereference(tp->root);
index 520c5027646aea5146f22d7898acfbc7dee3385a..037a3ae86829946135e2154bd83ddc722b61af17 100644 (file)
@@ -49,7 +49,10 @@ struct cls_bpf_prog {
        struct sock_filter *bpf_ops;
        const char *bpf_name;
        struct tcf_proto *tp;
-       struct rcu_head rcu;
+       union {
+               struct work_struct work;
+               struct rcu_head rcu;
+       };
 };
 
 static const struct nla_policy bpf_policy[TCA_BPF_MAX + 1] = {
@@ -257,9 +260,21 @@ static void __cls_bpf_delete_prog(struct cls_bpf_prog *prog)
        kfree(prog);
 }
 
+static void cls_bpf_delete_prog_work(struct work_struct *work)
+{
+       struct cls_bpf_prog *prog = container_of(work, struct cls_bpf_prog, work);
+
+       rtnl_lock();
+       __cls_bpf_delete_prog(prog);
+       rtnl_unlock();
+}
+
 static void cls_bpf_delete_prog_rcu(struct rcu_head *rcu)
 {
-       __cls_bpf_delete_prog(container_of(rcu, struct cls_bpf_prog, rcu));
+       struct cls_bpf_prog *prog = container_of(rcu, struct cls_bpf_prog, rcu);
+
+       INIT_WORK(&prog->work, cls_bpf_delete_prog_work);
+       tcf_queue_work(&prog->work);
 }
 
 static void __cls_bpf_delete(struct tcf_proto *tp, struct cls_bpf_prog *prog)
index d48452f8797528dd7ada96dae61a82b3905aa0de..a97e069bee89f0010daaa33c610cc1aea7b97811 100644 (file)
@@ -23,7 +23,10 @@ struct cls_cgroup_head {
        struct tcf_exts         exts;
        struct tcf_ematch_tree  ematches;
        struct tcf_proto        *tp;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
 };
 
 static int cls_cgroup_classify(struct sk_buff *skb, const struct tcf_proto *tp,
@@ -57,15 +60,26 @@ static const struct nla_policy cgroup_policy[TCA_CGROUP_MAX + 1] = {
        [TCA_CGROUP_EMATCHES]   = { .type = NLA_NESTED },
 };
 
+static void cls_cgroup_destroy_work(struct work_struct *work)
+{
+       struct cls_cgroup_head *head = container_of(work,
+                                                   struct cls_cgroup_head,
+                                                   work);
+       rtnl_lock();
+       tcf_exts_destroy(&head->exts);
+       tcf_em_tree_destroy(&head->ematches);
+       kfree(head);
+       rtnl_unlock();
+}
+
 static void cls_cgroup_destroy_rcu(struct rcu_head *root)
 {
        struct cls_cgroup_head *head = container_of(root,
                                                    struct cls_cgroup_head,
                                                    rcu);
 
-       tcf_exts_destroy(&head->exts);
-       tcf_em_tree_destroy(&head->ematches);
-       kfree(head);
+       INIT_WORK(&head->work, cls_cgroup_destroy_work);
+       tcf_queue_work(&head->work);
 }
 
 static int cls_cgroup_change(struct net *net, struct sk_buff *in_skb,
index 2a3a60ec5b8617c48e58d8a9339cda69be68442f..67f3a2af6aab1aadb5b492265d8469a37a1e8fd5 100644 (file)
@@ -57,7 +57,10 @@ struct flow_filter {
        u32                     divisor;
        u32                     baseclass;
        u32                     hashrnd;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
 };
 
 static inline u32 addr_fold(void *addr)
@@ -369,14 +372,24 @@ static const struct nla_policy flow_policy[TCA_FLOW_MAX + 1] = {
        [TCA_FLOW_PERTURB]      = { .type = NLA_U32 },
 };
 
-static void flow_destroy_filter(struct rcu_head *head)
+static void flow_destroy_filter_work(struct work_struct *work)
 {
-       struct flow_filter *f = container_of(head, struct flow_filter, rcu);
+       struct flow_filter *f = container_of(work, struct flow_filter, work);
 
+       rtnl_lock();
        del_timer_sync(&f->perturb_timer);
        tcf_exts_destroy(&f->exts);
        tcf_em_tree_destroy(&f->ematches);
        kfree(f);
+       rtnl_unlock();
+}
+
+static void flow_destroy_filter(struct rcu_head *head)
+{
+       struct flow_filter *f = container_of(head, struct flow_filter, rcu);
+
+       INIT_WORK(&f->work, flow_destroy_filter_work);
+       tcf_queue_work(&f->work);
 }
 
 static int flow_change(struct net *net, struct sk_buff *in_skb,
index b480d7c792ba03e26e2eece4998f1b82e9c75b05..5b5722c8b32c1a276f7441fb67baa0d16ba24ff2 100644 (file)
@@ -87,7 +87,10 @@ struct cls_fl_filter {
        struct list_head list;
        u32 handle;
        u32 flags;
-       struct rcu_head rcu;
+       union {
+               struct work_struct work;
+               struct rcu_head rcu;
+       };
        struct net_device *hw_dev;
 };
 
@@ -215,12 +218,22 @@ static int fl_init(struct tcf_proto *tp)
        return 0;
 }
 
-static void fl_destroy_filter(struct rcu_head *head)
+static void fl_destroy_filter_work(struct work_struct *work)
 {
-       struct cls_fl_filter *f = container_of(head, struct cls_fl_filter, rcu);
+       struct cls_fl_filter *f = container_of(work, struct cls_fl_filter, work);
 
+       rtnl_lock();
        tcf_exts_destroy(&f->exts);
        kfree(f);
+       rtnl_unlock();
+}
+
+static void fl_destroy_filter(struct rcu_head *head)
+{
+       struct cls_fl_filter *f = container_of(head, struct cls_fl_filter, rcu);
+
+       INIT_WORK(&f->work, fl_destroy_filter_work);
+       tcf_queue_work(&f->work);
 }
 
 static void fl_hw_destroy_filter(struct tcf_proto *tp, struct cls_fl_filter *f)
index 941245ad07fd4b8bb4fd97cd84fac8791c571276..99183b8621ecb0543af91020167d13c193cad214 100644 (file)
@@ -46,7 +46,10 @@ struct fw_filter {
 #endif /* CONFIG_NET_CLS_IND */
        struct tcf_exts         exts;
        struct tcf_proto        *tp;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
 };
 
 static u32 fw_hash(u32 handle)
@@ -119,12 +122,22 @@ static int fw_init(struct tcf_proto *tp)
        return 0;
 }
 
-static void fw_delete_filter(struct rcu_head *head)
+static void fw_delete_filter_work(struct work_struct *work)
 {
-       struct fw_filter *f = container_of(head, struct fw_filter, rcu);
+       struct fw_filter *f = container_of(work, struct fw_filter, work);
 
+       rtnl_lock();
        tcf_exts_destroy(&f->exts);
        kfree(f);
+       rtnl_unlock();
+}
+
+static void fw_delete_filter(struct rcu_head *head)
+{
+       struct fw_filter *f = container_of(head, struct fw_filter, rcu);
+
+       INIT_WORK(&f->work, fw_delete_filter_work);
+       tcf_queue_work(&f->work);
 }
 
 static void fw_destroy(struct tcf_proto *tp)
index eeac606c95abe99ca3f24ab462589adbe7c86388..c33f711b90198ab8b77bd314c289d09cbfe2d170 100644 (file)
@@ -21,7 +21,10 @@ struct cls_mall_head {
        struct tcf_result res;
        u32 handle;
        u32 flags;
-       struct rcu_head rcu;
+       union {
+               struct work_struct work;
+               struct rcu_head rcu;
+       };
 };
 
 static int mall_classify(struct sk_buff *skb, const struct tcf_proto *tp,
@@ -41,13 +44,23 @@ static int mall_init(struct tcf_proto *tp)
        return 0;
 }
 
+static void mall_destroy_work(struct work_struct *work)
+{
+       struct cls_mall_head *head = container_of(work, struct cls_mall_head,
+                                                 work);
+       rtnl_lock();
+       tcf_exts_destroy(&head->exts);
+       kfree(head);
+       rtnl_unlock();
+}
+
 static void mall_destroy_rcu(struct rcu_head *rcu)
 {
        struct cls_mall_head *head = container_of(rcu, struct cls_mall_head,
                                                  rcu);
 
-       tcf_exts_destroy(&head->exts);
-       kfree(head);
+       INIT_WORK(&head->work, mall_destroy_work);
+       tcf_queue_work(&head->work);
 }
 
 static int mall_replace_hw_filter(struct tcf_proto *tp,
index 9ddde65915d22615aa93036f01ae0368783c94f6..4b14ccd8b8f271aabecb97427fa3fa18f7484747 100644 (file)
@@ -57,7 +57,10 @@ struct route4_filter {
        u32                     handle;
        struct route4_bucket    *bkt;
        struct tcf_proto        *tp;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
 };
 
 #define ROUTE4_FAILURE ((struct route4_filter *)(-1L))
@@ -254,12 +257,22 @@ static int route4_init(struct tcf_proto *tp)
        return 0;
 }
 
-static void route4_delete_filter(struct rcu_head *head)
+static void route4_delete_filter_work(struct work_struct *work)
 {
-       struct route4_filter *f = container_of(head, struct route4_filter, rcu);
+       struct route4_filter *f = container_of(work, struct route4_filter, work);
 
+       rtnl_lock();
        tcf_exts_destroy(&f->exts);
        kfree(f);
+       rtnl_unlock();
+}
+
+static void route4_delete_filter(struct rcu_head *head)
+{
+       struct route4_filter *f = container_of(head, struct route4_filter, rcu);
+
+       INIT_WORK(&f->work, route4_delete_filter_work);
+       tcf_queue_work(&f->work);
 }
 
 static void route4_destroy(struct tcf_proto *tp)
index b1f6ed48bc729b9238d1a3502c147ca856b3a996..bdbc541787f87d6bc0592122acef87a80b0b8d03 100644 (file)
@@ -97,7 +97,10 @@ struct rsvp_filter {
 
        u32                             handle;
        struct rsvp_session             *sess;
-       struct rcu_head                 rcu;
+       union {
+               struct work_struct              work;
+               struct rcu_head                 rcu;
+       };
 };
 
 static inline unsigned int hash_dst(__be32 *dst, u8 protocol, u8 tunnelid)
@@ -282,12 +285,22 @@ static int rsvp_init(struct tcf_proto *tp)
        return -ENOBUFS;
 }
 
-static void rsvp_delete_filter_rcu(struct rcu_head *head)
+static void rsvp_delete_filter_work(struct work_struct *work)
 {
-       struct rsvp_filter *f = container_of(head, struct rsvp_filter, rcu);
+       struct rsvp_filter *f = container_of(work, struct rsvp_filter, work);
 
+       rtnl_lock();
        tcf_exts_destroy(&f->exts);
        kfree(f);
+       rtnl_unlock();
+}
+
+static void rsvp_delete_filter_rcu(struct rcu_head *head)
+{
+       struct rsvp_filter *f = container_of(head, struct rsvp_filter, rcu);
+
+       INIT_WORK(&f->work, rsvp_delete_filter_work);
+       tcf_queue_work(&f->work);
 }
 
 static void rsvp_delete_filter(struct tcf_proto *tp, struct rsvp_filter *f)
index 14a7e08b2fa9e2f8a3551f6dbc1fb38f1e8df579..beaa95e09c25c26ba94155f03375d27156e9cbc4 100644 (file)
 struct tcindex_filter_result {
        struct tcf_exts         exts;
        struct tcf_result       res;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
 };
 
 struct tcindex_filter {
        u16 key;
        struct tcindex_filter_result result;
        struct tcindex_filter __rcu *next;
-       struct rcu_head rcu;
+       union {
+               struct work_struct work;
+               struct rcu_head rcu;
+       };
 };
 
 
@@ -133,12 +139,34 @@ static int tcindex_init(struct tcf_proto *tp)
        return 0;
 }
 
+static void tcindex_destroy_rexts_work(struct work_struct *work)
+{
+       struct tcindex_filter_result *r;
+
+       r = container_of(work, struct tcindex_filter_result, work);
+       rtnl_lock();
+       tcf_exts_destroy(&r->exts);
+       rtnl_unlock();
+}
+
 static void tcindex_destroy_rexts(struct rcu_head *head)
 {
        struct tcindex_filter_result *r;
 
        r = container_of(head, struct tcindex_filter_result, rcu);
-       tcf_exts_destroy(&r->exts);
+       INIT_WORK(&r->work, tcindex_destroy_rexts_work);
+       tcf_queue_work(&r->work);
+}
+
+static void tcindex_destroy_fexts_work(struct work_struct *work)
+{
+       struct tcindex_filter *f = container_of(work, struct tcindex_filter,
+                                               work);
+
+       rtnl_lock();
+       tcf_exts_destroy(&f->result.exts);
+       kfree(f);
+       rtnl_unlock();
 }
 
 static void tcindex_destroy_fexts(struct rcu_head *head)
@@ -146,8 +174,8 @@ static void tcindex_destroy_fexts(struct rcu_head *head)
        struct tcindex_filter *f = container_of(head, struct tcindex_filter,
                                                rcu);
 
-       tcf_exts_destroy(&f->result.exts);
-       kfree(f);
+       INIT_WORK(&f->work, tcindex_destroy_fexts_work);
+       tcf_queue_work(&f->work);
 }
 
 static int tcindex_delete(struct tcf_proto *tp, void *arg, bool *last)
index 10b8d851fc6be96c761bea127776b84d21b4fc05..dadd1b3444970d1be4936e4f1a6cf8fd9a6d14a6 100644 (file)
@@ -68,7 +68,10 @@ struct tc_u_knode {
        u32 __percpu            *pcpu_success;
 #endif
        struct tcf_proto        *tp;
-       struct rcu_head         rcu;
+       union {
+               struct work_struct      work;
+               struct rcu_head         rcu;
+       };
        /* The 'sel' field MUST be the last field in structure to allow for
         * tc_u32_keys allocated at end of structure.
         */
@@ -418,11 +421,21 @@ static int u32_destroy_key(struct tcf_proto *tp, struct tc_u_knode *n,
  * this the u32_delete_key_rcu variant does not free the percpu
  * statistics.
  */
+static void u32_delete_key_work(struct work_struct *work)
+{
+       struct tc_u_knode *key = container_of(work, struct tc_u_knode, work);
+
+       rtnl_lock();
+       u32_destroy_key(key->tp, key, false);
+       rtnl_unlock();
+}
+
 static void u32_delete_key_rcu(struct rcu_head *rcu)
 {
        struct tc_u_knode *key = container_of(rcu, struct tc_u_knode, rcu);
 
-       u32_destroy_key(key->tp, key, false);
+       INIT_WORK(&key->work, u32_delete_key_work);
+       tcf_queue_work(&key->work);
 }
 
 /* u32_delete_key_freepf_rcu is the rcu callback variant
@@ -432,11 +445,21 @@ static void u32_delete_key_rcu(struct rcu_head *rcu)
  * for the variant that should be used with keys return from
  * u32_init_knode()
  */
+static void u32_delete_key_freepf_work(struct work_struct *work)
+{
+       struct tc_u_knode *key = container_of(work, struct tc_u_knode, work);
+
+       rtnl_lock();
+       u32_destroy_key(key->tp, key, true);
+       rtnl_unlock();
+}
+
 static void u32_delete_key_freepf_rcu(struct rcu_head *rcu)
 {
        struct tc_u_knode *key = container_of(rcu, struct tc_u_knode, rcu);
 
-       u32_destroy_key(key->tp, key, true);
+       INIT_WORK(&key->work, u32_delete_key_freepf_work);
+       tcf_queue_work(&key->work);
 }
 
 static int u32_delete_key(struct tcf_proto *tp, struct tc_u_knode *key)
index c6deb74e3d2f4a007554b9cf78e4ddf7b7b84535..22bc6fc4831116d75027a3871e7854e07b823d71 100644 (file)
@@ -301,6 +301,8 @@ struct Qdisc *qdisc_lookup(struct net_device *dev, u32 handle)
 {
        struct Qdisc *q;
 
+       if (!handle)
+               return NULL;
        q = qdisc_match_from_root(dev->qdisc, handle);
        if (q)
                goto out;
index 34f10e75f3b951a6fce87092a9af58dddb1f891b..621b5ca3fd1c17c3d7ef7bb1c7677ab98cebbe77 100644 (file)
@@ -794,7 +794,7 @@ hit:
 struct sctp_hash_cmp_arg {
        const union sctp_addr   *paddr;
        const struct net        *net;
-       u16                     lport;
+       __be16                  lport;
 };
 
 static inline int sctp_hash_cmp(struct rhashtable_compare_arg *arg,
@@ -820,37 +820,37 @@ out:
        return err;
 }
 
-static inline u32 sctp_hash_obj(const void *data, u32 len, u32 seed)
+static inline __u32 sctp_hash_obj(const void *data, u32 len, u32 seed)
 {
        const struct sctp_transport *t = data;
        const union sctp_addr *paddr = &t->ipaddr;
        const struct net *net = sock_net(t->asoc->base.sk);
-       u16 lport = htons(t->asoc->base.bind_addr.port);
-       u32 addr;
+       __be16 lport = htons(t->asoc->base.bind_addr.port);
+       __u32 addr;
 
        if (paddr->sa.sa_family == AF_INET6)
                addr = jhash(&paddr->v6.sin6_addr, 16, seed);
        else
-               addr = paddr->v4.sin_addr.s_addr;
+               addr = (__force __u32)paddr->v4.sin_addr.s_addr;
 
-       return  jhash_3words(addr, ((__u32)paddr->v4.sin_port) << 16 |
+       return  jhash_3words(addr, ((__force __u32)paddr->v4.sin_port) << 16 |
                             (__force __u32)lport, net_hash_mix(net), seed);
 }
 
-static inline u32 sctp_hash_key(const void *data, u32 len, u32 seed)
+static inline __u32 sctp_hash_key(const void *data, u32 len, u32 seed)
 {
        const struct sctp_hash_cmp_arg *x = data;
        const union sctp_addr *paddr = x->paddr;
        const struct net *net = x->net;
-       u16 lport = x->lport;
-       u32 addr;
+       __be16 lport = x->lport;
+       __u32 addr;
 
        if (paddr->sa.sa_family == AF_INET6)
                addr = jhash(&paddr->v6.sin6_addr, 16, seed);
        else
-               addr = paddr->v4.sin_addr.s_addr;
+               addr = (__force __u32)paddr->v4.sin_addr.s_addr;
 
-       return  jhash_3words(addr, ((__u32)paddr->v4.sin_port) << 16 |
+       return  jhash_3words(addr, ((__force __u32)paddr->v4.sin_port) << 16 |
                             (__force __u32)lport, net_hash_mix(net), seed);
 }
 
index 51c4887695909d171285b98ce1be779a3adedbab..a6dfa86c02016e3ff81f10f729a56e6673affc68 100644 (file)
@@ -738,7 +738,7 @@ static int sctp_v6_skb_iif(const struct sk_buff *skb)
 /* Was this packet marked by Explicit Congestion Notification? */
 static int sctp_v6_is_ce(const struct sk_buff *skb)
 {
-       return *((__u32 *)(ipv6_hdr(skb))) & htonl(1 << 20);
+       return *((__u32 *)(ipv6_hdr(skb))) & (__force __u32)htonl(1 << 20);
 }
 
 /* Dump the v6 addr to the seq file. */
@@ -882,8 +882,10 @@ static int sctp_inet6_bind_verify(struct sctp_sock *opt, union sctp_addr *addr)
                        net = sock_net(&opt->inet.sk);
                        rcu_read_lock();
                        dev = dev_get_by_index_rcu(net, addr->v6.sin6_scope_id);
-                       if (!dev ||
-                           !ipv6_chk_addr(net, &addr->v6.sin6_addr, dev, 0)) {
+                       if (!dev || !(opt->inet.freebind ||
+                                     net->ipv6.sysctl.ip_nonlocal_bind ||
+                                     ipv6_chk_addr(net, &addr->v6.sin6_addr,
+                                                   dev, 0))) {
                                rcu_read_unlock();
                                return 0;
                        }
index ca8f196b6c6c106386a65c75dccd7bc3451798ff..514465b03829b18c18ae3e890e0899138035bd7a 100644 (file)
@@ -2854,7 +2854,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
                addr_param_len = af->to_addr_param(addr, &addr_param);
                param.param_hdr.type = flags;
                param.param_hdr.length = htons(paramlen + addr_param_len);
-               param.crr_id = i;
+               param.crr_id = htonl(i);
 
                sctp_addto_chunk(retval, paramlen, &param);
                sctp_addto_chunk(retval, addr_param_len, &addr_param);
@@ -2867,7 +2867,7 @@ struct sctp_chunk *sctp_make_asconf_update_ip(struct sctp_association *asoc,
                addr_param_len = af->to_addr_param(addr, &addr_param);
                param.param_hdr.type = SCTP_PARAM_DEL_IP;
                param.param_hdr.length = htons(paramlen + addr_param_len);
-               param.crr_id = i;
+               param.crr_id = htonl(i);
 
                sctp_addto_chunk(retval, paramlen, &param);
                sctp_addto_chunk(retval, addr_param_len, &addr_param);
@@ -3591,7 +3591,7 @@ static struct sctp_chunk *sctp_make_reconf(const struct sctp_association *asoc,
  */
 struct sctp_chunk *sctp_make_strreset_req(
                                        const struct sctp_association *asoc,
-                                       __u16 stream_num, __u16 *stream_list,
+                                       __u16 stream_num, __be16 *stream_list,
                                        bool out, bool in)
 {
        struct sctp_strreset_outreq outreq;
@@ -3788,7 +3788,8 @@ bool sctp_verify_reconf(const struct sctp_association *asoc,
 {
        struct sctp_reconf_chunk *hdr;
        union sctp_params param;
-       __u16 last = 0, cnt = 0;
+       __be16 last = 0;
+       __u16 cnt = 0;
 
        hdr = (struct sctp_reconf_chunk *)chunk->chunk_hdr;
        sctp_walk_params(param, hdr, params) {
index e6a2974e020e1a4232d94e6c2933eebff5f8acb4..e2d9a4b49c9c98061a1c5b358b65ce5285f68de8 100644 (file)
@@ -1607,12 +1607,12 @@ static int sctp_cmd_interpreter(enum sctp_event event_type,
                        break;
 
                case SCTP_CMD_INIT_FAILED:
-                       sctp_cmd_init_failed(commands, asoc, cmd->obj.err);
+                       sctp_cmd_init_failed(commands, asoc, cmd->obj.u32);
                        break;
 
                case SCTP_CMD_ASSOC_FAILED:
                        sctp_cmd_assoc_failed(commands, asoc, event_type,
-                                             subtype, chunk, cmd->obj.err);
+                                             subtype, chunk, cmd->obj.u32);
                        break;
 
                case SCTP_CMD_INIT_COUNTER_INC:
@@ -1680,8 +1680,8 @@ static int sctp_cmd_interpreter(enum sctp_event event_type,
                case SCTP_CMD_PROCESS_CTSN:
                        /* Dummy up a SACK for processing. */
                        sackh.cum_tsn_ack = cmd->obj.be32;
-                       sackh.a_rwnd = asoc->peer.rwnd +
-                                       asoc->outqueue.outstanding_bytes;
+                       sackh.a_rwnd = htonl(asoc->peer.rwnd +
+                                            asoc->outqueue.outstanding_bytes);
                        sackh.num_gap_ack_blocks = 0;
                        sackh.num_dup_tsns = 0;
                        chunk->subh.sack_hdr = &sackh;
index 17841ab30798ecb2d7269296dcda3c62d434d622..6f45d1713452df982a985e1e882c964259ad9e20 100644 (file)
@@ -170,6 +170,36 @@ static inline void sctp_set_owner_w(struct sctp_chunk *chunk)
        sk_mem_charge(sk, chunk->skb->truesize);
 }
 
+static void sctp_clear_owner_w(struct sctp_chunk *chunk)
+{
+       skb_orphan(chunk->skb);
+}
+
+static void sctp_for_each_tx_datachunk(struct sctp_association *asoc,
+                                      void (*cb)(struct sctp_chunk *))
+
+{
+       struct sctp_outq *q = &asoc->outqueue;
+       struct sctp_transport *t;
+       struct sctp_chunk *chunk;
+
+       list_for_each_entry(t, &asoc->peer.transport_addr_list, transports)
+               list_for_each_entry(chunk, &t->transmitted, transmitted_list)
+                       cb(chunk);
+
+       list_for_each_entry(chunk, &q->retransmit, list)
+               cb(chunk);
+
+       list_for_each_entry(chunk, &q->sacked, list)
+               cb(chunk);
+
+       list_for_each_entry(chunk, &q->abandoned, list)
+               cb(chunk);
+
+       list_for_each_entry(chunk, &q->out_chunk_list, list)
+               cb(chunk);
+}
+
 /* Verify that this is a valid address. */
 static inline int sctp_verify_addr(struct sock *sk, union sctp_addr *addr,
                                   int len)
@@ -8212,7 +8242,9 @@ static void sctp_sock_migrate(struct sock *oldsk, struct sock *newsk,
         * paths won't try to lock it and then oldsk.
         */
        lock_sock_nested(newsk, SINGLE_DEPTH_NESTING);
+       sctp_for_each_tx_datachunk(assoc, sctp_clear_owner_w);
        sctp_assoc_migrate(assoc, newsk);
+       sctp_for_each_tx_datachunk(assoc, sctp_set_owner_w);
 
        /* If the association on the newsk is already closed before accept()
         * is called, set RCV_SHUTDOWN flag.
index 63ea1550371493ec8863627c7a43f46a22f4a4c9..fa8371ff05c43f31a7a0c5947161e08508671bcc 100644 (file)
@@ -118,6 +118,7 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
        __u16 i, str_nums, *str_list;
        struct sctp_chunk *chunk;
        int retval = -EINVAL;
+       __be16 *nstr_list;
        bool out, in;
 
        if (!asoc->peer.reconf_capable ||
@@ -148,13 +149,18 @@ int sctp_send_reset_streams(struct sctp_association *asoc,
                        if (str_list[i] >= stream->incnt)
                                goto out;
 
+       nstr_list = kcalloc(str_nums, sizeof(__be16), GFP_KERNEL);
+       if (!nstr_list) {
+               retval = -ENOMEM;
+               goto out;
+       }
+
        for (i = 0; i < str_nums; i++)
-               str_list[i] = htons(str_list[i]);
+               nstr_list[i] = htons(str_list[i]);
 
-       chunk = sctp_make_strreset_req(asoc, str_nums, str_list, out, in);
+       chunk = sctp_make_strreset_req(asoc, str_nums, nstr_list, out, in);
 
-       for (i = 0; i < str_nums; i++)
-               str_list[i] = ntohs(str_list[i]);
+       kfree(nstr_list);
 
        if (!chunk) {
                retval = -ENOMEM;
@@ -305,7 +311,7 @@ out:
 }
 
 static struct sctp_paramhdr *sctp_chunk_lookup_strreset_param(
-                       struct sctp_association *asoc, __u32 resp_seq,
+                       struct sctp_association *asoc, __be32 resp_seq,
                        __be16 type)
 {
        struct sctp_chunk *chunk = asoc->strreset_chunk;
@@ -345,8 +351,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
 {
        struct sctp_strreset_outreq *outreq = param.v;
        struct sctp_stream *stream = &asoc->stream;
-       __u16 i, nums, flags = 0, *str_p = NULL;
        __u32 result = SCTP_STRRESET_DENIED;
+       __u16 i, nums, flags = 0;
+       __be16 *str_p = NULL;
        __u32 request_seq;
 
        request_seq = ntohl(outreq->request_seq);
@@ -439,8 +446,9 @@ struct sctp_chunk *sctp_process_strreset_inreq(
        struct sctp_stream *stream = &asoc->stream;
        __u32 result = SCTP_STRRESET_DENIED;
        struct sctp_chunk *chunk = NULL;
-       __u16 i, nums, *str_p;
        __u32 request_seq;
+       __u16 i, nums;
+       __be16 *str_p;
 
        request_seq = ntohl(inreq->request_seq);
        if (TSN_lt(asoc->strreset_inseq, request_seq) ||
@@ -769,7 +777,7 @@ struct sctp_chunk *sctp_process_strreset_resp(
 
        if (req->type == SCTP_PARAM_RESET_OUT_REQUEST) {
                struct sctp_strreset_outreq *outreq;
-               __u16 *str_p;
+               __be16 *str_p;
 
                outreq = (struct sctp_strreset_outreq *)req;
                str_p = outreq->list_of_streams;
@@ -794,7 +802,7 @@ struct sctp_chunk *sctp_process_strreset_resp(
                        nums, str_p, GFP_ATOMIC);
        } else if (req->type == SCTP_PARAM_RESET_IN_REQUEST) {
                struct sctp_strreset_inreq *inreq;
-               __u16 *str_p;
+               __be16 *str_p;
 
                /* if the result is performed, it's impossible for inreq */
                if (result == SCTP_STRRESET_PERFORMED)
index 67abc0194f301239fcbf0bd6a1136aeec585e660..5447228bf1a014ad6c95b80355bb1c3827800db7 100644 (file)
@@ -847,7 +847,7 @@ struct sctp_ulpevent *sctp_ulpevent_make_sender_dry_event(
 
 struct sctp_ulpevent *sctp_ulpevent_make_stream_reset_event(
        const struct sctp_association *asoc, __u16 flags, __u16 stream_num,
-       __u16 *stream_list, gfp_t gfp)
+       __be16 *stream_list, gfp_t gfp)
 {
        struct sctp_stream_reset_event *sreset;
        struct sctp_ulpevent *event;
index d4ea46a5f233b42d56d2884bf1532ca7d9374a94..c5fda15ba3193f811151043ac3675a2ebfb15c38 100644 (file)
@@ -49,7 +49,7 @@ static void strp_abort_strp(struct strparser *strp, int err)
 {
        /* Unrecoverable error in receive */
 
-       del_timer(&strp->msg_timer);
+       cancel_delayed_work(&strp->msg_timer_work);
 
        if (strp->stopped)
                return;
@@ -68,7 +68,7 @@ static void strp_abort_strp(struct strparser *strp, int err)
 static void strp_start_timer(struct strparser *strp, long timeo)
 {
        if (timeo)
-               mod_timer(&strp->msg_timer, timeo);
+               mod_delayed_work(strp_wq, &strp->msg_timer_work, timeo);
 }
 
 /* Lower lock held */
@@ -319,7 +319,7 @@ static int __strp_recv(read_descriptor_t *desc, struct sk_buff *orig_skb,
                eaten += (cand_len - extra);
 
                /* Hurray, we have a new message! */
-               del_timer(&strp->msg_timer);
+               cancel_delayed_work(&strp->msg_timer_work);
                strp->skb_head = NULL;
                STRP_STATS_INCR(strp->stats.msgs);
 
@@ -450,9 +450,10 @@ static void strp_work(struct work_struct *w)
        do_strp_work(container_of(w, struct strparser, work));
 }
 
-static void strp_msg_timeout(unsigned long arg)
+static void strp_msg_timeout(struct work_struct *w)
 {
-       struct strparser *strp = (struct strparser *)arg;
+       struct strparser *strp = container_of(w, struct strparser,
+                                             msg_timer_work.work);
 
        /* Message assembly timed out */
        STRP_STATS_INCR(strp->stats.msg_timeouts);
@@ -505,9 +506,7 @@ int strp_init(struct strparser *strp, struct sock *sk,
        strp->cb.read_sock_done = cb->read_sock_done ? : default_read_sock_done;
        strp->cb.abort_parser = cb->abort_parser ? : strp_abort_strp;
 
-       setup_timer(&strp->msg_timer, strp_msg_timeout,
-                   (unsigned long)strp);
-
+       INIT_DELAYED_WORK(&strp->msg_timer_work, strp_msg_timeout);
        INIT_WORK(&strp->work, strp_work);
 
        return 0;
@@ -532,7 +531,7 @@ void strp_done(struct strparser *strp)
 {
        WARN_ON(!strp->stopped);
 
-       del_timer_sync(&strp->msg_timer);
+       cancel_delayed_work_sync(&strp->msg_timer_work);
        cancel_work_sync(&strp->work);
 
        if (strp->skb_head) {
index e741ec2b4d8e6ea5d08a8e942e3021e5a20e4c6a..898485e3ece4e82a93d7759af2d77fd509a8676d 100644 (file)
@@ -1333,7 +1333,7 @@ void xprt_release(struct rpc_task *task)
                rpc_count_iostats(task, task->tk_client->cl_metrics);
        spin_lock(&xprt->recv_lock);
        if (!list_empty(&req->rq_list)) {
-               list_del(&req->rq_list);
+               list_del_init(&req->rq_list);
                xprt_wait_on_pinned_rqst(req);
        }
        spin_unlock(&xprt->recv_lock);
@@ -1445,6 +1445,23 @@ out:
        return xprt;
 }
 
+static void xprt_destroy_cb(struct work_struct *work)
+{
+       struct rpc_xprt *xprt =
+               container_of(work, struct rpc_xprt, task_cleanup);
+
+       rpc_xprt_debugfs_unregister(xprt);
+       rpc_destroy_wait_queue(&xprt->binding);
+       rpc_destroy_wait_queue(&xprt->pending);
+       rpc_destroy_wait_queue(&xprt->sending);
+       rpc_destroy_wait_queue(&xprt->backlog);
+       kfree(xprt->servername);
+       /*
+        * Tear down transport state and free the rpc_xprt
+        */
+       xprt->ops->destroy(xprt);
+}
+
 /**
  * xprt_destroy - destroy an RPC transport, killing off all requests.
  * @xprt: transport to destroy
@@ -1454,22 +1471,19 @@ static void xprt_destroy(struct rpc_xprt *xprt)
 {
        dprintk("RPC:       destroying transport %p\n", xprt);
 
-       /* Exclude transport connect/disconnect handlers */
+       /*
+        * Exclude transport connect/disconnect handlers and autoclose
+        */
        wait_on_bit_lock(&xprt->state, XPRT_LOCKED, TASK_UNINTERRUPTIBLE);
 
        del_timer_sync(&xprt->timer);
 
-       rpc_xprt_debugfs_unregister(xprt);
-       rpc_destroy_wait_queue(&xprt->binding);
-       rpc_destroy_wait_queue(&xprt->pending);
-       rpc_destroy_wait_queue(&xprt->sending);
-       rpc_destroy_wait_queue(&xprt->backlog);
-       cancel_work_sync(&xprt->task_cleanup);
-       kfree(xprt->servername);
        /*
-        * Tear down transport state and free the rpc_xprt
+        * Destroy sockets etc from the system workqueue so they can
+        * safely flush receive work running on rpciod.
         */
-       xprt->ops->destroy(xprt);
+       INIT_WORK(&xprt->task_cleanup, xprt_destroy_cb);
+       schedule_work(&xprt->task_cleanup);
 }
 
 static void xprt_destroy_kref(struct kref *kref)
index 4d9679701a6df5113df3e24a1c9b86e2a63b3710..384c84e83462e51d24e469515f4b52f8dcf55877 100644 (file)
@@ -257,6 +257,8 @@ static int unix_diag_get_exact(struct sk_buff *in_skb,
        err = -ENOENT;
        if (sk == NULL)
                goto out_nosk;
+       if (!net_eq(sock_net(sk), net))
+               goto out;
 
        err = sock_diag_check_cookie(sk, req->udiag_cookie);
        if (err)
index 37cea4d98879979a013a5507a99bb2c6c79b917c..3dd05a08c60a1e2684d8f149ab48592917e8f35b 100644 (file)
@@ -523,11 +523,6 @@ static int cfg80211_sme_connect(struct wireless_dev *wdev,
                return -EOPNOTSUPP;
 
        if (wdev->current_bss) {
-               if (!prev_bssid)
-                       return -EALREADY;
-               if (prev_bssid &&
-                   !ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
-                       return -ENOTCONN;
                cfg80211_unhold_bss(wdev->current_bss);
                cfg80211_put_bss(wdev->wiphy, &wdev->current_bss->pub);
                wdev->current_bss = NULL;
@@ -1064,11 +1059,35 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
 
        ASSERT_WDEV_LOCK(wdev);
 
-       if (WARN_ON(wdev->connect_keys)) {
-               kzfree(wdev->connect_keys);
-               wdev->connect_keys = NULL;
+       /*
+        * If we have an ssid_len, we're trying to connect or are
+        * already connected, so reject a new SSID unless it's the
+        * same (which is the case for re-association.)
+        */
+       if (wdev->ssid_len &&
+           (wdev->ssid_len != connect->ssid_len ||
+            memcmp(wdev->ssid, connect->ssid, wdev->ssid_len)))
+               return -EALREADY;
+
+       /*
+        * If connected, reject (re-)association unless prev_bssid
+        * matches the current BSSID.
+        */
+       if (wdev->current_bss) {
+               if (!prev_bssid)
+                       return -EALREADY;
+               if (!ether_addr_equal(prev_bssid, wdev->current_bss->pub.bssid))
+                       return -ENOTCONN;
        }
 
+       /*
+        * Reject if we're in the process of connecting with WEP,
+        * this case isn't very interesting and trying to handle
+        * it would make the code much more complex.
+        */
+       if (wdev->connect_keys)
+               return -EINPROGRESS;
+
        cfg80211_oper_and_ht_capa(&connect->ht_capa_mask,
                                  rdev->wiphy.ht_capa_mod_mask);
 
@@ -1119,7 +1138,12 @@ int cfg80211_connect(struct cfg80211_registered_device *rdev,
 
        if (err) {
                wdev->connect_keys = NULL;
-               wdev->ssid_len = 0;
+               /*
+                * This could be reassoc getting refused, don't clear
+                * ssid_len in that case.
+                */
+               if (!wdev->current_bss)
+                       wdev->ssid_len = 0;
                return err;
        }
 
@@ -1146,6 +1170,14 @@ int cfg80211_disconnect(struct cfg80211_registered_device *rdev,
        else if (wdev->ssid_len)
                err = rdev_disconnect(rdev, dev, reason);
 
+       /*
+        * Clear ssid_len unless we actually were fully connected,
+        * in which case cfg80211_disconnected() will take care of
+        * this later.
+        */
+       if (!wdev->current_bss)
+               wdev->ssid_len = 0;
+
        return err;
 }
 
index 31a2e6d34dba652dd568d93ae077de3136c252ca..73ad8c8ef344ac4bb6229b49c0b14b099e5fdf13 100644 (file)
@@ -105,6 +105,9 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
                if (xfrm_offload(skb)) {
                        x->type_offload->encap(x, skb);
                } else {
+                       /* Inner headers are invalid now. */
+                       skb->encapsulation = 0;
+
                        err = x->type->output(x, skb);
                        if (err == -EINPROGRESS)
                                goto out;
@@ -208,7 +211,6 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
        int err;
 
        secpath_reset(skb);
-       skb->encapsulation = 0;
 
        if (xfrm_dev_offload_ok(skb, x)) {
                struct sec_path *sp;
index f06253969972aa3489e557faf1ef76f54b1eb3d3..8cafb3c0a4ac501348c5227f1450b800fb834c0e 100644 (file)
@@ -1573,6 +1573,14 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                        goto put_states;
                }
 
+               if (!dst_prev)
+                       dst0 = dst1;
+               else
+                       /* Ref count is taken during xfrm_alloc_dst()
+                        * No need to do dst_clone() on dst1
+                        */
+                       dst_prev->child = dst1;
+
                if (xfrm[i]->sel.family == AF_UNSPEC) {
                        inner_mode = xfrm_ip2inner_mode(xfrm[i],
                                                        xfrm_af2proto(family));
@@ -1584,14 +1592,6 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                } else
                        inner_mode = xfrm[i]->inner_mode;
 
-               if (!dst_prev)
-                       dst0 = dst1;
-               else
-                       /* Ref count is taken during xfrm_alloc_dst()
-                        * No need to do dst_clone() on dst1
-                        */
-                       dst_prev->child = dst1;
-
                xdst->route = dst;
                dst_copy_metrics(dst1, dst);
 
@@ -2076,7 +2076,6 @@ make_dummy_bundle:
        xdst->num_xfrms = num_xfrms;
        memcpy(xdst->pols, pols, sizeof(struct xfrm_policy *) * num_pols);
 
-       dst_hold(&xdst->u.dst);
        return xdst;
 
 inc_error:
index 12213477cd3ad90af9dc2e1bed236e461621115b..1f5cee2269af4296bd41745adec063a4a04faa9f 100644 (file)
@@ -2069,6 +2069,7 @@ int xfrm_user_policy(struct sock *sk, int optname, u8 __user *optval, int optlen
        if (err >= 0) {
                xfrm_sk_policy_insert(sk, err, pol);
                xfrm_pol_put(pol);
+               __sk_dst_reset(sk);
                err = 0;
        }
 
index b997f1395357e8696657d3c07b04318b908fff89..e44a0fed48dd088ac95a0726a5f2b58b0f07c5bb 100644 (file)
@@ -1693,32 +1693,34 @@ static int dump_one_policy(struct xfrm_policy *xp, int dir, int count, void *ptr
 
 static int xfrm_dump_policy_done(struct netlink_callback *cb)
 {
-       struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
+       struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
        struct net *net = sock_net(cb->skb->sk);
 
        xfrm_policy_walk_done(walk, net);
        return 0;
 }
 
+static int xfrm_dump_policy_start(struct netlink_callback *cb)
+{
+       struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
+
+       BUILD_BUG_ON(sizeof(*walk) > sizeof(cb->args));
+
+       xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
+       return 0;
+}
+
 static int xfrm_dump_policy(struct sk_buff *skb, struct netlink_callback *cb)
 {
        struct net *net = sock_net(skb->sk);
-       struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *) &cb->args[1];
+       struct xfrm_policy_walk *walk = (struct xfrm_policy_walk *)cb->args;
        struct xfrm_dump_info info;
 
-       BUILD_BUG_ON(sizeof(struct xfrm_policy_walk) >
-                    sizeof(cb->args) - sizeof(cb->args[0]));
-
        info.in_skb = cb->skb;
        info.out_skb = skb;
        info.nlmsg_seq = cb->nlh->nlmsg_seq;
        info.nlmsg_flags = NLM_F_MULTI;
 
-       if (!cb->args[0]) {
-               cb->args[0] = 1;
-               xfrm_policy_walk_init(walk, XFRM_POLICY_TYPE_ANY);
-       }
-
        (void) xfrm_policy_walk(net, walk, dump_one_policy, &info);
 
        return skb->len;
@@ -2474,6 +2476,7 @@ static const struct nla_policy xfrma_spd_policy[XFRMA_SPD_MAX+1] = {
 
 static const struct xfrm_link {
        int (*doit)(struct sk_buff *, struct nlmsghdr *, struct nlattr **);
+       int (*start)(struct netlink_callback *);
        int (*dump)(struct sk_buff *, struct netlink_callback *);
        int (*done)(struct netlink_callback *);
        const struct nla_policy *nla_pol;
@@ -2487,6 +2490,7 @@ static const struct xfrm_link {
        [XFRM_MSG_NEWPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_add_policy    },
        [XFRM_MSG_DELPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy    },
        [XFRM_MSG_GETPOLICY   - XFRM_MSG_BASE] = { .doit = xfrm_get_policy,
+                                                  .start = xfrm_dump_policy_start,
                                                   .dump = xfrm_dump_policy,
                                                   .done = xfrm_dump_policy_done },
        [XFRM_MSG_ALLOCSPI    - XFRM_MSG_BASE] = { .doit = xfrm_alloc_userspi },
@@ -2539,6 +2543,7 @@ static int xfrm_user_rcv_msg(struct sk_buff *skb, struct nlmsghdr *nlh,
 
                {
                        struct netlink_dump_control c = {
+                               .start = link->start,
                                .dump = link->dump,
                                .done = link->done,
                        };
index 446beb7ac48dc47f7319dcb6bcf91272bd0317d8..5522692100ba0d01d3cd669b7ea1bbdf84b0b72e 100644 (file)
@@ -78,7 +78,7 @@ static int simple_thread_fn(void *arg)
 }
 
 static DEFINE_MUTEX(thread_mutex);
-static bool simple_thread_cnt;
+static int simple_thread_cnt;
 
 int foo_bar_reg(void)
 {
index b8278b51cd9a1055fe7d15bb86fe15f0658d02b1..991db7d6e4df8bff58ac0e3b6b7799c0a195bba4 100644 (file)
@@ -98,7 +98,6 @@ vmlinux.o: FORCE
        $(call cmd,kernel-mod)
 
 # Declare generated files as targets for modpost
-$(symverfile):         __modpost ;
 $(modules:.ko=.mod.c): __modpost ;
 
 
index d5b291e94264f9784438ea38e3242ad7697cb510..9cdec70d72b8ed83c38ec3a271b9495b53975b2e 100644 (file)
@@ -1,6 +1,5 @@
 #
 # Generated include files
 #
-net_names.h
 capability_names.h
 rlim_names.h
index e7ff2183532ab1d589bb8d2f0a3f16f42efb72f2..9a6b4033d52b8f5459a7ac49b7d7b05ef38a2967 100644 (file)
@@ -5,44 +5,11 @@ obj-$(CONFIG_SECURITY_APPARMOR) += apparmor.o
 
 apparmor-y := apparmorfs.o audit.o capability.o context.o ipc.o lib.o match.o \
               path.o domain.o policy.o policy_unpack.o procattr.o lsm.o \
-              resource.o secid.o file.o policy_ns.o label.o mount.o net.o
+              resource.o secid.o file.o policy_ns.o label.o mount.o
 apparmor-$(CONFIG_SECURITY_APPARMOR_HASH) += crypto.o
 
-clean-files := capability_names.h rlim_names.h net_names.h
+clean-files := capability_names.h rlim_names.h
 
-# Build a lower case string table of address family names
-# Transform lines from
-#    #define AF_LOCAL          1       /* POSIX name for AF_UNIX       */
-#    #define AF_INET           2       /* Internet IP Protocol         */
-# to
-#    [1] = "local",
-#    [2] = "inet",
-#
-# and build the securityfs entries for the mapping.
-# Transforms lines from
-#    #define AF_INET           2       /* Internet IP Protocol         */
-# to
-#    #define AA_SFS_AF_MASK "local inet"
-quiet_cmd_make-af = GEN     $@
-cmd_make-af = echo "static const char *address_family_names[] = {" > $@ ;\
-       sed $< >>$@ -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
-        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
-       echo "};" >> $@ ;\
-       printf '%s' '\#define AA_SFS_AF_MASK "' >> $@ ;\
-       sed -r -n -e "/AF_MAX/d" -e "/AF_LOCAL/d" -e "/AF_ROUTE/d" -e \
-        's/^\#define[ \t]+AF_([A-Z0-9_]+)[ \t]+([0-9]+)(.*)/\L\1/p'\
-        $< | tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
-
-# Build a lower case string table of sock type names
-# Transform lines from
-#    SOCK_STREAM       = 1,
-# to
-#    [1] = "stream",
-quiet_cmd_make-sock = GEN     $@
-cmd_make-sock = echo "static const char *sock_type_names[] = {" >> $@ ;\
-       sed $^ >>$@ -r -n \
-       -e 's/^\tSOCK_([A-Z0-9_]+)[\t]+=[ \t]+([0-9]+)(.*)/[\2] = "\L\1",/p';\
-       echo "};" >> $@
 
 # Build a lower case string table of capability names
 # Transforms lines from
@@ -95,7 +62,6 @@ cmd_make-rlim = echo "static const char *const rlim_names[RLIM_NLIMITS] = {" \
            tr '\n' ' ' | sed -e 's/ $$/"\n/' >> $@
 
 $(obj)/capability.o : $(obj)/capability_names.h
-$(obj)/net.o : $(obj)/net_names.h
 $(obj)/resource.o : $(obj)/rlim_names.h
 $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
                            $(src)/Makefile
@@ -103,8 +69,3 @@ $(obj)/capability_names.h : $(srctree)/include/uapi/linux/capability.h \
 $(obj)/rlim_names.h : $(srctree)/include/uapi/asm-generic/resource.h \
                      $(src)/Makefile
        $(call cmd,make-rlim)
-$(obj)/net_names.h : $(srctree)/include/linux/socket.h \
-                    $(srctree)/include/linux/net.h \
-                    $(src)/Makefile
-       $(call cmd,make-af)
-       $(call cmd,make-sock)
index 518d5928661b518c8f037db26edfed44f6270752..caaf51dda64812067e07d1c9079c7750c4296e11 100644 (file)
@@ -2202,7 +2202,6 @@ static struct aa_sfs_entry aa_sfs_entry_features[] = {
        AA_SFS_DIR("policy",                    aa_sfs_entry_policy),
        AA_SFS_DIR("domain",                    aa_sfs_entry_domain),
        AA_SFS_DIR("file",                      aa_sfs_entry_file),
-       AA_SFS_DIR("network",                   aa_sfs_entry_network),
        AA_SFS_DIR("mount",                     aa_sfs_entry_mount),
        AA_SFS_DIR("namespaces",                aa_sfs_entry_ns),
        AA_SFS_FILE_U64("capability",           VFS_CAP_FLAGS_MASK),
index db80221891c66f034c1a3138f46d455a2685d102..3382518b87fa507200679cb9ef660329a292debc 100644 (file)
@@ -21,7 +21,6 @@
 #include "include/context.h"
 #include "include/file.h"
 #include "include/match.h"
-#include "include/net.h"
 #include "include/path.h"
 #include "include/policy.h"
 #include "include/label.h"
@@ -567,32 +566,6 @@ static int __file_path_perm(const char *op, struct aa_label *label,
        return error;
 }
 
-static int __file_sock_perm(const char *op, struct aa_label *label,
-                           struct aa_label *flabel, struct file *file,
-                           u32 request, u32 denied)
-{
-       struct socket *sock = (struct socket *) file->private_data;
-       int error;
-
-       AA_BUG(!sock);
-
-       /* revalidation due to label out of date. No revocation at this time */
-       if (!denied && aa_label_is_subset(flabel, label))
-               return 0;
-
-       /* TODO: improve to skip profiles cached in flabel */
-       error = aa_sock_file_perm(label, op, request, sock);
-       if (denied) {
-               /* TODO: improve to skip profiles checked above */
-               /* check every profile in file label to is cached */
-               last_error(error, aa_sock_file_perm(flabel, op, request, sock));
-       }
-       if (!error)
-               update_file_ctx(file_ctx(file), label, request);
-
-       return error;
-}
-
 /**
  * aa_file_perm - do permission revalidation check & audit for @file
  * @op: operation being checked
@@ -637,9 +610,6 @@ int aa_file_perm(const char *op, struct aa_label *label, struct file *file,
                error = __file_path_perm(op, label, flabel, file, request,
                                         denied);
 
-       else if (S_ISSOCK(file_inode(file)->i_mode))
-               error = __file_sock_perm(op, label, flabel, file, request,
-                                        denied);
 done:
        rcu_read_unlock();
 
index ff4316e1068d6b98ea7cbf44d21e96ff75cf9328..620e811696592ddec6fb221e2bec07d436f258b4 100644 (file)
@@ -121,29 +121,21 @@ struct apparmor_audit_data {
                /* these entries require a custom callback fn */
                struct {
                        struct aa_label *peer;
-                       union {
-                               struct {
-                                       kuid_t ouid;
-                                       const char *target;
-                               } fs;
-                               struct {
-                                       int type, protocol;
-                                       struct sock *peer_sk;
-                                       void *addr;
-                                       int addrlen;
-                               } net;
-                               int signal;
-                               struct {
-                                       int rlim;
-                                       unsigned long max;
-                               } rlim;
-                       };
+                       struct {
+                               const char *target;
+                               kuid_t ouid;
+                       } fs;
                };
                struct {
                        struct aa_profile *profile;
                        const char *ns;
                        long pos;
                } iface;
+               int signal;
+               struct {
+                       int rlim;
+                       unsigned long max;
+               } rlim;
                struct {
                        const char *src_name;
                        const char *type;
diff --git a/security/apparmor/include/net.h b/security/apparmor/include/net.h
deleted file mode 100644 (file)
index 140c8ef..0000000
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * AppArmor security module
- *
- * This file contains AppArmor network mediation definitions.
- *
- * Copyright (C) 1998-2008 Novell/SUSE
- * Copyright 2009-2017 Canonical Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-
-#ifndef __AA_NET_H
-#define __AA_NET_H
-
-#include <net/sock.h>
-#include <linux/path.h>
-
-#include "apparmorfs.h"
-#include "label.h"
-#include "perms.h"
-#include "policy.h"
-
-#define AA_MAY_SEND            AA_MAY_WRITE
-#define AA_MAY_RECEIVE         AA_MAY_READ
-
-#define AA_MAY_SHUTDOWN                AA_MAY_DELETE
-
-#define AA_MAY_CONNECT         AA_MAY_OPEN
-#define AA_MAY_ACCEPT          0x00100000
-
-#define AA_MAY_BIND            0x00200000
-#define AA_MAY_LISTEN          0x00400000
-
-#define AA_MAY_SETOPT          0x01000000
-#define AA_MAY_GETOPT          0x02000000
-
-#define NET_PERMS_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE |    \
-                       AA_MAY_SHUTDOWN | AA_MAY_BIND | AA_MAY_LISTEN |   \
-                       AA_MAY_CONNECT | AA_MAY_ACCEPT | AA_MAY_SETATTR | \
-                       AA_MAY_GETATTR | AA_MAY_SETOPT | AA_MAY_GETOPT)
-
-#define NET_FS_PERMS (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CREATE |   \
-                     AA_MAY_SHUTDOWN | AA_MAY_CONNECT | AA_MAY_RENAME |\
-                     AA_MAY_SETATTR | AA_MAY_GETATTR | AA_MAY_CHMOD |  \
-                     AA_MAY_CHOWN | AA_MAY_CHGRP | AA_MAY_LOCK |       \
-                     AA_MAY_MPROT)
-
-#define NET_PEER_MASK (AA_MAY_SEND | AA_MAY_RECEIVE | AA_MAY_CONNECT | \
-                      AA_MAY_ACCEPT)
-struct aa_sk_ctx {
-       struct aa_label *label;
-       struct aa_label *peer;
-       struct path path;
-};
-
-#define SK_CTX(X) ((X)->sk_security)
-#define SOCK_ctx(X) SOCK_INODE(X)->i_security
-#define DEFINE_AUDIT_NET(NAME, OP, SK, F, T, P)                                  \
-       struct lsm_network_audit NAME ## _net = { .sk = (SK),             \
-                                                 .family = (F)};         \
-       DEFINE_AUDIT_DATA(NAME,                                           \
-                         ((SK) && (F) != AF_UNIX) ? LSM_AUDIT_DATA_NET : \
-                                                    LSM_AUDIT_DATA_NONE, \
-                         OP);                                            \
-       NAME.u.net = &(NAME ## _net);                                     \
-       aad(&NAME)->net.type = (T);                                       \
-       aad(&NAME)->net.protocol = (P)
-
-#define DEFINE_AUDIT_SK(NAME, OP, SK)                                  \
-       DEFINE_AUDIT_NET(NAME, OP, SK, (SK)->sk_family, (SK)->sk_type,  \
-                        (SK)->sk_protocol)
-
-/* struct aa_net - network confinement data
- * @allow: basic network families permissions
- * @audit: which network permissions to force audit
- * @quiet: which network permissions to quiet rejects
- */
-struct aa_net {
-       u16 allow[AF_MAX];
-       u16 audit[AF_MAX];
-       u16 quiet[AF_MAX];
-};
-
-
-extern struct aa_sfs_entry aa_sfs_entry_network[];
-
-void audit_net_cb(struct audit_buffer *ab, void *va);
-int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
-                      u32 request, u16 family, int type);
-int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
-              int type, int protocol);
-static inline int aa_profile_af_sk_perm(struct aa_profile *profile,
-                                       struct common_audit_data *sa,
-                                       u32 request,
-                                       struct sock *sk)
-{
-       return aa_profile_af_perm(profile, sa, request, sk->sk_family,
-                                 sk->sk_type);
-}
-int aa_sk_perm(const char *op, u32 request, struct sock *sk);
-
-int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
-                     struct socket *sock);
-
-
-static inline void aa_free_net_rules(struct aa_net *new)
-{
-       /* NOP */
-}
-
-#endif /* __AA_NET_H */
index af04d5a7d73d46146f152c83529a50829b986962..2b27bb79aec4421665aaa6f2a2490868227bed0f 100644 (file)
@@ -135,10 +135,9 @@ extern struct aa_perms allperms;
 
 
 void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask);
-void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
-                        u32 mask);
+void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask);
 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
-                       u32 chrsmask, const char * const *names, u32 namesmask);
+                       u32 chrsmask, const char **names, u32 namesmask);
 void aa_apply_modes_to_perms(struct aa_profile *profile,
                             struct aa_perms *perms);
 void aa_compute_perms(struct aa_dfa *dfa, unsigned int state,
index 4364088a0b9e2188b6353e815cca6c1b3e70fc25..17fe41a9cac35e6d88f3ae738bf2b068de736ec1 100644 (file)
@@ -30,7 +30,6 @@
 #include "file.h"
 #include "lib.h"
 #include "label.h"
-#include "net.h"
 #include "perms.h"
 #include "resource.h"
 
@@ -112,7 +111,6 @@ struct aa_data {
  * @policy: general match rules governing policy
  * @file: The set of rules governing basic file access and domain transitions
  * @caps: capabilities for the profile
- * @net: network controls for the profile
  * @rlimits: rlimits for the profile
  *
  * @dents: dentries for the profiles file entries in apparmorfs
@@ -150,7 +148,6 @@ struct aa_profile {
        struct aa_policydb policy;
        struct aa_file_rules file;
        struct aa_caps caps;
-       struct aa_net net;
        struct aa_rlimit rlimits;
 
        struct aa_loaddata *rawdata;
@@ -223,16 +220,6 @@ static inline unsigned int PROFILE_MEDIATES_SAFE(struct aa_profile *profile,
        return 0;
 }
 
-static inline unsigned int PROFILE_MEDIATES_AF(struct aa_profile *profile,
-                                              u16 AF) {
-       unsigned int state = PROFILE_MEDIATES(profile, AA_CLASS_NET);
-       u16 be_af = cpu_to_be16(AF);
-
-       if (!state)
-               return 0;
-       return aa_dfa_match_len(profile->policy.dfa, state, (char *) &be_af, 2);
-}
-
 /**
  * aa_get_profile - increment refcount on profile @p
  * @p: profile  (MAYBE NULL)
index 8818621b5d956023d9fc799fbff00a0b073fabc8..08ca26bcca7703c7f74e1531879eea4dd3bf2ac9 100644 (file)
@@ -211,8 +211,7 @@ void aa_perm_mask_to_str(char *str, const char *chrs, u32 mask)
        *str = '\0';
 }
 
-void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
-                        u32 mask)
+void aa_audit_perm_names(struct audit_buffer *ab, const char **names, u32 mask)
 {
        const char *fmt = "%s";
        unsigned int i, perm = 1;
@@ -230,7 +229,7 @@ void aa_audit_perm_names(struct audit_buffer *ab, const char * const *names,
 }
 
 void aa_audit_perm_mask(struct audit_buffer *ab, u32 mask, const char *chrs,
-                       u32 chrsmask, const char * const *names, u32 namesmask)
+                       u32 chrsmask, const char **names, u32 namesmask)
 {
        char str[33];
 
index 72b915dfcaf7eeeed1a2d428777878c81e5f4f80..1346ee5be04f13e4bb64658755605852b8789ab5 100644 (file)
@@ -33,7 +33,6 @@
 #include "include/context.h"
 #include "include/file.h"
 #include "include/ipc.h"
-#include "include/net.h"
 #include "include/path.h"
 #include "include/label.h"
 #include "include/policy.h"
@@ -737,368 +736,6 @@ static int apparmor_task_kill(struct task_struct *target, struct siginfo *info,
        return error;
 }
 
-/**
- * apparmor_sk_alloc_security - allocate and attach the sk_security field
- */
-static int apparmor_sk_alloc_security(struct sock *sk, int family, gfp_t flags)
-{
-       struct aa_sk_ctx *ctx;
-
-       ctx = kzalloc(sizeof(*ctx), flags);
-       if (!ctx)
-               return -ENOMEM;
-
-       SK_CTX(sk) = ctx;
-
-       return 0;
-}
-
-/**
- * apparmor_sk_free_security - free the sk_security field
- */
-static void apparmor_sk_free_security(struct sock *sk)
-{
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
-
-       SK_CTX(sk) = NULL;
-       aa_put_label(ctx->label);
-       aa_put_label(ctx->peer);
-       path_put(&ctx->path);
-       kfree(ctx);
-}
-
-/**
- * apparmor_clone_security - clone the sk_security field
- */
-static void apparmor_sk_clone_security(const struct sock *sk,
-                                      struct sock *newsk)
-{
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
-       struct aa_sk_ctx *new = SK_CTX(newsk);
-
-       new->label = aa_get_label(ctx->label);
-       new->peer = aa_get_label(ctx->peer);
-       new->path = ctx->path;
-       path_get(&new->path);
-}
-
-static int aa_sock_create_perm(struct aa_label *label, int family, int type,
-                              int protocol)
-{
-       AA_BUG(!label);
-       AA_BUG(in_interrupt());
-
-       return aa_af_perm(label, OP_CREATE, AA_MAY_CREATE, family, type,
-                         protocol);
-}
-
-
-/**
- * apparmor_socket_create - check perms before creating a new socket
- */
-static int apparmor_socket_create(int family, int type, int protocol, int kern)
-{
-       struct aa_label *label;
-       int error = 0;
-
-       label = begin_current_label_crit_section();
-       if (!(kern || unconfined(label)))
-               error = aa_sock_create_perm(label, family, type, protocol);
-       end_current_label_crit_section(label);
-
-       return error;
-}
-
-/**
- * apparmor_socket_post_create - setup the per-socket security struct
- *
- * Note:
- * -   kernel sockets currently labeled unconfined but we may want to
- *     move to a special kernel label
- * -   socket may not have sk here if created with sock_create_lite or
- *     sock_alloc. These should be accept cases which will be handled in
- *     sock_graft.
- */
-static int apparmor_socket_post_create(struct socket *sock, int family,
-                                      int type, int protocol, int kern)
-{
-       struct aa_label *label;
-
-       if (kern) {
-               struct aa_ns *ns = aa_get_current_ns();
-
-               label = aa_get_label(ns_unconfined(ns));
-               aa_put_ns(ns);
-       } else
-               label = aa_get_current_label();
-
-       if (sock->sk) {
-               struct aa_sk_ctx *ctx = SK_CTX(sock->sk);
-
-               aa_put_label(ctx->label);
-               ctx->label = aa_get_label(label);
-       }
-       aa_put_label(label);
-
-       return 0;
-}
-
-/**
- * apparmor_socket_bind - check perms before bind addr to socket
- */
-static int apparmor_socket_bind(struct socket *sock,
-                               struct sockaddr *address, int addrlen)
-{
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-       AA_BUG(!address);
-       AA_BUG(in_interrupt());
-
-       return aa_sk_perm(OP_BIND, AA_MAY_BIND, sock->sk);
-}
-
-/**
- * apparmor_socket_connect - check perms before connecting @sock to @address
- */
-static int apparmor_socket_connect(struct socket *sock,
-                                  struct sockaddr *address, int addrlen)
-{
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-       AA_BUG(!address);
-       AA_BUG(in_interrupt());
-
-       return aa_sk_perm(OP_CONNECT, AA_MAY_CONNECT, sock->sk);
-}
-
-/**
- * apparmor_socket_list - check perms before allowing listen
- */
-static int apparmor_socket_listen(struct socket *sock, int backlog)
-{
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-       AA_BUG(in_interrupt());
-
-       return aa_sk_perm(OP_LISTEN, AA_MAY_LISTEN, sock->sk);
-}
-
-/**
- * apparmor_socket_accept - check perms before accepting a new connection.
- *
- * Note: while @newsock is created and has some information, the accept
- *       has not been done.
- */
-static int apparmor_socket_accept(struct socket *sock, struct socket *newsock)
-{
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-       AA_BUG(!newsock);
-       AA_BUG(in_interrupt());
-
-       return aa_sk_perm(OP_ACCEPT, AA_MAY_ACCEPT, sock->sk);
-}
-
-static int aa_sock_msg_perm(const char *op, u32 request, struct socket *sock,
-                           struct msghdr *msg, int size)
-{
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-       AA_BUG(!msg);
-       AA_BUG(in_interrupt());
-
-       return aa_sk_perm(op, request, sock->sk);
-}
-
-/**
- * apparmor_socket_sendmsg - check perms before sending msg to another socket
- */
-static int apparmor_socket_sendmsg(struct socket *sock,
-                                  struct msghdr *msg, int size)
-{
-       return aa_sock_msg_perm(OP_SENDMSG, AA_MAY_SEND, sock, msg, size);
-}
-
-/**
- * apparmor_socket_recvmsg - check perms before receiving a message
- */
-static int apparmor_socket_recvmsg(struct socket *sock,
-                                  struct msghdr *msg, int size, int flags)
-{
-       return aa_sock_msg_perm(OP_RECVMSG, AA_MAY_RECEIVE, sock, msg, size);
-}
-
-/* revaliation, get/set attr, shutdown */
-static int aa_sock_perm(const char *op, u32 request, struct socket *sock)
-{
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-       AA_BUG(in_interrupt());
-
-       return aa_sk_perm(op, request, sock->sk);
-}
-
-/**
- * apparmor_socket_getsockname - check perms before getting the local address
- */
-static int apparmor_socket_getsockname(struct socket *sock)
-{
-       return aa_sock_perm(OP_GETSOCKNAME, AA_MAY_GETATTR, sock);
-}
-
-/**
- * apparmor_socket_getpeername - check perms before getting remote address
- */
-static int apparmor_socket_getpeername(struct socket *sock)
-{
-       return aa_sock_perm(OP_GETPEERNAME, AA_MAY_GETATTR, sock);
-}
-
-/* revaliation, get/set attr, opt */
-static int aa_sock_opt_perm(const char *op, u32 request, struct socket *sock,
-                           int level, int optname)
-{
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-       AA_BUG(in_interrupt());
-
-       return aa_sk_perm(op, request, sock->sk);
-}
-
-/**
- * apparmor_getsockopt - check perms before getting socket options
- */
-static int apparmor_socket_getsockopt(struct socket *sock, int level,
-                                     int optname)
-{
-       return aa_sock_opt_perm(OP_GETSOCKOPT, AA_MAY_GETOPT, sock,
-                               level, optname);
-}
-
-/**
- * apparmor_setsockopt - check perms before setting socket options
- */
-static int apparmor_socket_setsockopt(struct socket *sock, int level,
-                                     int optname)
-{
-       return aa_sock_opt_perm(OP_SETSOCKOPT, AA_MAY_SETOPT, sock,
-                               level, optname);
-}
-
-/**
- * apparmor_socket_shutdown - check perms before shutting down @sock conn
- */
-static int apparmor_socket_shutdown(struct socket *sock, int how)
-{
-       return aa_sock_perm(OP_SHUTDOWN, AA_MAY_SHUTDOWN, sock);
-}
-
-/**
- * apparmor_socket_sock_recv_skb - check perms before associating skb to sk
- *
- * Note: can not sleep may be called with locks held
- *
- * dont want protocol specific in __skb_recv_datagram()
- * to deny an incoming connection  socket_sock_rcv_skb()
- */
-static int apparmor_socket_sock_rcv_skb(struct sock *sk, struct sk_buff *skb)
-{
-       return 0;
-}
-
-
-static struct aa_label *sk_peer_label(struct sock *sk)
-{
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
-
-       if (ctx->peer)
-               return ctx->peer;
-
-       return ERR_PTR(-ENOPROTOOPT);
-}
-
-/**
- * apparmor_socket_getpeersec_stream - get security context of peer
- *
- * Note: for tcp only valid if using ipsec or cipso on lan
- */
-static int apparmor_socket_getpeersec_stream(struct socket *sock,
-                                            char __user *optval,
-                                            int __user *optlen,
-                                            unsigned int len)
-{
-       char *name;
-       int slen, error = 0;
-       struct aa_label *label;
-       struct aa_label *peer;
-
-       label = begin_current_label_crit_section();
-       peer = sk_peer_label(sock->sk);
-       if (IS_ERR(peer)) {
-               error = PTR_ERR(peer);
-               goto done;
-       }
-       slen = aa_label_asxprint(&name, labels_ns(label), peer,
-                                FLAG_SHOW_MODE | FLAG_VIEW_SUBNS |
-                                FLAG_HIDDEN_UNCONFINED, GFP_KERNEL);
-       /* don't include terminating \0 in slen, it breaks some apps */
-       if (slen < 0) {
-               error = -ENOMEM;
-       } else {
-               if (slen > len) {
-                       error = -ERANGE;
-               } else if (copy_to_user(optval, name, slen)) {
-                       error = -EFAULT;
-                       goto out;
-               }
-               if (put_user(slen, optlen))
-                       error = -EFAULT;
-out:
-               kfree(name);
-
-       }
-
-done:
-       end_current_label_crit_section(label);
-
-       return error;
-}
-
-/**
- * apparmor_socket_getpeersec_dgram - get security label of packet
- * @sock: the peer socket
- * @skb: packet data
- * @secid: pointer to where to put the secid of the packet
- *
- * Sets the netlabel socket state on sk from parent
- */
-static int apparmor_socket_getpeersec_dgram(struct socket *sock,
-                                           struct sk_buff *skb, u32 *secid)
-
-{
-       /* TODO: requires secid support */
-       return -ENOPROTOOPT;
-}
-
-/**
- * apparmor_sock_graft - Initialize newly created socket
- * @sk: child sock
- * @parent: parent socket
- *
- * Note: could set off of SOCK_CTX(parent) but need to track inode and we can
- *       just set sk security information off of current creating process label
- *       Labeling of sk for accept case - probably should be sock based
- *       instead of task, because of the case where an implicitly labeled
- *       socket is shared by different tasks.
- */
-static void apparmor_sock_graft(struct sock *sk, struct socket *parent)
-{
-       struct aa_sk_ctx *ctx = SK_CTX(sk);
-
-       if (!ctx->label)
-               ctx->label = aa_get_current_label();
-}
-
 static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(ptrace_access_check, apparmor_ptrace_access_check),
        LSM_HOOK_INIT(ptrace_traceme, apparmor_ptrace_traceme),
@@ -1133,30 +770,6 @@ static struct security_hook_list apparmor_hooks[] __lsm_ro_after_init = {
        LSM_HOOK_INIT(getprocattr, apparmor_getprocattr),
        LSM_HOOK_INIT(setprocattr, apparmor_setprocattr),
 
-       LSM_HOOK_INIT(sk_alloc_security, apparmor_sk_alloc_security),
-       LSM_HOOK_INIT(sk_free_security, apparmor_sk_free_security),
-       LSM_HOOK_INIT(sk_clone_security, apparmor_sk_clone_security),
-
-       LSM_HOOK_INIT(socket_create, apparmor_socket_create),
-       LSM_HOOK_INIT(socket_post_create, apparmor_socket_post_create),
-       LSM_HOOK_INIT(socket_bind, apparmor_socket_bind),
-       LSM_HOOK_INIT(socket_connect, apparmor_socket_connect),
-       LSM_HOOK_INIT(socket_listen, apparmor_socket_listen),
-       LSM_HOOK_INIT(socket_accept, apparmor_socket_accept),
-       LSM_HOOK_INIT(socket_sendmsg, apparmor_socket_sendmsg),
-       LSM_HOOK_INIT(socket_recvmsg, apparmor_socket_recvmsg),
-       LSM_HOOK_INIT(socket_getsockname, apparmor_socket_getsockname),
-       LSM_HOOK_INIT(socket_getpeername, apparmor_socket_getpeername),
-       LSM_HOOK_INIT(socket_getsockopt, apparmor_socket_getsockopt),
-       LSM_HOOK_INIT(socket_setsockopt, apparmor_socket_setsockopt),
-       LSM_HOOK_INIT(socket_shutdown, apparmor_socket_shutdown),
-       LSM_HOOK_INIT(socket_sock_rcv_skb, apparmor_socket_sock_rcv_skb),
-       LSM_HOOK_INIT(socket_getpeersec_stream,
-                     apparmor_socket_getpeersec_stream),
-       LSM_HOOK_INIT(socket_getpeersec_dgram,
-                     apparmor_socket_getpeersec_dgram),
-       LSM_HOOK_INIT(sock_graft, apparmor_sock_graft),
-
        LSM_HOOK_INIT(cred_alloc_blank, apparmor_cred_alloc_blank),
        LSM_HOOK_INIT(cred_free, apparmor_cred_free),
        LSM_HOOK_INIT(cred_prepare, apparmor_cred_prepare),
diff --git a/security/apparmor/net.c b/security/apparmor/net.c
deleted file mode 100644 (file)
index 33d5443..0000000
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * AppArmor security module
- *
- * This file contains AppArmor network mediation
- *
- * Copyright (C) 1998-2008 Novell/SUSE
- * Copyright 2009-2017 Canonical Ltd.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation, version 2 of the
- * License.
- */
-
-#include "include/apparmor.h"
-#include "include/audit.h"
-#include "include/context.h"
-#include "include/label.h"
-#include "include/net.h"
-#include "include/policy.h"
-
-#include "net_names.h"
-
-
-struct aa_sfs_entry aa_sfs_entry_network[] = {
-       AA_SFS_FILE_STRING("af_mask",   AA_SFS_AF_MASK),
-       { }
-};
-
-static const char * const net_mask_names[] = {
-       "unknown",
-       "send",
-       "receive",
-       "unknown",
-
-       "create",
-       "shutdown",
-       "connect",
-       "unknown",
-
-       "setattr",
-       "getattr",
-       "setcred",
-       "getcred",
-
-       "chmod",
-       "chown",
-       "chgrp",
-       "lock",
-
-       "mmap",
-       "mprot",
-       "unknown",
-       "unknown",
-
-       "accept",
-       "bind",
-       "listen",
-       "unknown",
-
-       "setopt",
-       "getopt",
-       "unknown",
-       "unknown",
-
-       "unknown",
-       "unknown",
-       "unknown",
-       "unknown",
-};
-
-
-/* audit callback for net specific fields */
-void audit_net_cb(struct audit_buffer *ab, void *va)
-{
-       struct common_audit_data *sa = va;
-
-       audit_log_format(ab, " family=");
-       if (address_family_names[sa->u.net->family])
-               audit_log_string(ab, address_family_names[sa->u.net->family]);
-       else
-               audit_log_format(ab, "\"unknown(%d)\"", sa->u.net->family);
-       audit_log_format(ab, " sock_type=");
-       if (sock_type_names[aad(sa)->net.type])
-               audit_log_string(ab, sock_type_names[aad(sa)->net.type]);
-       else
-               audit_log_format(ab, "\"unknown(%d)\"", aad(sa)->net.type);
-       audit_log_format(ab, " protocol=%d", aad(sa)->net.protocol);
-
-       if (aad(sa)->request & NET_PERMS_MASK) {
-               audit_log_format(ab, " requested_mask=");
-               aa_audit_perm_mask(ab, aad(sa)->request, NULL, 0,
-                                  net_mask_names, NET_PERMS_MASK);
-
-               if (aad(sa)->denied & NET_PERMS_MASK) {
-                       audit_log_format(ab, " denied_mask=");
-                       aa_audit_perm_mask(ab, aad(sa)->denied, NULL, 0,
-                                          net_mask_names, NET_PERMS_MASK);
-               }
-       }
-       if (aad(sa)->peer) {
-               audit_log_format(ab, " peer=");
-               aa_label_xaudit(ab, labels_ns(aad(sa)->label), aad(sa)->peer,
-                               FLAGS_NONE, GFP_ATOMIC);
-       }
-}
-
-
-/* Generic af perm */
-int aa_profile_af_perm(struct aa_profile *profile, struct common_audit_data *sa,
-                      u32 request, u16 family, int type)
-{
-       struct aa_perms perms = { };
-
-       AA_BUG(family >= AF_MAX);
-       AA_BUG(type < 0 || type >= SOCK_MAX);
-
-       if (profile_unconfined(profile))
-               return 0;
-
-       perms.allow = (profile->net.allow[family] & (1 << type)) ?
-               ALL_PERMS_MASK : 0;
-       perms.audit = (profile->net.audit[family] & (1 << type)) ?
-               ALL_PERMS_MASK : 0;
-       perms.quiet = (profile->net.quiet[family] & (1 << type)) ?
-               ALL_PERMS_MASK : 0;
-       aa_apply_modes_to_perms(profile, &perms);
-
-       return aa_check_perms(profile, &perms, request, sa, audit_net_cb);
-}
-
-int aa_af_perm(struct aa_label *label, const char *op, u32 request, u16 family,
-              int type, int protocol)
-{
-       struct aa_profile *profile;
-       DEFINE_AUDIT_NET(sa, op, NULL, family, type, protocol);
-
-       return fn_for_each_confined(label, profile,
-                       aa_profile_af_perm(profile, &sa, request, family,
-                                          type));
-}
-
-static int aa_label_sk_perm(struct aa_label *label, const char *op, u32 request,
-                           struct sock *sk)
-{
-       struct aa_profile *profile;
-       DEFINE_AUDIT_SK(sa, op, sk);
-
-       AA_BUG(!label);
-       AA_BUG(!sk);
-
-       if (unconfined(label))
-               return 0;
-
-       return fn_for_each_confined(label, profile,
-                       aa_profile_af_sk_perm(profile, &sa, request, sk));
-}
-
-int aa_sk_perm(const char *op, u32 request, struct sock *sk)
-{
-       struct aa_label *label;
-       int error;
-
-       AA_BUG(!sk);
-       AA_BUG(in_interrupt());
-
-       /* TODO: switch to begin_current_label ???? */
-       label = begin_current_label_crit_section();
-       error = aa_label_sk_perm(label, op, request, sk);
-       end_current_label_crit_section(label);
-
-       return error;
-}
-
-
-int aa_sock_file_perm(struct aa_label *label, const char *op, u32 request,
-                     struct socket *sock)
-{
-       AA_BUG(!label);
-       AA_BUG(!sock);
-       AA_BUG(!sock->sk);
-
-       return aa_label_sk_perm(label, op, request, sock->sk);
-}
index 5a2aec358322a930a5e6473a9e22acd64462298b..4ede87c30f8b890a63e1aaae0a75a9ed6ba1045c 100644 (file)
@@ -275,19 +275,6 @@ fail:
        return 0;
 }
 
-static bool unpack_u16(struct aa_ext *e, u16 *data, const char *name)
-{
-       if (unpack_nameX(e, AA_U16, name)) {
-               if (!inbounds(e, sizeof(u16)))
-                       return 0;
-               if (data)
-                       *data = le16_to_cpu(get_unaligned((__le16 *) e->pos));
-               e->pos += sizeof(u16);
-               return 1;
-       }
-       return 0;
-}
-
 static bool unpack_u32(struct aa_ext *e, u32 *data, const char *name)
 {
        if (unpack_nameX(e, AA_U32, name)) {
@@ -597,7 +584,7 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
        struct aa_profile *profile = NULL;
        const char *tmpname, *tmpns = NULL, *name = NULL;
        const char *info = "failed to unpack profile";
-       size_t size = 0, ns_len;
+       size_t ns_len;
        struct rhashtable_params params = { 0 };
        char *key = NULL;
        struct aa_data *data;
@@ -730,38 +717,6 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
                goto fail;
        }
 
-       size = unpack_array(e, "net_allowed_af");
-       if (size) {
-
-               for (i = 0; i < size; i++) {
-                       /* discard extraneous rules that this kernel will
-                        * never request
-                        */
-                       if (i >= AF_MAX) {
-                               u16 tmp;
-
-                               if (!unpack_u16(e, &tmp, NULL) ||
-                                   !unpack_u16(e, &tmp, NULL) ||
-                                   !unpack_u16(e, &tmp, NULL))
-                                       goto fail;
-                               continue;
-                       }
-                       if (!unpack_u16(e, &profile->net.allow[i], NULL))
-                               goto fail;
-                       if (!unpack_u16(e, &profile->net.audit[i], NULL))
-                               goto fail;
-                       if (!unpack_u16(e, &profile->net.quiet[i], NULL))
-                               goto fail;
-               }
-               if (!unpack_nameX(e, AA_ARRAYEND, NULL))
-                       goto fail;
-       }
-       if (VERSION_LT(e->version, v7)) {
-               /* pre v7 policy always allowed these */
-               profile->net.allow[AF_UNIX] = 0xffff;
-               profile->net.allow[AF_NETLINK] = 0xffff;
-       }
-
        if (unpack_nameX(e, AA_STRUCT, "policydb")) {
                /* generic policy dfa - optional and may be NULL */
                info = "failed to unpack policydb";
index a7e51f7938671c76fa917ea66a7a1d6524f21364..36f842ec87f04580dfd051f4e50d395242a69eb6 100644 (file)
@@ -459,34 +459,33 @@ static long keyring_read(const struct key *keyring,
                         char __user *buffer, size_t buflen)
 {
        struct keyring_read_iterator_context ctx;
-       unsigned long nr_keys;
-       int ret;
+       long ret;
 
        kenter("{%d},,%zu", key_serial(keyring), buflen);
 
        if (buflen & (sizeof(key_serial_t) - 1))
                return -EINVAL;
 
-       nr_keys = keyring->keys.nr_leaves_on_tree;
-       if (nr_keys == 0)
-               return 0;
-
-       /* Calculate how much data we could return */
-       if (!buffer || !buflen)
-               return nr_keys * sizeof(key_serial_t);
-
-       /* Copy the IDs of the subscribed keys into the buffer */
-       ctx.buffer = (key_serial_t __user *)buffer;
-       ctx.buflen = buflen;
-       ctx.count = 0;
-       ret = assoc_array_iterate(&keyring->keys, keyring_read_iterator, &ctx);
-       if (ret < 0) {
-               kleave(" = %d [iterate]", ret);
-               return ret;
+       /* Copy as many key IDs as fit into the buffer */
+       if (buffer && buflen) {
+               ctx.buffer = (key_serial_t __user *)buffer;
+               ctx.buflen = buflen;
+               ctx.count = 0;
+               ret = assoc_array_iterate(&keyring->keys,
+                                         keyring_read_iterator, &ctx);
+               if (ret < 0) {
+                       kleave(" = %ld [iterate]", ret);
+                       return ret;
+               }
        }
 
-       kleave(" = %zu [ok]", ctx.count);
-       return ctx.count;
+       /* Return the size of the buffer needed */
+       ret = keyring->keys.nr_leaves_on_tree * sizeof(key_serial_t);
+       if (ret <= buflen)
+               kleave("= %ld [ok]", ret);
+       else
+               kleave("= %ld [buffer too small]", ret);
+       return ret;
 }
 
 /*
index bd85315cbfeb3e1bad3b01e7d9a6538bbb5d3577..98aa89ff7bfd9ed57662116ca455f3a5628ec380 100644 (file)
@@ -1147,20 +1147,21 @@ static long trusted_read(const struct key *key, char __user *buffer,
        p = dereference_key_locked(key);
        if (!p)
                return -EINVAL;
-       if (!buffer || buflen <= 0)
-               return 2 * p->blob_len;
-       ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
-       if (!ascii_buf)
-               return -ENOMEM;
 
-       bufp = ascii_buf;
-       for (i = 0; i < p->blob_len; i++)
-               bufp = hex_byte_pack(bufp, p->blob[i]);
-       if ((copy_to_user(buffer, ascii_buf, 2 * p->blob_len)) != 0) {
+       if (buffer && buflen >= 2 * p->blob_len) {
+               ascii_buf = kmalloc(2 * p->blob_len, GFP_KERNEL);
+               if (!ascii_buf)
+                       return -ENOMEM;
+
+               bufp = ascii_buf;
+               for (i = 0; i < p->blob_len; i++)
+                       bufp = hex_byte_pack(bufp, p->blob[i]);
+               if (copy_to_user(buffer, ascii_buf, 2 * p->blob_len) != 0) {
+                       kzfree(ascii_buf);
+                       return -EFAULT;
+               }
                kzfree(ascii_buf);
-               return -EFAULT;
        }
-       kzfree(ascii_buf);
        return 2 * p->blob_len;
 }
 
index 6c9cba2166d95b3b9175cc9eb39ca14e3a14f0f5..d10c780dfd5468137b3b862f6b04e0279d32e3d6 100644 (file)
@@ -663,7 +663,7 @@ static int deliver_to_subscribers(struct snd_seq_client *client,
        if (atomic)
                read_lock(&grp->list_lock);
        else
-               down_read(&grp->list_mutex);
+               down_read_nested(&grp->list_mutex, hop);
        list_for_each_entry(subs, &grp->list_head, src_list) {
                /* both ports ready? */
                if (atomic_read(&subs->ref_count) != 2)
index 6a437eb661152923b7fc0764850d2fae1f6806b4..59127b6ef39ee97b1abf66767b44a6933fa367e4 100644 (file)
@@ -133,7 +133,8 @@ enum {
 #endif /* CONFIG_X86_X32 */
 };
 
-static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, unsigned long arg)
+static long __snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
+                                         unsigned long arg)
 {
        void __user *argp = compat_ptr(arg);
 
@@ -153,7 +154,7 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
        case SNDRV_TIMER_IOCTL_PAUSE:
        case SNDRV_TIMER_IOCTL_PAUSE_OLD:
        case SNDRV_TIMER_IOCTL_NEXT_DEVICE:
-               return snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
+               return __snd_timer_user_ioctl(file, cmd, (unsigned long)argp);
        case SNDRV_TIMER_IOCTL_GPARAMS32:
                return snd_timer_user_gparams_compat(file, argp);
        case SNDRV_TIMER_IOCTL_INFO32:
@@ -167,3 +168,15 @@ static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd, uns
        }
        return -ENOIOCTLCMD;
 }
+
+static long snd_timer_user_ioctl_compat(struct file *file, unsigned int cmd,
+                                       unsigned long arg)
+{
+       struct snd_timer_user *tu = file->private_data;
+       long ret;
+
+       mutex_lock(&tu->ioctl_lock);
+       ret = __snd_timer_user_ioctl_compat(file, cmd, arg);
+       mutex_unlock(&tu->ioctl_lock);
+       return ret;
+}
index 0ce71111b4e3ec0fd58940b27a0638cc9d483fd1..546d515f3c1fb810641375e5fcf548ef4e360807 100644 (file)
@@ -327,6 +327,7 @@ static void alc_fill_eapd_coef(struct hda_codec *codec)
        case 0x10ec0215:
        case 0x10ec0225:
        case 0x10ec0233:
+       case 0x10ec0236:
        case 0x10ec0255:
        case 0x10ec0256:
        case 0x10ec0282:
@@ -911,6 +912,7 @@ static struct alc_codec_rename_pci_table rename_pci_tbl[] = {
        { 0x10ec0275, 0x1028, 0, "ALC3260" },
        { 0x10ec0899, 0x1028, 0, "ALC3861" },
        { 0x10ec0298, 0x1028, 0, "ALC3266" },
+       { 0x10ec0236, 0x1028, 0, "ALC3204" },
        { 0x10ec0256, 0x1028, 0, "ALC3246" },
        { 0x10ec0225, 0x1028, 0, "ALC3253" },
        { 0x10ec0295, 0x1028, 0, "ALC3254" },
@@ -3930,6 +3932,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
                alc_process_coef_fw(codec, coef0255_1);
                alc_process_coef_fw(codec, coef0255);
                break;
+       case 0x10ec0236:
        case 0x10ec0256:
                alc_process_coef_fw(codec, coef0256);
                alc_process_coef_fw(codec, coef0255);
@@ -4028,6 +4031,7 @@ static void alc_headset_mode_mic_in(struct hda_codec *codec, hda_nid_t hp_pin,
        };
 
        switch (codec->core.vendor_id) {
+       case 0x10ec0236:
        case 0x10ec0255:
        case 0x10ec0256:
                alc_write_coef_idx(codec, 0x45, 0xc489);
@@ -4160,6 +4164,7 @@ static void alc_headset_mode_default(struct hda_codec *codec)
                alc_process_coef_fw(codec, alc225_pre_hsmode);
                alc_process_coef_fw(codec, coef0225);
                break;
+       case 0x10ec0236:
        case 0x10ec0255:
        case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
@@ -4256,6 +4261,7 @@ static void alc_headset_mode_ctia(struct hda_codec *codec)
        case 0x10ec0255:
                alc_process_coef_fw(codec, coef0255);
                break;
+       case 0x10ec0236:
        case 0x10ec0256:
                alc_process_coef_fw(codec, coef0256);
                break;
@@ -4366,6 +4372,7 @@ static void alc_headset_mode_omtp(struct hda_codec *codec)
        case 0x10ec0255:
                alc_process_coef_fw(codec, coef0255);
                break;
+       case 0x10ec0236:
        case 0x10ec0256:
                alc_process_coef_fw(codec, coef0256);
                break;
@@ -4451,6 +4458,7 @@ static void alc_determine_headset_type(struct hda_codec *codec)
        };
 
        switch (codec->core.vendor_id) {
+       case 0x10ec0236:
        case 0x10ec0255:
        case 0x10ec0256:
                alc_process_coef_fw(codec, coef0255);
@@ -4705,6 +4713,7 @@ static void alc255_set_default_jack_type(struct hda_codec *codec)
        case 0x10ec0255:
                alc_process_coef_fw(codec, alc255fw);
                break;
+       case 0x10ec0236:
        case 0x10ec0256:
                alc_process_coef_fw(codec, alc256fw);
                break;
@@ -6419,6 +6428,14 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                ALC225_STANDARD_PINS,
                {0x12, 0xb7a60130},
                {0x1b, 0x90170110}),
+       SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x12, 0x90a60140},
+               {0x14, 0x90170110},
+               {0x21, 0x02211020}),
+       SND_HDA_PIN_QUIRK(0x10ec0236, 0x1028, "Dell", ALC255_FIXUP_DELL1_MIC_NO_PRESENCE,
+               {0x12, 0x90a60140},
+               {0x14, 0x90170150},
+               {0x21, 0x02211020}),
        SND_HDA_PIN_QUIRK(0x10ec0255, 0x1028, "Dell", ALC255_FIXUP_DELL2_MIC_NO_PRESENCE,
                {0x14, 0x90170110},
                {0x21, 0x02211020}),
@@ -6806,6 +6823,7 @@ static int patch_alc269(struct hda_codec *codec)
        case 0x10ec0255:
                spec->codec_variant = ALC269_TYPE_ALC255;
                break;
+       case 0x10ec0236:
        case 0x10ec0256:
                spec->codec_variant = ALC269_TYPE_ALC256;
                spec->shutup = alc256_shutup;
@@ -7857,6 +7875,7 @@ static const struct hda_device_id snd_hda_id_realtek[] = {
        HDA_CODEC_ENTRY(0x10ec0233, "ALC233", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0234, "ALC234", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0235, "ALC233", patch_alc269),
+       HDA_CODEC_ENTRY(0x10ec0236, "ALC236", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0255, "ALC255", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0256, "ALC256", patch_alc269),
        HDA_CODEC_ENTRY(0x10ec0260, "ALC260", patch_alc260),
index 2c1bd27638648796dd89e117613578655429232d..6758f789b712cd32af6940ef501619a5af6b8502 100644 (file)
@@ -90,6 +90,27 @@ static int adau17x1_pll_event(struct snd_soc_dapm_widget *w,
        return 0;
 }
 
+static int adau17x1_adc_fixup(struct snd_soc_dapm_widget *w,
+       struct snd_kcontrol *kcontrol, int event)
+{
+       struct snd_soc_codec *codec = snd_soc_dapm_to_codec(w->dapm);
+       struct adau *adau = snd_soc_codec_get_drvdata(codec);
+
+       /*
+        * If we are capturing, toggle the ADOSR bit in Converter Control 0 to
+        * avoid losing SNR (workaround from ADI). This must be done after
+        * the ADC(s) have been enabled. According to the data sheet, it is
+        * normally illegal to set this bit when the sampling rate is 96 kHz,
+        * but according to ADI it is acceptable for this workaround.
+        */
+       regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
+               ADAU17X1_CONVERTER0_ADOSR, ADAU17X1_CONVERTER0_ADOSR);
+       regmap_update_bits(adau->regmap, ADAU17X1_CONVERTER0,
+               ADAU17X1_CONVERTER0_ADOSR, 0);
+
+       return 0;
+}
+
 static const char * const adau17x1_mono_stereo_text[] = {
        "Stereo",
        "Mono Left Channel (L+R)",
@@ -121,7 +142,8 @@ static const struct snd_soc_dapm_widget adau17x1_dapm_widgets[] = {
        SND_SOC_DAPM_MUX("Right DAC Mode Mux", SND_SOC_NOPM, 0, 0,
                &adau17x1_dac_mode_mux),
 
-       SND_SOC_DAPM_ADC("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0),
+       SND_SOC_DAPM_ADC_E("Left Decimator", NULL, ADAU17X1_ADC_CONTROL, 0, 0,
+                          adau17x1_adc_fixup, SND_SOC_DAPM_POST_PMU),
        SND_SOC_DAPM_ADC("Right Decimator", NULL, ADAU17X1_ADC_CONTROL, 1, 0),
        SND_SOC_DAPM_DAC("Left DAC", NULL, ADAU17X1_DAC_CONTROL0, 0, 0),
        SND_SOC_DAPM_DAC("Right DAC", NULL, ADAU17X1_DAC_CONTROL0, 1, 0),
index ebae545241a444033377f87a494e3df4de27950f..eaf8f933bab8ae60c22475dbaaf6adf771474654 100644 (file)
@@ -130,5 +130,7 @@ bool adau17x1_has_dsp(struct adau *adau);
 
 #define ADAU17X1_CONVERTER0_CONVSR_MASK                0x7
 
+#define ADAU17X1_CONVERTER0_ADOSR              BIT(3)
+
 
 #endif
index ed6e5373916c390fb15dfc9efd943c9c55f7d819..12f2ecf3a4feeb3a6133012b33b5b10cad33999f 100644 (file)
@@ -145,9 +145,8 @@ done:
        mutex_unlock(&rt5514_dsp->dma_lock);
 }
 
-static irqreturn_t rt5514_spi_irq(int irq, void *data)
+static void rt5514_schedule_copy(struct rt5514_dsp *rt5514_dsp)
 {
-       struct rt5514_dsp *rt5514_dsp = data;
        u8 buf[8];
 
        rt5514_dsp->get_size = 0;
@@ -180,6 +179,13 @@ static irqreturn_t rt5514_spi_irq(int irq, void *data)
        if (rt5514_dsp->buf_base && rt5514_dsp->buf_limit &&
                rt5514_dsp->buf_rp && rt5514_dsp->buf_size)
                schedule_delayed_work(&rt5514_dsp->copy_work, 0);
+}
+
+static irqreturn_t rt5514_spi_irq(int irq, void *data)
+{
+       struct rt5514_dsp *rt5514_dsp = data;
+
+       rt5514_schedule_copy(rt5514_dsp);
 
        return IRQ_HANDLED;
 }
@@ -199,12 +205,19 @@ static int rt5514_spi_hw_params(struct snd_pcm_substream *substream,
        struct rt5514_dsp *rt5514_dsp =
                        snd_soc_platform_get_drvdata(rtd->platform);
        int ret;
+       u8 buf[8];
 
        mutex_lock(&rt5514_dsp->dma_lock);
        ret = snd_pcm_lib_alloc_vmalloc_buffer(substream,
                        params_buffer_bytes(hw_params));
        rt5514_dsp->substream = substream;
        rt5514_dsp->dma_offset = 0;
+
+       /* Read IRQ status and schedule copy accordingly. */
+       rt5514_spi_burst_read(RT5514_IRQ_CTRL, (u8 *)&buf, sizeof(buf));
+       if (buf[0] & RT5514_IRQ_STATUS_BIT)
+               rt5514_schedule_copy(rt5514_dsp);
+
        mutex_unlock(&rt5514_dsp->dma_lock);
 
        return ret;
index a6434ee6ff037c11c945a3358a90070de316b09c..c1a36647c1197f925985a623ffe52336fd167c68 100644 (file)
@@ -20,6 +20,9 @@
 #define RT5514_BUFFER_VOICE_BASE       0x18000200
 #define RT5514_BUFFER_VOICE_LIMIT      0x18000204
 #define RT5514_BUFFER_VOICE_WP         0x1800020c
+#define RT5514_IRQ_CTRL                        0x18002094
+
+#define RT5514_IRQ_STATUS_BIT          (0x1 << 5)
 
 /* SPI Command */
 enum {
index 0945d212b8dca9d34d19b273d9075977075964e1..d7956ababd11775b0b9d04552faa68f2fadd2545 100644 (file)
@@ -338,39 +338,6 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
                                fw = NULL;
                        }
 
-                       if (rt5514->model_buf && rt5514->model_len) {
-#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
-                               int ret;
-
-                               ret = rt5514_spi_burst_write(0x4ff80000,
-                                       rt5514->model_buf,
-                                       ((rt5514->model_len / 8) + 1) * 8);
-                               if (ret) {
-                                       dev_err(codec->dev,
-                                               "Model load failed %d\n", ret);
-                                       return ret;
-                               }
-#else
-                               dev_err(codec->dev,
-                                       "No SPI driver for loading firmware\n");
-#endif
-                       } else {
-                               request_firmware(&fw, RT5514_FIRMWARE3,
-                                                codec->dev);
-                               if (fw) {
-#if IS_ENABLED(CONFIG_SND_SOC_RT5514_SPI)
-                                       rt5514_spi_burst_write(0x4ff80000,
-                                               fw->data,
-                                               ((fw->size/8)+1)*8);
-#else
-                                       dev_err(codec->dev,
-                                               "No SPI driver to load fw\n");
-#endif
-                                       release_firmware(fw);
-                                       fw = NULL;
-                               }
-                       }
-
                        /* DSP run */
                        regmap_write(rt5514->i2c_regmap, 0x18002f00,
                                0x00055148);
@@ -385,34 +352,6 @@ static int rt5514_dsp_voice_wake_up_put(struct snd_kcontrol *kcontrol,
        return 0;
 }
 
-static int rt5514_hotword_model_put(struct snd_kcontrol *kcontrol,
-               const unsigned int __user *bytes, unsigned int size)
-{
-       struct snd_soc_component *component = snd_kcontrol_chip(kcontrol);
-       struct rt5514_priv *rt5514 = snd_soc_component_get_drvdata(component);
-       struct snd_soc_codec *codec = rt5514->codec;
-       int ret = 0;
-
-       if (rt5514->model_buf || rt5514->model_len < size) {
-               if (rt5514->model_buf)
-                       devm_kfree(codec->dev, rt5514->model_buf);
-               rt5514->model_buf = devm_kmalloc(codec->dev, size, GFP_KERNEL);
-               if (!rt5514->model_buf) {
-                       ret = -ENOMEM;
-                       goto done;
-               }
-       }
-
-       /* Skips the TLV header. */
-       bytes += 2;
-
-       if (copy_from_user(rt5514->model_buf, bytes, size))
-               ret = -EFAULT;
-done:
-       rt5514->model_len = (ret ? 0 : size);
-       return ret;
-}
-
 static const struct snd_kcontrol_new rt5514_snd_controls[] = {
        SOC_DOUBLE_TLV("MIC Boost Volume", RT5514_ANA_CTRL_MICBST,
                RT5514_SEL_BSTL_SFT, RT5514_SEL_BSTR_SFT, 8, 0, bst_tlv),
@@ -424,8 +363,6 @@ static const struct snd_kcontrol_new rt5514_snd_controls[] = {
                adc_vol_tlv),
        SOC_SINGLE_EXT("DSP Voice Wake Up", SND_SOC_NOPM, 0, 1, 0,
                rt5514_dsp_voice_wake_up_get, rt5514_dsp_voice_wake_up_put),
-       SND_SOC_BYTES_TLV("Hotword Model", 0x8504,
-               NULL, rt5514_hotword_model_put),
 };
 
 /* ADC Mixer*/
index 803311cb7e2a075aa405847a673b31cac66afc6a..2dc40e6d8b3f69835ded69ac71012cb765ac0a36 100644 (file)
 
 #define RT5514_FIRMWARE1       "rt5514_dsp_fw1.bin"
 #define RT5514_FIRMWARE2       "rt5514_dsp_fw2.bin"
-#define RT5514_FIRMWARE3       "rt5514_dsp_fw3.bin"
 
 /* System Clock Source */
 enum {
@@ -282,8 +281,6 @@ struct rt5514_priv {
        int pll_in;
        int pll_out;
        int dsp_enabled;
-       u8 *model_buf;
-       unsigned int model_len;
 };
 
 #endif /* __RT5514_H__ */
index c94e94fe8297877c75f929498628b5d5adf4b654..0e5f54a9bc7efdf1db73307030310b21472c862c 100644 (file)
@@ -98,7 +98,7 @@ static const struct reg_default rt5616_reg[] = {
        { 0x8e, 0x0004 },
        { 0x8f, 0x1100 },
        { 0x90, 0x0000 },
-       { 0x91, 0x0000 },
+       { 0x91, 0x0c00 },
        { 0x92, 0x0000 },
        { 0x93, 0x2000 },
        { 0x94, 0x0200 },
index 71216db15eab8811775275575b573754b85889b5..fa66b11df8d447d1a41af835d085d76afca2ba5e 100644 (file)
@@ -2744,7 +2744,8 @@ static const struct snd_soc_dapm_widget rt5659_dapm_widgets[] = {
                SND_SOC_DAPM_PRE_PMU),
        SND_SOC_DAPM_PGA_S("HP Amp", 1, SND_SOC_NOPM, 0, 0, rt5659_hp_event,
                SND_SOC_DAPM_PRE_PMD | SND_SOC_DAPM_POST_PMU),
-       SND_SOC_DAPM_PGA("LOUT Amp", SND_SOC_NOPM, 0, 0, NULL, 0),
+       SND_SOC_DAPM_PGA_S("LOUT Amp", 1,  RT5659_PWR_ANLG_1, RT5659_PWR_LM_BIT,
+               0,  NULL, 0),
 
        SND_SOC_DAPM_SUPPLY("Charge Pump", SND_SOC_NOPM, 0, 0,
                rt5659_charge_pump_event, SND_SOC_DAPM_PRE_PMU |
@@ -3208,6 +3209,7 @@ static const struct snd_soc_dapm_route rt5659_dapm_routes[] = {
        { "LOUT R MIX", "OUTVOL R Switch", "OUTVOL R" },
        { "LOUT Amp", NULL, "LOUT L MIX" },
        { "LOUT Amp", NULL, "LOUT R MIX" },
+       { "LOUT Amp", NULL, "Charge Pump" },
        { "LOUT Amp", NULL, "SYS CLK DET" },
        { "LOUT L Playback", "Switch", "LOUT Amp" },
        { "LOUT R Playback", "Switch", "LOUT Amp" },
index ab9e0ebff5a7ffe8c24a026441538c6bd877a733..e45b895d8279e42ea8bbac880f5be31a669f0206 100644 (file)
@@ -1639,7 +1639,8 @@ static irqreturn_t rt5663_irq(int irq, void *data)
 {
        struct rt5663_priv *rt5663 = data;
 
-       dev_dbg(rt5663->codec->dev, "%s IRQ queue work\n", __func__);
+       dev_dbg(regmap_get_device(rt5663->regmap), "%s IRQ queue work\n",
+               __func__);
 
        queue_delayed_work(system_wq, &rt5663->jack_detect_work,
                msecs_to_jiffies(250));
index dd471d2c02665631535fb446dcd5fca40e522f8e..01a50413c66f6612762791b2d1d905b077eb87a2 100644 (file)
@@ -1301,7 +1301,7 @@ static struct snd_kcontrol_new *soc_tplg_dapm_widget_denum_create(
                /* validate kcontrol */
                if (strnlen(ec->hdr.name, SNDRV_CTL_ELEM_ID_NAME_MAXLEN) ==
                            SNDRV_CTL_ELEM_ID_NAME_MAXLEN)
-                       return NULL;
+                       goto err;
 
                se = kzalloc(sizeof(*se), GFP_KERNEL);
                if (se == NULL)
@@ -1378,6 +1378,9 @@ err_se:
        for (; i >= 0; i--) {
                /* free values and texts */
                se = (struct soc_enum *)kc[i].private_value;
+               if (!se)
+                       continue;
+
                kfree(se->dobj.control.dvalues);
                for (j = 0; j < ec->items; j++)
                        kfree(se->dobj.control.dtexts[j]);
index 24b35a1fd4d67eebf65e4dc83faaaacca9d2e1fb..01cc7ba399240f69a917af73abe624f8edf5d283 100644 (file)
@@ -576,7 +576,7 @@ union bpf_attr {
  *     @map: pointer to sockmap
  *     @key: key to lookup sock in map
  *     @flags: reserved for future use
- *     Return: SK_REDIRECT
+ *     Return: SK_PASS
  *
  * int bpf_sock_map_update(skops, map, key, flags)
  *     @skops: pointer to bpf_sock_ops
@@ -787,9 +787,8 @@ struct xdp_md {
 };
 
 enum sk_action {
-       SK_ABORTED = 0,
-       SK_DROP,
-       SK_REDIRECT,
+       SK_DROP = 0,
+       SK_PASS,
 };
 
 #define BPF_TAG_SIZE   8
index 4c5a481a850c6d4490db28ae0d6448197e4b4517..d6e1c02ddcfead4532cdc73f2d81207f62a8db5f 100644 (file)
@@ -26,7 +26,7 @@ endif
 
 ifneq ($(OUTPUT),)
 # check that the output directory actually exists
-OUTDIR := $(realpath $(OUTPUT))
+OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
 $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
 endif
 
index f5c95d4f56a1747c8f5537e33a26ba4907a0e339..654efd9768fd3687924d6c2caf75a9b5425b8225 100644 (file)
@@ -1,8 +1,8 @@
 # SPDX-License-Identifier: GPL-2.0
 ifneq ($(O),)
 ifeq ($(origin O), command line)
-       ABSOLUTE_O := $(realpath $(O))
-       dummy := $(if $(ABSOLUTE_O),,$(error O=$(O) does not exist))
+       dummy := $(if $(shell test -d $(O) || echo $(O)),$(error O=$(O) does not exist),)
+       ABSOLUTE_O := $(shell cd $(O) ; pwd)
        OUTPUT := $(ABSOLUTE_O)/$(if $(subdir),$(subdir)/)
        COMMAND_O := O=$(ABSOLUTE_O)
 ifeq ($(objtree),)
@@ -13,7 +13,7 @@ endif
 
 # check that the output directory actually exists
 ifneq ($(OUTPUT),)
-OUTDIR := $(realpath $(OUTPUT))
+OUTDIR := $(shell cd $(OUTPUT) && /bin/pwd)
 $(if $(OUTDIR),, $(error output directory "$(OUTPUT)" does not exist))
 endif
 
index f65886af7c0cac60e4502e8973b4a602fe67c7b6..5bef05d6ba3935c4c288faec8c8efc83ed4a3849 100644 (file)
@@ -31,7 +31,11 @@ define RUN_TESTS
                        echo "selftests: Warning: file $$BASENAME_TEST is not executable, correct this.";\
                        echo "not ok 1..$$test_num selftests: $$BASENAME_TEST [FAIL]"; \
                else                                    \
-                       cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests:  $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
+               if [ "X$(summary)" != "X" ]; then               \
+                               cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST > /tmp/$$BASENAME_TEST 2>&1 && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests:  $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
+                       else                            \
+                               cd `dirname $$TEST` > /dev/null; (./$$BASENAME_TEST && echo "ok 1..$$test_num selftests: $$BASENAME_TEST [PASS]") || echo "not ok 1..$$test_num selftests:  $$BASENAME_TEST [FAIL]"; cd - > /dev/null;\
+                       fi;                             \
                fi;                                     \
        done;
 endef
index c727b96a59b0d009ed93246d0f624ff1bdef045c..5fa02d86b35f6c7b69ca28e8dfc27acdabd1e470 100644 (file)
         "teardown": [
             "$TC qdisc del dev $DEV1 ingress"
         ]
+    },
+    {
+        "id": "d052",
+        "name": "Add 1M filters with the same action",
+        "category": [
+            "filter",
+            "flower"
+        ],
+        "setup": [
+            "$TC qdisc add dev $DEV2 ingress",
+            "./tdc_batch.py $DEV2 $BATCH_FILE --share_action -n 1000000"
+        ],
+        "cmdUnderTest": "$TC -b $BATCH_FILE",
+        "expExitCode": "0",
+        "verifyCmd": "$TC actions list action gact",
+        "matchPattern": "action order 0: gact action drop.*index 1 ref 1000000 bind 1000000",
+        "matchCount": "1",
+        "teardown": [
+            "$TC qdisc del dev $DEV2 ingress",
+            "/bin/rm $BATCH_FILE"
+        ]
     }
-]
\ No newline at end of file
+]
index f8ccc7e0ab052a550ea00506abc3b5977a9c276a..b8462e1b74f960a837de44e5e8b75638d1fdee62 100755 (executable)
@@ -89,7 +89,7 @@ def prepare_env(cmdlist):
             exit(1)
 
 
-def test_runner(filtered_tests):
+def test_runner(filtered_tests, args):
     """
     Driver function for the unit tests.
 
@@ -106,6 +106,8 @@ def test_runner(filtered_tests):
     for tidx in testlist:
         result = True
         tresult = ""
+        if "flower" in tidx["category"] and args.device == None:
+            continue
         print("Test " + tidx["id"] + ": " + tidx["name"])
         prepare_env(tidx["setup"])
         (p, procout) = exec_cmd(tidx["cmdUnderTest"])
@@ -151,7 +153,11 @@ def ns_create():
         exec_cmd(cmd, False)
         cmd = 'ip link set $DEV0 up'
         exec_cmd(cmd, False)
-        cmd = 'ip -s $NS link set $DEV1 up'
+        cmd = 'ip -n $NS link set $DEV1 up'
+        exec_cmd(cmd, False)
+        cmd = 'ip link set $DEV2 netns $NS'
+        exec_cmd(cmd, False)
+        cmd = 'ip -n $NS link set $DEV2 up'
         exec_cmd(cmd, False)
 
 
@@ -212,7 +218,8 @@ def set_args(parser):
                         help='Execute the single test case with specified ID')
     parser.add_argument('-i', '--id', action='store_true', dest='gen_id',
                         help='Generate ID numbers for new test cases')
-    return parser
+    parser.add_argument('-d', '--device',
+                        help='Execute the test case in flower category')
     return parser
 
 
@@ -226,6 +233,8 @@ def check_default_settings(args):
 
     if args.path != None:
          NAMES['TC'] = args.path
+    if args.device != None:
+         NAMES['DEV2'] = args.device
     if not os.path.isfile(NAMES['TC']):
         print("The specified tc path " + NAMES['TC'] + " does not exist.")
         exit(1)
@@ -382,14 +391,17 @@ def set_operation_mode(args):
             if (len(alltests) == 0):
                 print("Cannot find a test case with ID matching " + target_id)
                 exit(1)
-        catresults = test_runner(alltests)
+        catresults = test_runner(alltests, args)
         print("All test results: " + "\n\n" + catresults)
     elif (len(target_category) > 0):
+        if (target_category == "flower") and args.device == None:
+            print("Please specify a NIC device (-d) to run category flower")
+            exit(1)
         if (target_category not in ucat):
             print("Specified category is not present in this file.")
             exit(1)
         else:
-            catresults = test_runner(testcases[target_category])
+            catresults = test_runner(testcases[target_category], args)
             print("Category " + target_category + "\n\n" + catresults)
 
     ns_destroy()
diff --git a/tools/testing/selftests/tc-testing/tdc_batch.py b/tools/testing/selftests/tc-testing/tdc_batch.py
new file mode 100755 (executable)
index 0000000..707c6bf
--- /dev/null
@@ -0,0 +1,62 @@
+#!/usr/bin/python3
+
+"""
+tdc_batch.py - a script to generate TC batch file
+
+Copyright (C) 2017 Chris Mi <chrism@mellanox.com>
+"""
+
+import argparse
+
+parser = argparse.ArgumentParser(description='TC batch file generator')
+parser.add_argument("device", help="device name")
+parser.add_argument("file", help="batch file name")
+parser.add_argument("-n", "--number", type=int,
+                    help="how many lines in batch file")
+parser.add_argument("-o", "--skip_sw",
+                    help="skip_sw (offload), by default skip_hw",
+                    action="store_true")
+parser.add_argument("-s", "--share_action",
+                    help="all filters share the same action",
+                    action="store_true")
+parser.add_argument("-p", "--prio",
+                    help="all filters have different prio",
+                    action="store_true")
+args = parser.parse_args()
+
+device = args.device
+file = open(args.file, 'w')
+
+number = 1
+if args.number:
+    number = args.number
+
+skip = "skip_hw"
+if args.skip_sw:
+    skip = "skip_sw"
+
+share_action = ""
+if args.share_action:
+    share_action = "index 1"
+
+prio = "prio 1"
+if args.prio:
+    prio = ""
+    if number > 0x4000:
+        number = 0x4000
+
+index = 0
+for i in range(0x100):
+    for j in range(0x100):
+        for k in range(0x100):
+            mac = ("%02x:%02x:%02x" % (i, j, k))
+            src_mac = "e4:11:00:" + mac
+            dst_mac = "e4:12:00:" + mac
+            cmd = ("filter add dev %s %s protocol ip parent ffff: flower %s "
+                   "src_mac %s dst_mac %s action drop %s" %
+                   (device, prio, skip, src_mac, dst_mac, share_action))
+            file.write("%s\n" % cmd)
+            index += 1
+            if index >= number:
+                file.close()
+                exit(0)
index c56269c7cac86d1925daa6833f0ec962467a5a69..eb188c729dd6a06d03923ecbb7163cc9b1944b4b 100644 (file)
@@ -13,6 +13,8 @@ NAMES = {
           # Name of veth devices to be created for the namespace
           'DEV0': 'v0p0',
           'DEV1': 'v0p1',
+          'DEV2': '',
+          'BATCH_FILE': './batch.txt',
           # Name of the namespace to use
           'NS': 'tcut'
         }